Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jondot/hypercontroller
A more civilized controller abstraction for TypeScript and Node.js. Hosts libraries for controllers built using hypergen
https://github.com/jondot/hypercontroller
express fastify nodejs typescript
Last synced: about 1 month ago
JSON representation
A more civilized controller abstraction for TypeScript and Node.js. Hosts libraries for controllers built using hypergen
- Host: GitHub
- URL: https://github.com/jondot/hypercontroller
- Owner: jondot
- License: mit
- Created: 2017-11-18T10:36:10.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T04:03:31.000Z (almost 2 years ago)
- Last Synced: 2024-04-13T23:47:14.439Z (8 months ago)
- Topics: express, fastify, nodejs, typescript
- Language: TypeScript
- Homepage:
- Size: 2.66 MB
- Stars: 8
- Watchers: 3
- Forks: 2
- Open Issues: 29
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
![](media/cover.png)
# Hypercontroller
✅ Structured and declarative project layout with controllers, actions, and middleware
✅ Bring your own framework: use with [Fastify](https://fastify.io) or [Express](https://github.com/expressjs/express)
✅ Automatic routing and mounting
✅ Helpers and best-practices for strong params and async promise-based flows
✅ TypeScript-first
✅ Generators driven (quickly add controllers, actions)```ts
import { Controller, get, postWithRoute, permitParams } from 'hypercontroller'
const accountParams = permitParams('account', ['name'])@Controller()
class AccountController {
@get()
index(_req, res) {
res.json({ name: 'Homer Simpson' })
}@postWithRoute('/')
async update(_req, res) {
const params = accountParams(req.body)
const record = await save(params)
res.json(record)
}
}
```## Quick Start
Install:
```
$ yarn add hypercontroller
```Set up a `server.ts` file using a framework of your choice:
```ts
import express from 'express'
import { Server, ExpressAdapter } from 'hypercontroller'
import AccountController from './controllers/account'const server = new Server(new ExpressAdapter(express))
server.mount([
new AccountController()
])const port = process.env.PORT || 5160
const createServer = () =>
server
.start()
.then(({ opts }) => console.log(`Listening on ${opts.port}`))
.then(() => server)
createServer()
```And run (here using `ts-node`):
```
$ ts-node server.ts
```## Controllers, Actions and Middleware
Hypercontroller tries to follow the same concepts as [Rails ActionController](https://edgeguides.rubyonrails.org/action_controller_overview.html).
A controller is created with the `@Controller` decorator and a plain class:
```ts
@Controller()
class AccountController {
...
```You add actions (request handlers) to controllers by marking it with an HTTP verb decorator:
```ts
import { Controller, get } from 'hypercontroller'@Controller()
class AccountController {
@get()
index(_req, res) {
res.json({ name: 'Homer Simpson' })
}
...
```In terms of routing, hypercontroller will _infer_ the route name from the decorated subject. When `index` or `Index` is used, it will use the index route `/` instead of the literal word `index`.
In any case, hypercontroller lets you specify a route explicitly with the `WithRoute` variant of the `Controller` decorator and each of the HTTP verb decorators.
```ts
@Controller()
class AccountController {
@get()
index(_req, res) {
res.json({ name: 'Homer Simpson' })
}@postWithRoute('/')
async update(_req, res) {
const params = accountParams(req.body)
const record = await save(params)
res.json(record)
}
}
```This controller will form the following routes once mounted:
```
GET /accounts
POST /accounts
```Any decorator you use accepts middleware as an array of middleware or a single instance:
```ts
@Controller(jwtAuth)
class AccountController {
@get([cacheWithEtag, compress])
index(_req, res) {
res.json({ name: 'Homer Simpson' })
}
...
```All middleware are the same ones you would originally use with Express or Fastify.
## Server and Mounting
Hypercontroller's `Server` is an entrypoint that takes controllers and understands their structure, and mount actions and middleware cleanly using your chosen web framework.
```ts
const server = new Server(new ExpressAdapter(express))
server.mount([
new AccountController()
])
```You can use either `ExpressAdapter` or `FastifyAdapter`, and give each an instance of `express` or `fastify` to work with.
Hypercontroller always lets you work with your web framework directly, and exposes the current app via `server.app`. This way you can use existing legacy code, framework-specific modules, practices, testing harnesses and more -- you take it from here.
## Strong Params
Hypercontroller makes [hyperparams](https://github.com/jondot/hyperparams) accessible for you to use in your actions if you want to implement [strong parameter](https://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters) (which you should).
You create a requirement statically:
```ts
const accountParams = permitParams('account', ['name'])
```And use it in your actions, or anywhere else you want:
```ts
@get()
index(req, res){
const params = accoutnParams(req.body)
...
}
```Hyperparams is extremely performant, and modular compared to full-fledged validation libraries.
# Contributing
Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
### Thanks:
To all [Contributors](https://github.com/jondot/hypercontroller/graphs/contributors) - you make this happen, thanks!
# Copyright
Copyright (c) 2019 [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details.