From 53f8528b9e5739443258f5412e5a67b14b3792dd Mon Sep 17 00:00:00 2001 From: smallchill Date: Fri, 18 Jan 2019 22:39:21 +0800 Subject: [PATCH] :tada: 1.0.0-RC2 --- .gitpod.yml | 6 ++ config/config.js | 4 +- functions/index.js | 3 +- functions/matchMock.js | 66 ++++++------- functions/package.json | 10 +- jest-puppeteer.config.js | 1 - mock/notices.js | 209 ++++++++++++++++++++------------------- mock/route.js | 5 + package.json | 12 ++- scripts/lint-prettier.js | 62 ++++++------ scripts/prettier.js | 6 +- tests/run-tests.js | 6 +- 12 files changed, 209 insertions(+), 181 deletions(-) create mode 100644 .gitpod.yml create mode 100644 mock/route.js diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..ba727aa --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: +- port: 8000 + onOpen: open-preview +tasks: +- init: npm install + command: npm start diff --git a/config/config.js b/config/config.js index e23eec3..a0f13b8 100644 --- a/config/config.js +++ b/config/config.js @@ -20,6 +20,7 @@ const plugins = [ }, dynamicImport: { loadingComponent: './components/PageLoading/index', + webpackChunkName: true, }, pwa: { workboxPluginMode: 'InjectManifest', @@ -33,7 +34,7 @@ const plugins = [ include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'], exclude: ['@babel/runtime'], }, - hardSource: true, + hardSource: false, } : {}), }, @@ -58,6 +59,7 @@ export default { define: { APP_TYPE: process.env.APP_TYPE || '', }, + treeShaking: true, targets: { ie: 11, }, diff --git a/functions/index.js b/functions/index.js index f4c65f9..609b51c 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,9 +1,10 @@ // [START functionsimport] const functions = require('firebase-functions'); const express = require('express'); + const matchMock = require('./matchMock'); + const app = express(); app.use(matchMock); - exports.api = functions.https.onRequest(app); diff --git a/functions/matchMock.js b/functions/matchMock.js index 4ef7ae8..924573a 100644 --- a/functions/matchMock.js +++ b/functions/matchMock.js @@ -1,10 +1,11 @@ -const mockFile = require('./mock/index'); const pathToRegexp = require('path-to-regexp'); -const debug = console.log; const bodyParser = require('body-parser'); +const mockFile = require('./mock/index'); + const BODY_PARSED_METHODS = ['post', 'put', 'patch']; +const debug = console.log; function parseKey(key) { let method = 'get'; let path = key; @@ -20,7 +21,14 @@ function parseKey(key) { } function createHandler(method, path, handler) { - return function(req, res, next) { + return (req, res, next) => { + function sendData() { + if (typeof handler === 'function') { + handler(req, res, next); + } else { + res.json(handler); + } + } if (BODY_PARSED_METHODS.includes(method)) { bodyParser.json({ limit: '5mb', strict: false })(req, res, () => { bodyParser.urlencoded({ limit: '5mb', extended: true })(req, res, () => { @@ -30,14 +38,6 @@ function createHandler(method, path, handler) { } else { sendData(); } - - function sendData() { - if (typeof handler === 'function') { - handler(req, res, next); - } else { - res.json(handler); - } - } }; } @@ -63,6 +63,24 @@ const mockData = normalizeConfig(mockFile); function matchMock(req) { const { path: exceptPath } = req; const exceptMethod = req.method.toLowerCase(); + function decodeParam(val) { + if (typeof val !== 'string' || val.length === 0) { + return val; + } + + try { + return decodeURIComponent(val); + } catch (err) { + if (err instanceof URIError) { + err.message = `Failed to decode param ' ${val} '`; + err.statusCode = 400; + err.status = 400; + } + + throw err; + } + } + // eslint-disable-next-line no-restricted-syntax for (const mock of mockData) { const { method, re, keys } = mock; if (method === exceptMethod) { @@ -70,7 +88,7 @@ function matchMock(req) { if (match) { const params = {}; - for (let i = 1; i < match.length; i = i + 1) { + for (let i = 1; i < match.length; i += 1) { const key = keys[i - 1]; const prop = key.name; const val = decodeParam(match[i]); @@ -85,33 +103,13 @@ function matchMock(req) { } } - function decodeParam(val) { - if (typeof val !== 'string' || val.length === 0) { - return val; - } - - try { - return decodeURIComponent(val); - } catch (err) { - if (err instanceof URIError) { - err.message = `Failed to decode param ' ${val} '`; - err.status = err.statusCode = 400; - } - - throw err; - } - } - - return mockData.filter(({ method, re }) => { - return method === exceptMethod && re.test(exceptPath); - })[0]; + return mockData.filter(({ method, re }) => method === exceptMethod && re.test(exceptPath))[0]; } module.exports = (req, res, next) => { const match = matchMock(req); if (match) { debug(`mock matched: [${match.method}] ${match.path}`); return match.handler(req, res, next); - } else { - return next(); } + return next(); }; diff --git a/functions/package.json b/functions/package.json index 1fde857..dd72819 100644 --- a/functions/package.json +++ b/functions/package.json @@ -2,19 +2,19 @@ "name": "functions", "description": "Cloud Functions for Firebase", "scripts": { - "serve": "npm run mock && firebase serve --only functions", + "serve": "firebase serve --only functions", "shell": "firebase functions:shell", "start": "npm run shell", - "deploy": "firebase deploy --only functions", + "deploy": "npm run mock && firebase deploy --only functions", "logs": "firebase functions:log", "mock": "node ../scripts/generateMock.js" }, "dependencies": { "@babel/runtime": "^7.0.0", "body-parser": "^1.18.3", - "express": "^4.16.3", - "firebase-admin": "^5.12.1", - "firebase-functions": "^2.0.5", + "express": "^4.16.4", + "firebase-admin": "^6.4.0", + "firebase-functions": "^2.1.0", "mockjs": "^1.0.1-beta3", "moment": "^2.22.2", "path-to-regexp": "^2.2.1" diff --git a/jest-puppeteer.config.js b/jest-puppeteer.config.js index d720fc2..58c2b54 100644 --- a/jest-puppeteer.config.js +++ b/jest-puppeteer.config.js @@ -9,7 +9,6 @@ module.exports = { '--no-first-run', '--no-sandbox', '--no-zygote', - '--single-process', ], }, }; diff --git a/mock/notices.js b/mock/notices.js index 47f64e8..f908d8b 100644 --- a/mock/notices.js +++ b/mock/notices.js @@ -1,104 +1,113 @@ +const fakeNotices = [ + { + id: '000000001', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '你收到了 14 份新周报', + datetime: '2017-08-09', + type: 'notification', + }, + { + id: '000000002', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', + title: '你推荐的 曲妮妮 已通过第三轮面试', + datetime: '2017-08-08', + type: 'notification', + }, + { + id: '000000003', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', + title: '这种模板可以区分多种通知类型', + datetime: '2017-08-07', + read: true, + type: 'notification', + }, + { + id: '000000004', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000005', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '内容不要超过两行字,超出时自动截断', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000006', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '曲丽丽 评论了你', + description: '描述信息描述信息描述信息', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000007', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '朱偏右 回复了你', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000008', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '标题', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000009', + title: '任务名称', + description: '任务需要在 2017-01-12 20:00 前启动', + extra: '未开始', + status: 'todo', + type: 'event', + }, + { + id: '000000010', + title: '第三方紧急代码变更', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '马上到期', + status: 'urgent', + type: 'event', + }, + { + id: '000000011', + title: '信息安全考试', + description: '指派竹尔于 2017-01-09 前完成更新并发布', + extra: '已耗时 8 天', + status: 'doing', + type: 'event', + }, + { + id: '000000012', + title: 'ABCD 版本发布', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '进行中', + status: 'processing', + type: 'event', + }, +]; + const getNotices = (req, res) => { - const json = { code: 200, success: true, msg: '操作成功' }; - const data = [ - { - id: '000000001', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', - title: '你收到了 14 份新周报', - datetime: '2017-08-09', - type: 'notification', - }, - { - id: '000000002', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', - title: '你推荐的 曲妮妮 已通过第三轮面试', - datetime: '2017-08-08', - type: 'notification', - }, - { - id: '000000003', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', - title: '这种模板可以区分多种通知类型', - datetime: '2017-08-07', - read: true, - type: 'notification', - }, - { - id: '000000004', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', - title: '左侧图标用于区分不同的类型', - datetime: '2017-08-07', - type: 'notification', - }, - { - id: '000000005', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', - title: '内容不要超过两行字,超出时自动截断', - datetime: '2017-08-07', - type: 'notification', - }, - { - id: '000000006', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '曲丽丽 评论了你', - description: '描述信息描述信息描述信息', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000007', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '朱偏右 回复了你', - description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000008', - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', - title: '标题', - description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', - datetime: '2017-08-07', - type: 'message', - clickClose: true, - }, - { - id: '000000009', - title: '任务名称', - description: '任务需要在 2017-01-12 20:00 前启动', - extra: '未开始', - status: 'todo', - type: 'event', - }, - { - id: '000000010', - title: '第三方紧急代码变更', - description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', - extra: '马上到期', - status: 'urgent', - type: 'event', - }, - { - id: '000000011', - title: '信息安全考试', - description: '指派竹尔于 2017-01-09 前完成更新并发布', - extra: '已耗时 8 天', - status: 'doing', - type: 'event', - }, - { - id: '000000012', - title: 'ABCD 版本发布', - description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', - extra: '进行中', - status: 'processing', - type: 'event', - }, - ]; - json.data = data; - return res.json(json); + if (req.query && req.query.type) { + const startFrom = parseInt(req.query.lastItemId, 10) + 1; + const result = fakeNotices + .filter(({ type }) => type === req.query.type) + .map((notice, index) => ({ + ...notice, + id: `0000000${startFrom + index}`, + })); + return res.json(startFrom > 24 ? result.concat(null) : result); + } + return res.json(fakeNotices); }; export default { diff --git a/mock/route.js b/mock/route.js new file mode 100644 index 0000000..418d10f --- /dev/null +++ b/mock/route.js @@ -0,0 +1,5 @@ +export default { + '/api/auth_routes': { + '/form/advanced-form': { authority: ['admin', 'user'] }, + }, +}; diff --git a/package.json b/package.json index 4da31ef..9729606 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "An out-of-box UI solution for enterprise applications", "private": true, "scripts": { - "presite": "node ./scripts/generateMock.js && cd functions && npm install", + "presite": "cd functions && npm install", "start": "cross-env APP_TYPE=site PORT=8888 umi dev", "start:no-mock": "cross-env MOCK=none PORT=8888 umi dev", "build": "umi build", @@ -27,8 +27,8 @@ "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up", "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build", "docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./", - "docker:tag": "docker tag ant-design-pro chenshuai2144/ant-design-pro", - "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push chenshuai2144/ant-design-pro" + "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro", + "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro" }, "dependencies": { "@antv/data-set": "^0.10.0", @@ -36,6 +36,7 @@ "antd": "^3.11.6", "bizcharts": "^3.4.2", "bizcharts-plugin-slider": "^2.1.1-beta.1", + "chalk": "^2.4.2", "classnames": "^2.2.6", "dva": "^2.4.0", "enquire-js": "^0.2.1", @@ -83,6 +84,7 @@ "gh-pages": "^2.0.1", "husky": "^1.2.0", "jest-puppeteer": "^3.5.1", + "less": "^3.9.0", "lint-staged": "^8.1.0", "merge-umi-mock-data": "^0.0.3", "mockjs": "^1.0.1-beta3", @@ -95,9 +97,9 @@ "tslint": "^5.10.0", "tslint-config-prettier": "^1.10.0", "tslint-react": "^3.6.0", - "umi": "^2.3.1", + "umi": "^2.4.2", "umi-plugin-ga": "^1.1.3", - "umi-plugin-react": "^1.2.0" + "umi-plugin-react": "^1.3.4" }, "optionalDependencies": { "puppeteer": "^1.10.0" diff --git a/scripts/lint-prettier.js b/scripts/lint-prettier.js index ab498fc..677f793 100644 --- a/scripts/lint-prettier.js +++ b/scripts/lint-prettier.js @@ -6,43 +6,45 @@ *----------*****-------------- */ -const glob = require('glob'); const prettier = require('prettier'); const fs = require('fs'); +const chalk = require('chalk'); const prettierConfigPath = require.resolve('../.prettierrc'); const files = process.argv.slice(2); let didError = false; -let didWarn = false; files.forEach(file => { - const options = prettier.resolveConfig.sync(file, { - config: prettierConfigPath, - }); - try { - const fileInfo = prettier.getFileInfo.sync(file); - if (fileInfo.ignored) { - return; - } - const input = fs.readFileSync(file, 'utf8'); - const withParserOptions = { - ...options, - parser: fileInfo.inferredParser, - }; - const isPrettier = prettier.check(input, withParserOptions); - if (!isPrettier) { - console.log( - `\x1b[31m ${file} is no prettier, please use npm run prettier and git add !\x1b[0m` - ); - didWarn = true; - } - } catch (e) { - didError = true; - } + Promise.all([ + prettier.resolveConfig(file, { + config: prettierConfigPath, + }), + prettier.getFileInfo(file), + ]) + .then(resolves => { + const [options, fileInfo] = resolves; + if (fileInfo.ignored) { + return; + } + const input = fs.readFileSync(file, 'utf8'); + const withParserOptions = { + ...options, + parser: fileInfo.inferredParser, + }; + const output = prettier.format(input, withParserOptions); + if (output !== input) { + fs.writeFileSync(file, output, 'utf8'); + console.log(chalk.green(`${file} is prettier`)); + } + }) + .catch(e => { + didError = true; + }) + .finally(() => { + if (didError) { + process.exit(1); + } + console.log(chalk.hex('#1890FF')('prettier success!')); + }); }); - -if (didWarn || didError) { - process.exit(1); -} -console.log('\x1b[32m lint prettier success!\x1b[0m'); diff --git a/scripts/prettier.js b/scripts/prettier.js index 9ce7813..17ded6c 100644 --- a/scripts/prettier.js +++ b/scripts/prettier.js @@ -6,11 +6,11 @@ *----------*****-------------- */ -const glob = require('glob'); const prettier = require('prettier'); const fs = require('fs'); const getPrettierFiles = require('./getPrettierFiles'); const prettierConfigPath = require.resolve('../.prettierrc'); +const chalk = require('chalk'); let didError = false; @@ -33,7 +33,7 @@ files.forEach(file => { const output = prettier.format(input, withParserOptions); if (output !== input) { fs.writeFileSync(file, output, 'utf8'); - console.log(`\x1b[34m ${file} is prettier`); + console.log(chalk.green(`${file} is prettier`)); } } catch (e) { didError = true; @@ -43,4 +43,4 @@ files.forEach(file => { if (didError) { process.exit(1); } -console.log('\x1b[32m prettier success!'); +console.log(chalk.hex('#1890FF')('prettier success!')); diff --git a/tests/run-tests.js b/tests/run-tests.js index 02c42b0..5735ada 100644 --- a/tests/run-tests.js +++ b/tests/run-tests.js @@ -24,7 +24,11 @@ startServer.on('exit', () => { console.log('Starting development server for e2e tests...'); startServer.stdout.on('data', data => { console.log(data.toString()); - if (!once && data.toString().indexOf('Compiled successfully') >= 0) { + // hack code , wait umi + if ( + (!once && data.toString().indexOf('Compiled successfully') >= 0) || + data.toString().indexOf('Theme generated successfully') >= 0 + ) { // eslint-disable-next-line once = true; console.log('Development server is started, ready to run tests.');