From c76317f098ea0abeb0e940b602399ed1c46ecd35 Mon Sep 17 00:00:00 2001 From: popomore Date: Tue, 7 Feb 2017 23:26:05 +0800 Subject: [PATCH 1/4] feat: async/await Example Closes https://github.com/eggjs/egg/issues/276 --- hackernews-async/.autod.conf.js | 27 +++ hackernews-async/.eslintrc | 5 + hackernews-async/README.md | 26 +++ hackernews-async/app/controller/news.js | 29 +++ hackernews-async/app/extend/filter.js | 7 + hackernews-async/app/public/css/news.css | 203 ++++++++++++++++++ hackernews-async/app/public/favicon.png | Bin 0 -> 3113 bytes hackernews-async/app/router.js | 8 + hackernews-async/app/service/HackerNews.js | 70 ++++++ hackernews-async/app/view/layout/layout.tpl | 22 ++ hackernews-async/app/view/news/detail.tpl | 27 +++ hackernews-async/app/view/news/item.tpl | 16 ++ hackernews-async/app/view/news/list.tpl | 17 ++ hackernews-async/app/view/news/user.tpl | 23 ++ hackernews-async/appveyor.yml | 14 ++ hackernews-async/config/config.default.js | 22 ++ hackernews-async/config/plugin.js | 9 + hackernews-async/package.json | 33 +++ .../test/app/controller/news.test.js | 39 ++++ .../test/app/service/HackerNews.test.js | 28 +++ 20 files changed, 625 insertions(+) create mode 100644 hackernews-async/.autod.conf.js create mode 100644 hackernews-async/.eslintrc create mode 100644 hackernews-async/README.md create mode 100644 hackernews-async/app/controller/news.js create mode 100644 hackernews-async/app/extend/filter.js create mode 100644 hackernews-async/app/public/css/news.css create mode 100644 hackernews-async/app/public/favicon.png create mode 100644 hackernews-async/app/router.js create mode 100644 hackernews-async/app/service/HackerNews.js create mode 100644 hackernews-async/app/view/layout/layout.tpl create mode 100644 hackernews-async/app/view/news/detail.tpl create mode 100644 hackernews-async/app/view/news/item.tpl create mode 100644 hackernews-async/app/view/news/list.tpl create mode 100644 hackernews-async/app/view/news/user.tpl create mode 100644 hackernews-async/appveyor.yml create mode 100644 hackernews-async/config/config.default.js create mode 100644 hackernews-async/config/plugin.js create mode 100644 hackernews-async/package.json create mode 100644 hackernews-async/test/app/controller/news.test.js create mode 100644 hackernews-async/test/app/service/HackerNews.test.js diff --git a/hackernews-async/.autod.conf.js b/hackernews-async/.autod.conf.js new file mode 100644 index 0000000..0568172 --- /dev/null +++ b/hackernews-async/.autod.conf.js @@ -0,0 +1,27 @@ +'ues strict'; + +module.exports = { + write: true, + plugin: 'autod-egg', + prefix: '^', + devprefix: '^', + registry: 'https://r.cnpmjs.org', + exclude: [ + 'test/fixtures', + ], + dep: [ + 'egg', + ], + devdep: [ + 'autod', + 'autod-egg', + 'eslint', + 'eslint-config-egg', + 'egg-bin', + ], + keep: [ + ], + semver: [ + ], + test: 'scripts', +}; diff --git a/hackernews-async/.eslintrc b/hackernews-async/.eslintrc new file mode 100644 index 0000000..62b2994 --- /dev/null +++ b/hackernews-async/.eslintrc @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "ecmaVersion": 2017 + } +} diff --git a/hackernews-async/README.md b/hackernews-async/README.md new file mode 100644 index 0000000..3d3bb17 --- /dev/null +++ b/hackernews-async/README.md @@ -0,0 +1,26 @@ +# egg-example-hackernews-async + +[Hacker News](https://news.ycombinator.com/) showcase using async/await for egg + +## QuickStart + +### Development +```shell +$ npm install +$ npm run dev +$ open http://localhost:7001/ +``` + +### Deploy + +Use `EGG_SERVER_ENV=prod` to enable prod mode + +```shell +$ EGG_SERVER_ENV=prod npm start +``` + +### npm scripts + +- Use `npm run autod` to auto detect dependencies upgrade +- Use `npm run lint` to check code style +- Use `npm test` to run unit test diff --git a/hackernews-async/app/controller/news.js b/hackernews-async/app/controller/news.js new file mode 100644 index 0000000..7f27ef5 --- /dev/null +++ b/hackernews-async/app/controller/news.js @@ -0,0 +1,29 @@ +'use strict'; + +module.exports = app => { + return class NewsController extends app.Controller { + async list() { + const pageSize = this.app.config.news.pageSize; + const page = parseInt(this.query.page) || 1; + + const idList = await this.service.hackerNews.getTopStories(page); + // get itemInfo parallel + const newsList = await idList.map(id => this.service.hackerNews.getItem(id)); + await this.render('news/list.tpl', { list: newsList, page, pageSize }); + } + + async detail() { + const id = this.params.id; + const newsInfo = await this.service.hackerNews.getItem(id); + // get comment parallel + const commentList = await newsInfo.kids.map(id => this.service.hackerNews.getItem(id)); + await this.render('news/detail.tpl', { item: newsInfo, comments: commentList }); + } + + async user() { + const id = this.params.id; + const userInfo = await this.service.hackerNews.getUser(id); + await this.render('news/user.tpl', { user: userInfo }); + } + }; +}; diff --git a/hackernews-async/app/extend/filter.js b/hackernews-async/app/extend/filter.js new file mode 100644 index 0000000..623379e --- /dev/null +++ b/hackernews-async/app/extend/filter.js @@ -0,0 +1,7 @@ +'use strict'; + +const moment = require('moment'); + +exports.relativeTime = time => moment(new Date(time * 1000)).fromNow(); + +exports.domain = url => url && url.split('/')[2]; diff --git a/hackernews-async/app/public/css/news.css b/hackernews-async/app/public/css/news.css new file mode 100644 index 0000000..b922c98 --- /dev/null +++ b/hackernews-async/app/public/css/news.css @@ -0,0 +1,203 @@ +body, +html { + font-family: Verdana; + font-size: 13px; + height: 100% +} +ul { + list-style-type: none; + padding: 0; + margin: 0 +} +a { + color: #000; + cursor: pointer; + text-decoration: none +} +#wrapper { + background-color: #f6f6ef; + width: 85%; + min-height: 80px; + margin: 0 auto +} +#header, +#wrapper { + position: relative +} +#header { + background-color: #f60; + height: 24px +} +#header h1 { + font-weight: 700; + font-size: 13px; + display: inline-block; + vertical-align: middle; + margin: 0 +} +#header .source { + color: #fff; + font-size: 11px; + position: absolute; + top: 4px; + right: 4px +} +#header .source a { + color: #fff +} +#header .source a:hover { + text-decoration: underline +} +#yc { + border: 1px solid #fff; + margin: 2px; + display: inline-block +} +#yc, +#yc img { + vertical-align: middle +} +.view { + position: absolute; + background-color: #f6f6ef; + width: 100%; + -webkit-transition: opacity .2s ease; + transition: opacity .2s ease; + box-sizing: border-box; + padding: 8px 20px +} +.view.v-enter, +.view.v-leave { + opacity: 0 +} +@media screen and (max-width: 700px) { + body, + html { + margin: 0 + } + #wrapper { + width: 100% + } +} +.news-view { + padding-left: 5px; + padding-right: 15px +} +.news-view.loading:before { + content: "Loading..."; + position: absolute; + top: 16px; + left: 20px +} +.news-view .nav { + padding: 10px 10px 10px 40px; + margin-top: 10px; + border-top: 2px solid #f60 +} +.news-view .nav a { + margin-right: 10px +} +.news-view .nav a:hover { + text-decoration: underline +} +.item { + padding: 2px 0 2px 40px; + position: relative; + -webkit-transition: background-color .2s ease; + transition: background-color .2s ease +} +.item p { + margin: 2px 0 +} +.item .index, +.item .title:visited { + color: #828282 +} +.item .index { + position: absolute; + width: 30px; + text-align: right; + left: 0; + top: 4px +} +.item .domain, +.item .subtext { + font-size: 11px; + color: #828282 +} +.item .domain a, +.item .subtext a { + color: #828282 +} +.item .subtext a:hover { + text-decoration: underline +} +.item-view .item { + padding-left: 0; + margin-bottom: 30px +} +.item-view .item .index { + display: none +} +.item-view .poll-options { + margin-left: 30px; + margin-bottom: 40px +} +.item-view .poll-options li { + margin: 12px 0 +} +.item-view .poll-options p { + margin: 8px 0 +} +.item-view .poll-options .subtext { + color: #828282; + font-size: 11px +} +.item-view .itemtext { + color: #828282; + margin-top: 0; + margin-bottom: 30px +} +.item-view .itemtext p { + margin: 10px 0 +} +.comhead { + font-size: 11px; + margin-bottom: 8px +} +.comhead, +.comhead a { + color: #828282 +} +.comhead a:hover { + text-decoration: underline +} +.comhead .toggle { + margin-right: 4px +} +.comment-content { + margin: 0 0 16px 24px; + word-wrap: break-word +} +.comment-content code { + white-space: pre-wrap +} +.child-comments { + margin: 8px 0 8px 22px +} +.user-view { + color: #828282 +} +.user-view li { + margin: 5px 0 +} +.user-view .label { + display: inline-block; + min-width: 60px +} +.user-view .about { + margin-top: 1em +} +.user-view .links a { + text-decoration: underline +} \ No newline at end of file diff --git a/hackernews-async/app/public/favicon.png b/hackernews-async/app/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..41d69cdc414faa424c7a12c783f8009f0fec2da8 GIT binary patch literal 3113 zcmZ8jZBLU|7;d3ZWE2q)Xlb$VFc1-~76A)Ipyf@V2$b@sWrea8kctAcQoxuknVnejbDQUT)ar7-EP*Yj9 z9H_(DMlcW`6@8>mG&rnVFzRn`q^8zL=rs2(-rBaTNlMDPCDm9~AePJ|Ko?7@A{E zi`C}YRTxiyj4oe-4u&7yh@1Y;d|MMjwuPXX>js!@iJ}f&J>-ganq^!Zo#2|*)Co8Wo4?lI0osj= zaM<92=EpbkU_HCeAAbCa1YcZx@U2+IhoP&|9t;8;Q%gBsEUV$`Un zX)cC8oZ%~E)%zPQ0VWlg-#?mU*#!Bk?8ZXBszxYP4ply8^x>Dz`@hNjt~dP=?ra0X zqcyf)9W>ZnF2McW`ABT=sr|YMgVobCRWOx_ki;u;oCVC?EUHVc`z?4fPt%C-WGejpaloW zLt-{;J`lhYckg2mx5hyMv*YCp0Us*>a8H_;Pt;)+&r>N{*x};*)lGh7!YU^)JIB|X zpavi%_6g6~WVsRMJCJqeho_M10(@@X5p!&%z;w;31jix)o-EeN264`SPO1i~hAk)! zIjpd_XMn%(8muOb$6K|??!j6X2k=7naH|0OmD||9KDm7z+Ff5CWzBUkO@hPW?ohw_ zK6w%>PN6>5!Q-yQ2jWntAz>~)?-GdF;LcsGb}%<4xWMZ*ntr+XimCzJS6+M$0hVr< z69Im*bo3RC&Dq!pIu7Ypj?#lp&C<#bEyNI?LmAu%3Dr}JIcHS z#EuowINstc%TqhlcIu~QiVE>{WoNuk-#f%2Cyc36D-*y*-74cv0wmQem)CaSKyhp8 z7Fy?Y)&nTrFsUku59Yd`{2r`-+n;J7iR;|H2=neu-4|m+EsGm+rAbV+&OaZ(ZRKk2f9-tbOvUg18ZpUS z;nV?v&x>{-2+EzVJ~YD{N-!&G4eB6-*E+y-h9GQYV4F8=jo3O*>(&Kc2!oJlX}ccG rwB+~k1jb$SF@uF0YU2~ecQe815J!PJps)e_<2Uqn2K+EP_$~Pl&{xhR literal 0 HcmV?d00001 diff --git a/hackernews-async/app/router.js b/hackernews-async/app/router.js new file mode 100644 index 0000000..ba3dc32 --- /dev/null +++ b/hackernews-async/app/router.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = app => { + app.redirect('/', '/news'); + app.get('/news', 'news.list'); + app.get('/news/item/:id', 'news.detail'); + app.get('/news/user/:id', 'news.user'); +}; diff --git a/hackernews-async/app/service/HackerNews.js b/hackernews-async/app/service/HackerNews.js new file mode 100644 index 0000000..7789d8b --- /dev/null +++ b/hackernews-async/app/service/HackerNews.js @@ -0,0 +1,70 @@ +'use strict'; + +module.exports = app => { + /** + * HackerNews Api Service + */ + class HackerNews extends app.Service { + constructor(ctx) { + super(ctx); + this.config = this.ctx.app.config.news; + this.serverUrl = this.config.serverUrl; + this.pageSize = this.config.pageSize; + } + + /** + * request hacker-news api + * @param {String} api - Api name + * @param {Object} [opts] - urllib options + * @return {Promise} response.data + */ + async request(api, opts) { + const options = Object.assign({ + dataType: 'json', + }, opts); + + const result = await this.ctx.curl(`${this.serverUrl}/${api}`, options); + return result.data; + } + + /** + * get top story ids + * @param {Number} [page] - page number, 1-base + * @param {Number} [pageSize] - page count + * @return {Promise} id list + */ + async getTopStories(page, pageSize) { + page = page || 1; + pageSize = pageSize || this.pageSize; + + const result = await this.request('topstories.json', { + data: { + orderBy: '"$key"', + startAt: `"${pageSize * (page - 1)}"`, + endAt: `"${pageSize * page - 1}"`, + }, + }); + return Object.keys(result).map(key => result[key]); + } + + /** + * query item + * @param {Number} id - itemId + * @return {Promise} item info + */ + async getItem(id) { + return await this.request(`item/${id}.json`); + } + + /** + * get user info + * @param {Number} id - userId + * @return {Promise} user info + */ + async getUser(id) { + return await this.request(`user/${id}.json`); + } + } + + return HackerNews; +}; diff --git a/hackernews-async/app/view/layout/layout.tpl b/hackernews-async/app/view/layout/layout.tpl new file mode 100644 index 0000000..d9fcc3d --- /dev/null +++ b/hackernews-async/app/view/layout/layout.tpl @@ -0,0 +1,22 @@ + + + + + + + + {% block title %}egg - HackerNews{% endblock %} + + +
+ + {% block content %}{% endblock %} +
+ + diff --git a/hackernews-async/app/view/news/detail.tpl b/hackernews-async/app/view/news/detail.tpl new file mode 100644 index 0000000..37a824b --- /dev/null +++ b/hackernews-async/app/view/news/detail.tpl @@ -0,0 +1,27 @@ +{% extends "../layout/layout.tpl" %} + +{% block content %} +
+ + {% include "./item.tpl" %} + + {% if comments.length > 0%} +
    +
    + [-] + {{ comment.by }} + {{ comment.time | relativeTime }} +
    +
    + {{ helper.shtml(comment.text) }} +
    + + {% endfor %} +
+ {% else %} +

No comments yet.

+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/hackernews-async/app/view/news/item.tpl b/hackernews-async/app/view/news/item.tpl new file mode 100644 index 0000000..0f42cd0 --- /dev/null +++ b/hackernews-async/app/view/news/item.tpl @@ -0,0 +1,16 @@ +
+ {{ index }}. +

+ {{ helper.shtml(item.title) }} + ({{ item.url | domain }}) +

+

+ + {{ item.score }} points by {{ item.by }} + + {{ item.time | relativeTime }} + + | {{ item.descendants }} comments + +

+
\ No newline at end of file diff --git a/hackernews-async/app/view/news/list.tpl b/hackernews-async/app/view/news/list.tpl new file mode 100644 index 0000000..e6c2500 --- /dev/null +++ b/hackernews-async/app/view/news/list.tpl @@ -0,0 +1,17 @@ +{% extends "../layout/layout.tpl" %} + +{% block content %} +
+ {% for item in list %} + {% set index = ((page-1) * pageSize + loop.index) %} + {% include "./item.tpl" %} + {% endfor %} + + +
+{% endblock %} \ No newline at end of file diff --git a/hackernews-async/app/view/news/user.tpl b/hackernews-async/app/view/news/user.tpl new file mode 100644 index 0000000..fc9c0f5 --- /dev/null +++ b/hackernews-async/app/view/news/user.tpl @@ -0,0 +1,23 @@ +{% extends "../layout/layout.tpl" %} +{% block title %} + Profile: {{ user.id }} | egg - HackerNews +{% endblock %} +{% block content %} +
+
    +
  • user: {{ user.id }}
  • +
  • created: {{ user.created | relativeTime }}
  • +
  • karma: {{ user.karma }}
  • +
  • + about: +
    + {{ helper.shtml(user.about) }} +
    +
  • +
+ +
+{% endblock %} \ No newline at end of file diff --git a/hackernews-async/appveyor.yml b/hackernews-async/appveyor.yml new file mode 100644 index 0000000..7f70c1b --- /dev/null +++ b/hackernews-async/appveyor.yml @@ -0,0 +1,14 @@ +environment: + matrix: + - nodejs_version: '4' + +install: + - ps: Install-Product node $env:nodejs_version + - npm i npminstall && node_modules\.bin\npminstall + +test_script: + - node --version + - npm --version + - npm run ci + +build: off diff --git a/hackernews-async/config/config.default.js b/hackernews-async/config/config.default.js new file mode 100644 index 0000000..5b3b3d8 --- /dev/null +++ b/hackernews-async/config/config.default.js @@ -0,0 +1,22 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +module.exports = appInfo => { + const config = {}; + + // should change to your own + config.keys = appInfo.name + '123456'; + + config.siteFile = { + '/favicon.ico': fs.readFileSync(path.join(appInfo.baseDir, 'app/public/favicon.png')), + }; + + config.news = { + pageSize: 30, + serverUrl: 'https://hacker-news.firebaseio.com/v0', + }; + + return config; +}; diff --git a/hackernews-async/config/plugin.js b/hackernews-async/config/plugin.js new file mode 100644 index 0000000..2fdb00f --- /dev/null +++ b/hackernews-async/config/plugin.js @@ -0,0 +1,9 @@ +'use strict'; + +exports.static = true; + +exports.view = { + enable: true, + package: 'egg-view-nunjucks', +}; + diff --git a/hackernews-async/package.json b/hackernews-async/package.json new file mode 100644 index 0000000..4e1ea70 --- /dev/null +++ b/hackernews-async/package.json @@ -0,0 +1,33 @@ +{ + "name": "egg-example-hackernews-async", + "version": "1.0.0", + "description": "hackernews showcase using async/await for egg", + "private": true, + "dependencies": { + "egg": "^0.11.0", + "egg-view-nunjucks": "^1.0.0", + "moment": "^2.17.1" + }, + "devDependencies": { + "autod": "^2.7.1", + "autod-egg": "^1.0.0", + "cheerio": "^0.22.0", + "egg-bin": "^2.0.2", + "egg-mock": "^2.3.1", + "eslint": "^3.15.0", + "eslint-config-egg": "^3.2.0", + "supertest": "^3.0.0" + }, + "engines": { + "node": ">=7.0.0" + }, + "scripts": { + "dev": "egg-bin dev", + "test": "npm run lint -- --fix && npm run test-local", + "test-local": "egg-bin test", + "cov": "egg-bin cov", + "lint": "eslint .", + "ci": "npm run lint && npm run cov", + "autod": "autod" + } +} diff --git a/hackernews-async/test/app/controller/news.test.js b/hackernews-async/test/app/controller/news.test.js new file mode 100644 index 0000000..ac43c99 --- /dev/null +++ b/hackernews-async/test/app/controller/news.test.js @@ -0,0 +1,39 @@ +'use strict'; + +const request = require('supertest'); +const mm = require('egg-mock'); +const assert = require('assert'); +const cheerio = require('cheerio'); + +describe('test/app/controller/news.test.js', () => { + let app; + before(async () => { + app = mm.app(); + await app.ready(); + }); + + after(() => app.close()); + + afterEach(mm.restore); + + it('should GET /news', async () => { + const result = await request(app.callback()).get('/news').expect(200); + const $ = cheerio.load(result.text); + const listItem = $('.news-view .item'); + assert(listItem.length === app.config.news.pageSize); + }); + + it('should GET /news/item/:id', async () => { + await request(app.callback()) + .get('/news/item/1') + .expect(/\/news\/item\/1/) // just a example, use regex to test part of dom string, but should be strong characteristic + .expect(200); + }); + + it('should GET /news/user/:id', async () => { + await request(app.callback()) + .get('/news/user/activatedgeek') + .expect(/user:<\/span> activatedgeek/) // just a example, use regex to test part of dom string, but should be strong characteristic + .expect(200); + }); +}); diff --git a/hackernews-async/test/app/service/HackerNews.test.js b/hackernews-async/test/app/service/HackerNews.test.js new file mode 100644 index 0000000..2ac70fc --- /dev/null +++ b/hackernews-async/test/app/service/HackerNews.test.js @@ -0,0 +1,28 @@ +'use strict'; + +const assert = require('assert'); +const mm = require('egg-mock'); + +describe('test/app/service/HackerNews.test.js', () => { + let app; + let ctx; + + before(async () => { + app = mm.app(); + await app.ready(); + ctx = app.mockContext(); + }); + + after(() => app.close()); + afterEach(mm.restore); + + it('getTopStories', async () => { + const list = await ctx.service.hackerNews.getTopStories(); + assert(list.length === 30); + }); + + it('getItem', async () => { + const item = await ctx.service.hackerNews.getItem(1); + assert(item.hasOwnProperty('id') && item.hasOwnProperty('title') && item.hasOwnProperty('url')); + }); +}); From 452accf5e0398798f4ad076f6406a02d232e3e4e Mon Sep 17 00:00:00 2001 From: dead-horse Date: Tue, 14 Feb 2017 00:21:42 +0800 Subject: [PATCH 2/4] feat: async hacknews --- hackernews-async/app/controller/news.js | 28 ++++++++++++++----------- hackernews-async/package.json | 6 +++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hackernews-async/app/controller/news.js b/hackernews-async/app/controller/news.js index 7f27ef5..711da2e 100644 --- a/hackernews-async/app/controller/news.js +++ b/hackernews-async/app/controller/news.js @@ -3,27 +3,31 @@ module.exports = app => { return class NewsController extends app.Controller { async list() { - const pageSize = this.app.config.news.pageSize; - const page = parseInt(this.query.page) || 1; + const { ctx, app } = this; + const pageSize = app.config.news.pageSize; + const page = parseInt(ctx.query.page) || 1; + + const idList = await ctx.service.hackerNews.getTopStories(page); - const idList = await this.service.hackerNews.getTopStories(page); // get itemInfo parallel - const newsList = await idList.map(id => this.service.hackerNews.getItem(id)); - await this.render('news/list.tpl', { list: newsList, page, pageSize }); + const newsList = await Promise.all(idList.map(id => ctx.service.hackerNews.getItem(id))); + await ctx.render('news/list.tpl', { list: newsList, page, pageSize }); } async detail() { - const id = this.params.id; - const newsInfo = await this.service.hackerNews.getItem(id); + const { ctx } = this; + const id = ctx.params.id; + const newsInfo = await ctx.service.hackerNews.getItem(id); // get comment parallel - const commentList = await newsInfo.kids.map(id => this.service.hackerNews.getItem(id)); - await this.render('news/detail.tpl', { item: newsInfo, comments: commentList }); + const commentList = await Promise.all(newsInfo.kids.map(id => ctx.service.hackerNews.getItem(id))); + await ctx.render('news/detail.tpl', { item: newsInfo, comments: commentList }); } async user() { - const id = this.params.id; - const userInfo = await this.service.hackerNews.getUser(id); - await this.render('news/user.tpl', { user: userInfo }); + const { ctx } = this; + const id = ctx.params.id; + const userInfo = await ctx.service.hackerNews.getUser(id); + await ctx.render('news/user.tpl', { user: userInfo }); } }; }; diff --git a/hackernews-async/package.json b/hackernews-async/package.json index 4e1ea70..73efa29 100644 --- a/hackernews-async/package.json +++ b/hackernews-async/package.json @@ -4,7 +4,7 @@ "description": "hackernews showcase using async/await for egg", "private": true, "dependencies": { - "egg": "^0.11.0", + "egg": "^0.12.0", "egg-view-nunjucks": "^1.0.0", "moment": "^2.17.1" }, @@ -13,13 +13,13 @@ "autod-egg": "^1.0.0", "cheerio": "^0.22.0", "egg-bin": "^2.0.2", - "egg-mock": "^2.3.1", + "egg-mock": "^3.0.0", "eslint": "^3.15.0", "eslint-config-egg": "^3.2.0", "supertest": "^3.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=7.6.0" }, "scripts": { "dev": "egg-bin dev", From 8ff110ac07e447a9daf1eb8dc319ca85e847b755 Mon Sep 17 00:00:00 2001 From: dead-horse Date: Tue, 14 Feb 2017 00:23:42 +0800 Subject: [PATCH 3/4] f --- hackernews-async/README.md | 2 ++ hackernews-async/appveyor.yml | 14 -------------- 2 files changed, 2 insertions(+), 14 deletions(-) delete mode 100644 hackernews-async/appveyor.yml diff --git a/hackernews-async/README.md b/hackernews-async/README.md index 3d3bb17..fe559d4 100644 --- a/hackernews-async/README.md +++ b/hackernews-async/README.md @@ -4,6 +4,8 @@ ## QuickStart +**Please ensure your node version is 7.6.0+.** + ### Development ```shell $ npm install diff --git a/hackernews-async/appveyor.yml b/hackernews-async/appveyor.yml deleted file mode 100644 index 7f70c1b..0000000 --- a/hackernews-async/appveyor.yml +++ /dev/null @@ -1,14 +0,0 @@ -environment: - matrix: - - nodejs_version: '4' - -install: - - ps: Install-Product node $env:nodejs_version - - npm i npminstall && node_modules\.bin\npminstall - -test_script: - - node --version - - npm --version - - npm run ci - -build: off From 76bb9e6aa885c9095707ec8f0b57fca2ead74a8e Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 15 Feb 2017 19:01:24 +0800 Subject: [PATCH 4/4] f --- hackernews-async/README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hackernews-async/README.md b/hackernews-async/README.md index fe559d4..aac89b4 100644 --- a/hackernews-async/README.md +++ b/hackernews-async/README.md @@ -4,8 +4,6 @@ ## QuickStart -**Please ensure your node version is 7.6.0+.** - ### Development ```shell $ npm install @@ -21,8 +19,19 @@ Use `EGG_SERVER_ENV=prod` to enable prod mode $ EGG_SERVER_ENV=prod npm start ``` -### npm scripts +### Npm Scripts - Use `npm run autod` to auto detect dependencies upgrade - Use `npm run lint` to check code style - Use `npm test` to run unit test + +### Requirement + +Please ensure your node version is `>=7.6.0` for async await support without flag. If your node version is `>=7.0.0 < 7.6.0`, you can run npm scripts with harmony flag + +```shell +# start server +npm run dev -- --harmony-async-await +# run test cases +npm run test-local -- --harmony-async-await +```