A practical REST API framework
Paquet is a REST API framework with a specific mission: To get a REST API set up as quickly and effortlessly as possible, with a full suite of production-ready features. Paquet was written so that you could use one line and an object structure to spin up a REST API - written entirely in ES6.
Under the hood, Paquet is simply leveraging Express and Koa to give you two basic options - ES6 with generator functions and ES5.
Install
Examples
API
Notes
Contributors
Paquet is for:
- front-end developers who want to get started quickly with a basic API for their single-page React or Angular app to consume
- anyone who wants to use ES5 and ES6 syntax without switching frameworks
- human beings just starting out with Node.js who want a more opinionated framework
- experienced developers who want object-based mapping between routes and controllers
Paquet is not claiming to be something new, it simply makes what's out there more accessible and intuitive to get started with, by unifying their APIs. Instead of worrying about whether you've installed and loaded all the correct middleware, Paquet ships with some basic features out of the box, such as:
- Body parsing
- Cookie parsing
- Sessions support
- URL Querystring parsing
- Serving static files
Plus, you can still load the Express/Koa middleware you know and love!
When you create an API using var paquet = new Paquet(mode).start(options)
, the underlyng Koa/Express app will always be accessible as paquet.instance.app
.
npm install paquet -g
npm install paquet --save
paquet --public ./public --middleware ./middleware.js
This would start an API on the default port 3000 and point the static file server at ./public (relative to your project's root) and load middleware from the file middleware.js
in your project's root.
To specify routes
, use a paquet.json
in your project's root. Here's an example paquet.json.
import Paquet from 'paquet'
const paquet = new Paquet('es6')
paquet.start({
port: 9090, // optional, defaults to 3000
name: 'helloworld', // optional
public: './test/public', // optional, required if no routes set
session: { // optional
name: 'paquet',
keys: ['key1', 'key2']
},
middleware: { // optional
'/*': function * (next) {
if (this.path === '/favicon.ico') return;
var n = this.session.views || 0;
this.session.views = ++n;
yield next
},
'/docs': `./test/docs`
},
routes: { // optional, required if no public folder set
get: {
'/file/:id': function * () {
this.response.serveFile(`./test/files/${this.params.id}`)
},
'/post/:id': [
function * (next) {
yield next
},
function * () {
this.response.success({ title: "My post", author: "random guy" })
}
],
'/error': function * () {
this.response.error(404, "uh oh! an error!")
}
},
post: {
'/cookie/:id': function * () {
this.cookies.set(this.params.id, 'value')
this.response.success({ id: this.params.id })
}
}
}
})
That's it - all your declaraion upon instantiation. Of course, you're still able to do this:
paquet.route({
get: {
'/new-route': function * () {
this.response.success("A new route for my new app")
}
}
})
after the fact.
var Paquet = require('paquet')
var paquet = new Paquet()
paquet.start({
port: 9090,
name: 'helloworld',
public: './test/public',
session: {
name: 'paquet',
keys: ['key1', 'key2']
},
middleware: {
'/*': function () {
if (this.path === '/favicon.ico') return;
var n = this.session.views || 0;
this.session.views = ++n;
},
'/docs': './test/docs'
},
routes: { // syntax is identical. except for the absence of generators
get: {
'/file/:id': function () {
this.response.serveFile('./test/files/' + this.params.id)
},
'/post/:id': [
function (req, res, next) {
return next() // You can also return a promise :)
},
function () {
this.response.success({ title: "My post", author: "random guy" })
}
],
'/error': function() {
this.response.error(404, "uh oh! an error!")
}
},
post: {
'/cookie/:id': function () {
this.cookies.set(this.params.id, 'value')
this.response.success({ id: this.params.id })
}
}
}
})
And, you're still able to do this:
paquet.route({
get: {
'/new-route': function () {
this.response.success("A new route for my new app")
}
}
})
after the fact, as well.
Creates a new instance of class Paquet
.
mode
Defaults to es5
. When es6
, Paquet will only accept generator functions as middleware and routes.
Starts a Paquet API with the following available options:
name: String
, requiredport: Number
, optional. Defaults to 3000public: String
, optional. Sets a folder as a static file servermiddleware: Object
, optional. Inserts middleware before the routes
options.middleware
object has the following structure:
{
'/:path': (String|Array|Function),
...
}
When a String is passed, if it is a valid path, this path will also be set as a static file server, accessible at /:path
.
When an Array of functions is passed, these will be injected as cascading middleware into the stack.
When a single Function is passed, the function will be injected into the stack.
routes: Object
, required. Sets the routes for your app
options.routes
object has the following structure:
{
'(get|post|put|patch|delete)': {
'/:path': (Array|Function),
...
},
...
}
Helper method - behaves identically to options.routes
, allowing you to add new routes later on in your code.
This project is brand new, so there will inevitably be some bugs. Please file an issue with this repo and I'll get to it as soon as I can.
Coming soon:
- Plugins
- ES7 async/await support via Koa 2