From 3c47abb7d6c7a44f86a53defa2efe44c2ae214f6 Mon Sep 17 00:00:00 2001
From: TZ <atian25@qq.com>
Date: Wed, 4 Apr 2018 20:19:56 +0800
Subject: [PATCH 1/2] feat: use egg 2.6.0

---
 hackernews-async-ts/README.md                 | 31 +++++++---------
 hackernews-async-ts/app/controller/news.ts    | 10 +++---
 hackernews-async-ts/app/extend/filter.ts      |  8 +++--
 hackernews-async-ts/app/router.ts             |  2 +-
 .../app/service/{HackerNews.ts => News.ts}    |  0
 .../app/view/layout/layout.tpl                |  2 +-
 hackernews-async-ts/config/config.default.ts  | 19 ++++++----
 hackernews-async-ts/config/plugin.ts          | 11 +++---
 hackernews-async-ts/package.json              | 35 +++++++++----------
 .../{HackerNews.test.ts => News.test.ts}      |  6 ++--
 .../typings/app/service/index.d.ts            |  4 +--
 hackernews-async-ts/typings/index.d.ts        |  7 +---
 12 files changed, 67 insertions(+), 68 deletions(-)
 rename hackernews-async-ts/app/service/{HackerNews.ts => News.ts} (100%)
 rename hackernews-async-ts/test/app/service/{HackerNews.test.ts => News.test.ts} (65%)

diff --git a/hackernews-async-ts/README.md b/hackernews-async-ts/README.md
index dded0eb..b5946f5 100644
--- a/hackernews-async-ts/README.md
+++ b/hackernews-async-ts/README.md
@@ -1,38 +1,33 @@
-# egg-example-hackernews-async
+# hackernews-async-ts
 
-[Hacker News](https://news.ycombinator.com/) showcase using async/await for egg
+[Hacker News](https://news.ycombinator.com/) showcase using typescript && egg
 
 ## QuickStart
 
 ### Development
-```shell
-$ npm install
-$ npm run tsc:w
+
+```bash
+$ npm i
 $ npm run dev
 $ open http://localhost:7001/
 ```
 
-### Deploy
+Don't tsc compile at development mode, if you had run `tsc` then you need to `npm run clean` before `npm run dev`.
 
-Use `EGG_SERVER_ENV=prod` to enable prod mode
+### Deploy
 
-```shell
-$ EGG_SERVER_ENV=prod npm start
+```bash
+$ npm run tsc
+$ 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
+- se `npm run clean` to clean compiled js at development mode once
 
 ### 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
-```
+- Node.js 8.x
+- Typescript 2.8+
diff --git a/hackernews-async-ts/app/controller/news.ts b/hackernews-async-ts/app/controller/news.ts
index 1fe7734..851f8fe 100644
--- a/hackernews-async-ts/app/controller/news.ts
+++ b/hackernews-async-ts/app/controller/news.ts
@@ -6,26 +6,26 @@ export default class NewsController extends Controller {
     const pageSize = app.config.news.pageSize;
     const page = parseInt(ctx.query.page, 10) || 1;
 
-    const idList = await ctx.service.hackerNews.getTopStories(page);
+    const idList = await ctx.service.news.getTopStories(page);
 
     // get itemInfo parallel
-    const newsList = await Promise.all(idList.map((id) => ctx.service.hackerNews.getItem(id)));
+    const newsList = await Promise.all(idList.map((id) => ctx.service.news.getItem(id)));
     await ctx.render('news/list.tpl', { list: newsList, page, pageSize });
   }
 
   public async detail() {
     const { ctx } = this;
     const id = ctx.params.id;
-    const newsInfo = await ctx.service.hackerNews.getItem(id);
+    const newsInfo = await ctx.service.news.getItem(id);
     // get comment parallel
-    const commentList = await Promise.all(newsInfo.kids.map((_id) => ctx.service.hackerNews.getItem(_id)));
+    const commentList = await Promise.all(newsInfo.kids.map((_id) => ctx.service.news.getItem(_id)));
     await ctx.render('news/detail.tpl', { item: newsInfo, comments: commentList });
   }
 
   public async user() {
     const { ctx } = this;
     const id = ctx.params.id;
-    const userInfo = await ctx.service.hackerNews.getUser(id);
+    const userInfo = await ctx.service.news.getUser(id);
     await ctx.render('news/user.tpl', { user: userInfo });
   }
 }
diff --git a/hackernews-async-ts/app/extend/filter.ts b/hackernews-async-ts/app/extend/filter.ts
index e74123e..7c22c89 100644
--- a/hackernews-async-ts/app/extend/filter.ts
+++ b/hackernews-async-ts/app/extend/filter.ts
@@ -2,6 +2,10 @@
 
 import * as moment from 'moment';
 
-exports.relativeTime = (time) => moment(new Date(time * 1000)).fromNow();
+export function relativeTime(time) {
+  return moment(new Date(time * 1000)).fromNow();
+};
 
-exports.domain = (url) => url && url.split('/')[2];
+export function domain (url) {
+  return url && url.split('/')[2];
+};
diff --git a/hackernews-async-ts/app/router.ts b/hackernews-async-ts/app/router.ts
index 50a9d49..cead0f3 100644
--- a/hackernews-async-ts/app/router.ts
+++ b/hackernews-async-ts/app/router.ts
@@ -3,7 +3,7 @@ import { Application } from 'egg';
 export default (app: Application) => {
   const { controller, router } = app;
 
-  // router.redirect('/', '/news');
+  router.redirect('/', '/news');
   router.get('/news', controller.news.list);
   router.get('/news/item/:id', controller.news.detail);
   router.get('/news/user/:id', controller.news.user);
diff --git a/hackernews-async-ts/app/service/HackerNews.ts b/hackernews-async-ts/app/service/News.ts
similarity index 100%
rename from hackernews-async-ts/app/service/HackerNews.ts
rename to hackernews-async-ts/app/service/News.ts
diff --git a/hackernews-async-ts/app/view/layout/layout.tpl b/hackernews-async-ts/app/view/layout/layout.tpl
index d9fcc3d..aae4fb2 100644
--- a/hackernews-async-ts/app/view/layout/layout.tpl
+++ b/hackernews-async-ts/app/view/layout/layout.tpl
@@ -13,7 +13,7 @@
         <a id="yc" href="http://www.ycombinator.com"><img src="https://news.ycombinator.com/y18.gif"></a>
         <h1><a href="/news">Hacker News</a></h1>
         <span class="source">
-          Built with <a href="https://eggjs.org/" target="_blank">egg</a> | <a href="https://github.com/eggjs/egg-boilerplate-simple" target="_blank">Source</a>
+          Built with <a href="https://eggjs.org/" target="_blank">Egg</a> | <a href="https://github.com/eggjs/examples/tree/master/hackernews-async-ts" target="_blank">Source</a>
         </span>
       </div>
       {% block content %}{% endblock %}
diff --git a/hackernews-async-ts/config/config.default.ts b/hackernews-async-ts/config/config.default.ts
index 7265d53..7602ea0 100644
--- a/hackernews-async-ts/config/config.default.ts
+++ b/hackernews-async-ts/config/config.default.ts
@@ -1,12 +1,15 @@
 'use strict';
+
 import { EggAppConfig, PowerPartial } from 'egg';
 import * as fs from 'fs';
 import * as path from 'path';
 
+// 提供给 config.{env}.ts 使用
 export type DefaultConfig = PowerPartial<EggAppConfig & BizConfig>;
 
-// 本应用的自定义配置的定义
+// 应用本身的配置 Scheme
 export interface BizConfig {
+  sourceUrl: string;
   news: {
     pageSize: number;
     serverUrl: string;
@@ -16,10 +19,17 @@ export interface BizConfig {
 export default (appInfo: EggAppConfig) => {
   const config = {} as PowerPartial<EggAppConfig> & BizConfig;
 
+  // 应用本身的配置
+  config.sourceUrl = `https://github.com/eggjs/examples/tree/master/${appInfo.name}`;
+  config.news = {
+    pageSize: 30,
+    serverUrl: 'https://hacker-news.firebaseio.com/v0',
+  };
+
+  // 覆盖框架,插件的配置
   config.keys = appInfo.name + '123456';
 
   config.view = {
-    root: path.join(appInfo.baseDir, 'app/view'),
     defaultViewEngine: 'nunjucks',
     mapping: {
       '.tpl': 'nunjucks',
@@ -30,10 +40,5 @@ export default (appInfo: EggAppConfig) => {
     '/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-ts/config/plugin.ts b/hackernews-async-ts/config/plugin.ts
index 31c3046..99c3979 100644
--- a/hackernews-async-ts/config/plugin.ts
+++ b/hackernews-async-ts/config/plugin.ts
@@ -1,7 +1,8 @@
-exports.static = true;
+'use strict';
 
-exports.nunjucks = {
-  enable: true,
-  package: 'egg-view-nunjucks',
+export default {
+  nunjucks: {
+    enable: true,
+    package: 'egg-view-nunjucks',
+  },
 };
-
diff --git a/hackernews-async-ts/package.json b/hackernews-async-ts/package.json
index 1845c04..4e18739 100644
--- a/hackernews-async-ts/package.json
+++ b/hackernews-async-ts/package.json
@@ -1,17 +1,29 @@
 {
-  "name": "egg-example-hackernews-async-ts",
+  "name": "hackernews-async-ts",
   "version": "1.0.0",
-  "description": "hackernews showcase using async/await for egg",
+  "description": "hackernews showcase using typescript && egg",
   "private": true,
   "egg": {
     "typescript": true
   },
+  "scripts": {
+    "start": "egg-scripts start",
+    "dev": "egg-bin dev -r egg-ts-helper/register",
+    "tsc": "ets && tsc -p tsconfig.json",
+    "clean": "ets clean",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test -r egg-ts-helper/register",
+    "cov": "egg-bin cov",
+    "lint": "tslint .",
+    "ci": "npm run lint && npm run tsc && npm run cov --no-ts",
+    "debug": "egg-bin debug",
+    "autod": "autod"
+  },
   "dependencies": {
-    "egg": "^2.5.0",
+    "egg": "^2.6.0",
     "egg-scripts": "^2.5.1",
     "egg-view-nunjucks": "^2.2.0",
-    "moment": "^2.21.0",
-    "source-map-support": "^0.5.4"
+    "moment": "^2.21.0"
   },
   "devDependencies": {
     "@types/cheerio": "^0.22.1",
@@ -31,18 +43,5 @@
   },
   "engines": {
     "node": ">=8.9.0"
-  },
-  "scripts": {
-    "start": "egg-scripts start",
-    "dev": "egg-bin dev -r egg-ts-helper/register",
-    "tsc": "ets && tsc -p tsconfig.json",
-    "clean": "ets clean",
-    "test": "npm run lint -- --fix && npm run test-local",
-    "test-local": "egg-bin test -r egg-ts-helper/register",
-    "cov": "egg-bin cov",
-    "lint": "tslint .",
-    "ci": "npm run lint && npm run cov",
-    "debug": "egg-bin debug",
-    "autod": "autod"
   }
 }
diff --git a/hackernews-async-ts/test/app/service/HackerNews.test.ts b/hackernews-async-ts/test/app/service/News.test.ts
similarity index 65%
rename from hackernews-async-ts/test/app/service/HackerNews.test.ts
rename to hackernews-async-ts/test/app/service/News.test.ts
index 2d6bf27..804235c 100644
--- a/hackernews-async-ts/test/app/service/HackerNews.test.ts
+++ b/hackernews-async-ts/test/app/service/News.test.ts
@@ -3,7 +3,7 @@
 import { Context } from 'egg';
 import { app, assert } from 'egg-mock/bootstrap';
 
-describe('test/app/service/HackerNews.test.js', () => {
+describe('test/app/service/News.test.js', () => {
   let ctx: Context;
 
   before(async () => {
@@ -11,12 +11,12 @@ describe('test/app/service/HackerNews.test.js', () => {
   });
 
   it('getTopStories', async () => {
-    const list = await ctx.service.hackerNews.getTopStories();
+    const list = await ctx.service.news.getTopStories();
     assert(list.length === 30);
   });
 
   it('getItem', async () => {
-    const item = await ctx.service.hackerNews.getItem(1);
+    const item = await ctx.service.news.getItem(1);
     assert(item.id && item.title && item.url);
   });
 });
diff --git a/hackernews-async-ts/typings/app/service/index.d.ts b/hackernews-async-ts/typings/app/service/index.d.ts
index d51448b..2f6ba7f 100644
--- a/hackernews-async-ts/typings/app/service/index.d.ts
+++ b/hackernews-async-ts/typings/app/service/index.d.ts
@@ -1,10 +1,10 @@
 // This file was auto created by egg-ts-helper
 // Do not modify this file!!!!!!!!!
 
-import HackerNews from '../../../app/service/HackerNews';
+import News from '../../../app/service/News';
 
 declare module 'egg' {
   interface IService {
-    hackerNews: HackerNews;
+    news: News;
   }
 }
diff --git a/hackernews-async-ts/typings/index.d.ts b/hackernews-async-ts/typings/index.d.ts
index ae2f559..57f2414 100644
--- a/hackernews-async-ts/typings/index.d.ts
+++ b/hackernews-async-ts/typings/index.d.ts
@@ -1,8 +1,3 @@
-// extend egg
 declare module 'egg' {
-  type PowerPartial<T> = {
-    [U in keyof T]?: T[U] extends {}
-      ? { [V in keyof T[U]]?: T[U][V] extends {} ? Partial<T[U][V]> : T[U][V] }
-      : T[U]
-  };
+
 }
\ No newline at end of file

From 4a8967a5c144161991871377b13efbdd366bf983 Mon Sep 17 00:00:00 2001
From: TZ <atian25@qq.com>
Date: Wed, 4 Apr 2018 22:12:23 +0800
Subject: [PATCH 2/2] feat: update ts scripts

---
 hackernews-async-ts/.autod.conf.js           |  6 +++---
 hackernews-async-ts/config/config.default.ts |  8 ++++----
 hackernews-async-ts/package.json             | 18 +++++++++---------
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/hackernews-async-ts/.autod.conf.js b/hackernews-async-ts/.autod.conf.js
index 96fdfa1..44bb3fb 100644
--- a/hackernews-async-ts/.autod.conf.js
+++ b/hackernews-async-ts/.autod.conf.js
@@ -7,23 +7,23 @@ module.exports = {
   devprefix: '^',
   exclude: [
     'test/fixtures',
+    'coverage',
   ],
   dep: [
     'egg',
     'egg-scripts',
     'egg-view-nunjucks',
     'moment',
-    'source-map-support',
   ],
   devdep: [
     'autod',
     'autod-egg',
     'egg-bin',
-  ],
-  keep: [
     'tslib',
     'typescript',
   ],
+  keep: [
+  ],
   semver: [
   ],
   test: 'scripts',
diff --git a/hackernews-async-ts/config/config.default.ts b/hackernews-async-ts/config/config.default.ts
index 7602ea0..5cb0b04 100644
--- a/hackernews-async-ts/config/config.default.ts
+++ b/hackernews-async-ts/config/config.default.ts
@@ -4,10 +4,10 @@ import { EggAppConfig, PowerPartial } from 'egg';
 import * as fs from 'fs';
 import * as path from 'path';
 
-// 提供给 config.{env}.ts 使用
+// for config.{env}.ts
 export type DefaultConfig = PowerPartial<EggAppConfig & BizConfig>;
 
-// 应用本身的配置 Scheme
+// app special config scheme
 export interface BizConfig {
   sourceUrl: string;
   news: {
@@ -19,14 +19,14 @@ export interface BizConfig {
 export default (appInfo: EggAppConfig) => {
   const config = {} as PowerPartial<EggAppConfig> & BizConfig;
 
-  // 应用本身的配置
+  // app special config
   config.sourceUrl = `https://github.com/eggjs/examples/tree/master/${appInfo.name}`;
   config.news = {
     pageSize: 30,
     serverUrl: 'https://hacker-news.firebaseio.com/v0',
   };
 
-  // 覆盖框架,插件的配置
+  // override config from framework / plugin
   config.keys = appInfo.name + '123456';
 
   config.view = {
diff --git a/hackernews-async-ts/package.json b/hackernews-async-ts/package.json
index 4e18739..62b092d 100644
--- a/hackernews-async-ts/package.json
+++ b/hackernews-async-ts/package.json
@@ -9,21 +9,21 @@
   "scripts": {
     "start": "egg-scripts start",
     "dev": "egg-bin dev -r egg-ts-helper/register",
-    "tsc": "ets && tsc -p tsconfig.json",
-    "clean": "ets clean",
-    "test": "npm run lint -- --fix && npm run test-local",
+    "debug": "egg-bin debug -r egg-ts-helper/register",
     "test-local": "egg-bin test -r egg-ts-helper/register",
+    "test": "npm run lint -- --fix && npm run test-local",
     "cov": "egg-bin cov",
+    "tsc": "ets && tsc -p tsconfig.json",
+    "ci": "npm run lint && npm run tsc && egg-bin cov --no-ts",
+    "autod": "autod",
     "lint": "tslint .",
-    "ci": "npm run lint && npm run tsc && npm run cov --no-ts",
-    "debug": "egg-bin debug",
-    "autod": "autod"
+    "clean": "ets clean"
   },
   "dependencies": {
     "egg": "^2.6.0",
-    "egg-scripts": "^2.5.1",
+    "egg-scripts": "^2.6.0",
     "egg-view-nunjucks": "^2.2.0",
-    "moment": "^2.21.0"
+    "moment": "^2.22.0"
   },
   "devDependencies": {
     "@types/cheerio": "^0.22.1",
@@ -33,7 +33,7 @@
     "autod": "^3.0.1",
     "autod-egg": "^1.1.0",
     "cheerio": "^1.0.0-rc.2",
-    "egg-bin": "^4.6.0",
+    "egg-bin": "^4.6.2",
     "egg-mock": "^3.16.0",
     "egg-ts-helper": "^1.4.2",
     "rimraf": "^2.6.1",