├── .babelrc ├── .gitignore ├── README.md ├── app ├── config.js ├── controllers │ └── auth.js ├── index.js ├── middleware │ ├── crosMiddleware.js │ └── pipeMiddleware.js ├── models │ └── user.js ├── routes │ ├── auth.js │ └── index.js └── utils │ └── rules.js ├── index.js └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | /dist 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # koa2-restful 2 | 3 | > Just A Simple Demo 4 | 5 | **Please go to [https://github.com/luckcoding/hotchcms](https://github.com/luckcoding/hotchcms)** 6 | 7 | 8 | ## run 9 | 10 | 1. `$ git clone https://github.com/luckcoding/koa2-restful.git` 11 | 2. `$ cd koa2-restful && npm install` 12 | 3. `$ npm install` 13 | 4. **sart mongodb** 14 | 5. `$ npm run dev ` or `$ npm start` 15 | -------------------------------------------------------------------------------- /app/config.js: -------------------------------------------------------------------------------- 1 | export const port = process.env.PORT || 3030 2 | export const mongodb = 'mongodb://localhost/koa' 3 | export const baseApi = 'koa' 4 | -------------------------------------------------------------------------------- /app/controllers/auth.js: -------------------------------------------------------------------------------- 1 | import User from '../models/user.js' 2 | import { isEmail } from '../utils/rules.js' 3 | 4 | export async function register (ctx) { 5 | // ==================== 6 | // 普通写法 : 7 | // ==================== 8 | const { email, password } = ctx.request.body 9 | const hasUser = await User.findOne({email: email}) 10 | if (hasUser) { 11 | ctx.throw(400,'已存在用户') 12 | } 13 | const user = await new User(ctx.request.body).save() 14 | ctx.body = user 15 | 16 | this.session.user = { 17 | email: user.email 18 | } 19 | 20 | // ==================== 21 | // mongooose : 22 | // ==================== 23 | // const {done,data} = await User.create(ctx.request.body) 24 | // if (done === true) { 25 | // ctx.body = data 26 | // } else { 27 | // ctx.throw(400,'已存在用户') 28 | // } 29 | 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | import Koa from 'koa' 2 | import bodyParser from 'koa-bodyparser' 3 | import logger from 'koa-logger' 4 | import convert from 'koa-convert' 5 | import session from 'koa-session' 6 | import mongoose from 'mongoose' 7 | 8 | import cros from './middleware/crosMiddleware' 9 | import pipeMiddleware from './middleware/pipeMiddleware' 10 | 11 | import routing from './routes/' 12 | import { port, mongodb } from './config' 13 | 14 | mongoose.connect(mongodb) 15 | mongoose.connection.on('error', console.error) 16 | 17 | const app = new Koa() 18 | 19 | app.jsonSpaces = 0 // 压缩json返回中的空格 20 | app.keys = ['key'] 21 | 22 | app.use(convert.compose( 23 | cros, // 跨域 24 | logger(), 25 | bodyParser(), 26 | session(app), 27 | pipeMiddleware() 28 | )) 29 | // app.use(cros) // 跨域 30 | // app.use(convert(logger())) 31 | // app.use(convert(bodyParser())) 32 | // app.use(convert(session(app))) 33 | // app.use(pipeMiddleware()) 34 | 35 | routing(app) 36 | 37 | app.listen(port, () => console.log(`✅ The server is running at http://localhost:${port}/`)) 38 | 39 | export default app -------------------------------------------------------------------------------- /app/middleware/crosMiddleware.js: -------------------------------------------------------------------------------- 1 | export default async function (ctx, next) { 2 | ctx.set('Access-Control-Allow-Origin', '*') 3 | ctx.set('Access-Control-Allow-Headers','content-type') 4 | // if (!ctx.request.header.origin.includes('http://localhost:8080')) { 5 | // return false 6 | // } 7 | await next() 8 | } -------------------------------------------------------------------------------- /app/middleware/pipeMiddleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ====================== 3 | * resCode [Number] 4 | * 200 成功 5 | * 400 用户级别错误 6 | * 500 服务器级别错误 7 | * 511 校验级别错误 8 | */ 9 | 10 | export default function pipeMiddleware() { 11 | return async (ctx, next) => { 12 | try { 13 | await next() 14 | const status = ctx.status || 404 15 | if (status === 404) { 16 | ctx.throw(400) 17 | } 18 | if (ctx.body) { 19 | ctx.body = spellRespone(status,ctx.message,ctx.body) 20 | } 21 | } catch (err) { 22 | // // koa : [err.status] 23 | // // mongod : [err.errors] 24 | const status = err.status || 400 25 | if (status === 400) { 26 | ctx.body = spellRespone(status,err.message) 27 | } else { 28 | ctx.app.emit('error', err, ctx) 29 | } 30 | 31 | } 32 | } 33 | } 34 | 35 | function spellRespone(respCode, respDesc, respBody) { 36 | // mongod validation failed callback 37 | respDesc.indexOf('validation failed') != -1 38 | ? respDesc = '数据格式非法' 39 | : respDesc 40 | 41 | // callback 42 | return { 43 | respHead: { 44 | respCode, 45 | respDesc 46 | }, 47 | respBody 48 | } 49 | } -------------------------------------------------------------------------------- /app/models/user.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | import validate from 'mongoose-validator' 3 | const Schema = mongoose.Schema 4 | 5 | const userSchema = new Schema({ 6 | email: { 7 | type: String, 8 | lowercase: true, 9 | required: true, 10 | validate: validate({ 11 | validator: 'isEmail', 12 | message: '邮箱格式错误', 13 | }) 14 | }, 15 | name: { type: String, minlength: 10 }, 16 | password: { type: String, required: true }, 17 | registed: { type: Date, default: Date.now }, 18 | regdevice: { type: String }, 19 | regcity: { type: String, required: true, } 20 | }) 21 | 22 | /** 23 | * todo 24 | */ 25 | 26 | // find by id 27 | userSchema.statics.findbyid = async function (_id) { 28 | const exists = await this.findById(_id) 29 | if (exists) { 30 | return { 31 | done: true, 32 | data: exists 33 | } 34 | } 35 | } 36 | 37 | // create 38 | userSchema.statics.create = async function (obj) { 39 | const user = new this(obj) 40 | 41 | const exists = await this.findOne({email: user.email}) 42 | if (exists) { 43 | return { 44 | done: false, 45 | } 46 | } 47 | const back = await user.save() 48 | if (back) { 49 | return { 50 | done: true, 51 | data: back 52 | } 53 | } 54 | } 55 | 56 | export default mongoose.model('User', userSchema) -------------------------------------------------------------------------------- /app/routes/auth.js: -------------------------------------------------------------------------------- 1 | import Router from 'koa-router' 2 | 3 | import { baseApi } from '../config' 4 | import { register } from '../controllers/auth.js' 5 | 6 | const api = 'auth' 7 | 8 | const router = new Router() 9 | 10 | router.prefix(`/${baseApi}/${api}`) 11 | 12 | router.post('/register', register) 13 | 14 | export default router -------------------------------------------------------------------------------- /app/routes/index.js: -------------------------------------------------------------------------------- 1 | import auth from './auth' 2 | 3 | const routes = [auth] 4 | 5 | export default function (app) { 6 | routes.forEach((route) => { 7 | app 8 | .use(route.routes()) 9 | .use(route.allowedMethods({ 10 | throw: true 11 | })) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /app/utils/rules.js: -------------------------------------------------------------------------------- 1 | export function isEmail(email) { 2 | return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(email) 3 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-register'); 4 | require("babel-polyfill"); 5 | 6 | require("./app/index.js") -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa2-shopping", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "dev": "nodemon index.js" 9 | }, 10 | "author": "Luckcoding", 11 | "license": "ISC", 12 | "dependencies": { 13 | "babel-polyfill": "^6.7.4", 14 | "babel-preset-es2015": "^6.6.0", 15 | "babel-preset-stage-0": "^6.5.0", 16 | "babel-register": "^6.7.2", 17 | "koa": "^2.0.0-alpha.3", 18 | "koa-bodyparser": "^3.0.0", 19 | "koa-convert": "^1.2.0", 20 | "koa-logger": "^2.0.0", 21 | "koa-router": "^7.0.0", 22 | "koa-session": "^3.3.1", 23 | "mongoose": "^4.4.12", 24 | "mongoose-validator": "^1.2.4", 25 | "nodemon": "^1.9.1" 26 | } 27 | } 28 | --------------------------------------------------------------------------------