Skip to content

Commit

Permalink
Merge pull request #2 from jeffijoe/next
Browse files Browse the repository at this point in the history
v1
  • Loading branch information
jeffijoe committed Nov 11, 2017
2 parents f419957 + 11a64ae commit 39b4b86
Show file tree
Hide file tree
Showing 37 changed files with 5,571 additions and 341 deletions.
4 changes: 0 additions & 4 deletions .codeclimate.yml

This file was deleted.

12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
1 change: 0 additions & 1 deletion .eslintignore

This file was deleted.

5 changes: 0 additions & 5 deletions .eslintrc

This file was deleted.

10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
node_modules
npm-debug.log
coverage
yarn-error.log
coverage
.nyc_output
lib
.test-out
.DS_Store
.idea/workspace.xml
.sublime-workspace
.npmrc
6 changes: 5 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
examples
test
coverage
.test-out
src
**/__tests__/**
**/__helpers__/**
24 changes: 22 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
# Oh yeah!
language: node_js
cache:
directories:
- node_modules
notifications:
email: false

# Add additional versions here as appropriate.
node_js:
- "stable"
- "8"
- "7"
- "6"

# Lint errors should trigger a failure.
before_script: npm run lint
before_script:
- npm run lint
- npm run build

# Runs the coverage script (which runs the tests)
script: npm run coveralls

# Code coverage
after_success:
npm run coveralls
- npm run semantic-release

branches:
except:
- /^v\d+\.\d+\.\d+$/
31 changes: 31 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/lib/index.js",
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
},
{
"type": "node",
"request": "launch",
"name": "Jest Tests",
"program": "${workspaceRoot}/node_modules/jest/bin/jest.js",
"protocol": "inspector",
"args": [
"-i"
],
"internalConsoleOptions": "openOnSessionStart",
"outFiles": [
"${workspaceRoot}/lib/**/*"
],
"env": {
"NODE_ENV": "test"
}
}
]
}
15 changes: 15 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"coverage": true,
".idea": true,
"lib": true,
"**/*.sublime-*": true,
"node_modules": true
}
}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog

## 1.0.0

* Rewritten in TypeScript.
* Added `awilix-router-core` binding for `koa-router`.

## 0.1.1

* Updated packages.

## 0.1.0

* Initial release.
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# The MIT License (MIT)

Copyright (c) Jeff Hansen 2016 to present.
Copyright (c) Jeff Hansen 2017 to present.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
129 changes: 117 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@
[![devDependency Status](https://david-dm.org/jeffijoe/awilix-koa/dev-status.svg)](https://david-dm.org/jeffijoe/awilix-koa#info=devDependencies)
[![Build Status](https://travis-ci.org/jeffijoe/awilix-koa.svg?branch=master)](https://travis-ci.org/jeffijoe/awilix-koa)
[![Coverage Status](https://coveralls.io/repos/github/jeffijoe/awilix-koa/badge.svg?branch=master)](https://coveralls.io/github/jeffijoe/awilix-koa?branch=master)
[![Code Climate](https://codeclimate.com/github/jeffijoe/awilix-koa/badges/gpa.svg)](https://codeclimate.com/github/jeffijoe/awilix-koa)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
![Typings Included](https://img.shields.io/badge/typings-included-brightgreen.svg)

Awilix 2 helpers and scope-instantiating middleware for **Koa 2**. :rocket:
Awilix helpers, router and scope-instantiating middleware for **Koa**. 🐨

> **NEW IN V1**: [first-class router support with auto-loading!](#awesome-usage) 🚀
# Table of Contents

* [Installation](#installation)
* [Basic Usage](#basic-usage)
* [Awesome Usage](#awesome-usage)
* [Why do I need it?](#why-do-i-need-it)
* [Manual](#manual)
* [Using awilix-koa](#using-awilix-koa)
* [API](#api)
* [Contributing](#contributing)
* [npm run scripts](#npm-run-scripts)
* [Author](#author)

# Installation

Expand All @@ -18,7 +32,7 @@ npm install --save awilix-koa

_Requires Node v6 or above_

# Usage
# Basic Usage

Add the middleware to your Koa app.

Expand Down Expand Up @@ -50,7 +64,6 @@ app.use((ctx, next) => {
Then in your route handlers...

```js
// There's a makeClassInvoker for classes..
const { makeInvoker } = require('awilix-koa')

function makeAPI ({ todosService }) {
Expand All @@ -70,6 +83,86 @@ const api = makeInvoker(makeAPI)
router.get('/todos', api('find'))
```

# Awesome Usage

**As of `awilix-koa@1.0.0`**, we ship with `koa-router` bindings for [`awilix-router-core`][awilix-router-core]!
This is cool because now your routing setup can be streamlined with first-class Awilix support!

The Awilix-based router comes in 2 flavors: **a builder** and **ESNext decorators**.

**`routes/todos-api.js`** - demos the builder pattern

```js
import bodyParser from 'koa-bodyparser'
import { authenticate } from './your-auth-middleware'
import { createController } from 'awilix-koa' // or `awilix-router-core`

const API = ({ todoService }) => ({
getTodo: async (ctx) => (ctx.body = await todoService.get(ctx.params.id)),
createTodo: async (ctx) => (ctx.body = await todoService.create(ctx.request.body))
})

export default createController(API)
.prefix('/todos') // Prefix all endpoints with `/todo`
.before([authenticate()]) // run authentication for all endpoints
.get('/:id', 'getTodo') // Maps `GET /todos/:id` to the `getTodo` function on the returned object from `API`
.post('', 'createTodo', { // Maps `POST /todos` to the `createTodo` function on the returned object from `API`
before: [bodyParser()] // Runs the bodyParser just for this endpoint
})
```

**`routes/users-api.js`** - demos the decorator pattern

```js
import bodyParser from 'koa-bodyparser'
import { authenticate } from './your-auth-middleware'
import { route, GET, POST, before } from 'awilix-koa' // or `awilix-router-core`

@route('/users')
export default class UserAPI {
constructor ({ userService }) {
this.userService = userService
}

@route('/:id')
@GET()
@before([authenticate()])
async getUser (ctx) {
ctx.body = await this.userService.get(ctx.params.id)
}

@POST()
@before([bodyParser()])
async createUser (ctx) {
ctx.body = await this.userService.create(ctx.request.body)
}
}
```

**`server.js`**

```js
import Koa from 'koa'
import { createContainer } from 'awilix'
import { loadControllers, scopePerRequest } from 'awilix-koa'

const app = new Koa()
const container = createContainer()
.registerClass({
userService: /*...*/,
todoService: /*...*/
})
// Loads all controllers in the `routes` folder
// relative to the current working directory.
// This is a glob pattern.
app.use(scopePerRequest(container))
app.use(loadControllers('routes/*.js', { cwd: __dirname }))

app.listen(3000)
```

Please see the [`awilix-router-core`][awilix-router-core] docs for information about the full API.

# Why do I need it?

You can certainly use Awilix with Koa without this library, but follow along and you might see why it's useful.
Expand Down Expand Up @@ -199,10 +292,10 @@ export default function (router) {
In our route handler, do the following:

```js
import { makeClassInvoker } from 'awilix-koa'
import { makeInvoker } from 'awilix-koa'

export default function (router) {
const api = makeClassInvoker(TodoAPI)
const api = makeInvoker(TodoAPI)
router.get('/todos', api('getTodos'))
}
```
Expand Down Expand Up @@ -237,7 +330,7 @@ app.use((ctx, next) => {
})
```

Now **that** is way simpler! If you are more of a factory-function aficionado like myself, you can use `makeInvoker` in place of `makeClassInvoker`:
Now **that** is way simpler!

```js
import { makeInvoker } from 'awilix-koa'
Expand All @@ -258,17 +351,29 @@ export default function (router) {

That concludes the tutorial! Hope you find it useful, I know I have.

# API

The package exports everything from `awilix-router-core` as well as the following **Koa middleware factories**:

* `scopePerRequest(container)`: creates a scope per request.
* `controller(decoratedClassOrController)`: registers routes and delegates to Koa Router.
* `loadControllers(pattern, opts)`: loads files matching a glob pattern and registers their exports as controllers.
* `makeInvoker(functionOrClass, opts)(methodName)`: using `isClass`, calls either `makeFunctionInvoker` or `makeClassInvoker`.
* `makeClassInvoker(Class, opts)(methodName)`: resolves & calls `methodName` on the resolved instance, passing it `ctx` and `next`.
* `makeFunctionInvoker(function, opts)(methodName)`: resolves & calls `methodName` on the resolved instance, passing it `ctx` and `next`.
* `makeResolverInvoker(resolver, opts)`: used by the other invokers, exported for convenience.

# Contributing

## `npm run` scripts

* `npm run test`: Runs tests once
* `npm run test-watch`: Runs tests in watch-mode
* `npm run lint`: Lints the code once
* `npm run lint-watch`: Lints the code in watch-mode
* `npm run lint`: Lints + formats the code once
* `npm run cover`: Runs code coverage using `istanbul`
* `npm run coveralls`: Used by coveralls

# Author

Jeff Hansen - [@Jeffijoe](https://twitter.com/Jeffijoe)


[awilix-router-core]: https://github.com/jeffijoe/awilix-router-core
18 changes: 18 additions & 0 deletions __fixtures__/1/js-class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { route, GET, before, after } from 'awilix-router-core'

@route('/js')
@before((ctx, next) => ctx.set('x-root-before', 'js') || next())
@after(ctx => ctx.set('x-root-after', ctx.body.message))
export default class JsClass {
constructor({ service }) {
this.service = service
}

@route('/get')
@GET()
func(ctx, next) {
ctx.status = 200
ctx.body = this.service.get('js')
return next()
}
}
3 changes: 3 additions & 0 deletions __fixtures__/1/no-decorators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class NotGonnaGetRegistered {
func(ctx, next) {}
}
Loading

0 comments on commit 39b4b86

Please sign in to comment.