添加分页功能、打包优化、ts编译优化

This commit is contained in:
周炽键 2021-07-23 21:34:47 +08:00
parent fd85fcef74
commit 6a1f9a3f6b
15 changed files with 3340 additions and 141 deletions

2
.gitignore vendored
View File

@ -62,6 +62,4 @@ typings/
dist
entity/**/*.js
ormconfig.json

23
@types/index.d.ts vendored
View File

@ -1,11 +1,17 @@
/**
*
*/
interface ExpressResponseError extends Record<string,unknown>{
interface ExpressResponseError extends Record<string,unknown>{
error:string
}
/**
*
*/
interface ExpressResponseSuccess extends Record<string,unknown>{
message:string
}
/**
*
*/
@ -17,10 +23,17 @@ interface ExpressResponseDetail<T=Record<string,unknown>> extends Record<string,
detail:T
}
type SSEPayload = Record<string|number,SSEPayload>|string|number
declare namespace Express {
export interface Response {
error(error:string,statusCode:number,errObj:Record<string,unknown>):ExpressResponseError
list<T=Record<string,unknown>>(list:T,resObj:Record<string,unknown>):ExpressResponseList<T>
detail<T=Record<string,unknown>>(detail:T,resObj:Record<string,unknown>):ExpressResponseDetail<T>
error(error:string,statusCode:number,errObj?:Record<string,unknown>):ExpressResponseError
list<T=Record<string,unknown>>(list:T,resObj?:Record<string,unknown>):ExpressResponseList<T>
detail<T=Record<string,unknown>>(detail:T,resObj?:Record<string,unknown>):ExpressResponseDetail<T>
success(message:string,resObj?:Record<string,unknown>):ExpressResponseSuccess
enable_sse():this
sse(data:SSEPayload,event:string):this
}
}

12
app.js
View File

@ -42,6 +42,18 @@ Object.defineProperty(express.response,'detail',{
configurable:false
})
Object.defineProperty(express.response,'success',{
value:function (msg,resObj = {}) {
resObj.message = msg
this.status(200).send(resObj)
},
enumerable:false,
writable:false,
configurable:false
})
/**
* 连接数据库
*/

87
bin/www
View File

@ -3,94 +3,95 @@
/**
* Module dependencies.
*/
require('dotenv').config({path:'./config/.env'})
var app = require('../app');
var debug = require('debug')('express-my-admin:server');
var http = require('http');
const event = require('../event')
const {resolve} = require('path')
require('dotenv').config({ path:resolve(__dirname,'../.env') })
var app = require(resolve(__dirname,'../app'))
var debug = require('debug')('express-im:server')
var http = require('http')
const event = require(resolve(__dirname,'../event'))
/**
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var port = normalizePort(process.env.PORT || '3000')
app.set('port', port)
/**
/**
* Create HTTP server.
*/
var server = http.createServer(app);
var server = http.createServer(app)
/**
/**
* Listen on provided port, on all network interfaces.
*/
event.on('typeorm-connection',()=>{
event.on('typeorm-connection',()=>{
server.listen(port,()=>{
console.log(`Admin服务启动成功,监听端口${port}`);
});
})
console.log(`服务启动成功,监听端口${port}`)
})
})
server.on('error', onError);
server.on('listening', onListening);
server.on('error', onError)
server.on('listening', onListening)
/**
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
function normalizePort (val) {
var port = parseInt(val, 10)
if (isNaN(port)) {
// named pipe
return val;
return val
}
if (port >= 0) {
// port number
return port;
return port
}
return false;
}
return false
}
/**
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
function onError (error) {
if (error.syscall !== 'listen') {
throw error;
throw error
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
: 'Port ' + port
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
console.error(bind + ' requires elevated privileges')
process.exit(1)
break
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
console.error(bind + ' is already in use')
process.exit(1)
break
default:
throw error;
throw error
}
}
}
/**
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
function onListening () {
var addr = server.address()
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
: 'port ' + addr.port
debug('Listening on ' + bind)
}

View File

@ -1,30 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostAdminMemberDto = void 0;
var class_transformer_1 = require("class-transformer");
var class_validator_1 = require("class-validator");
var PostAdminMemberDto = /** @class */ (function () {
function PostAdminMemberDto() {
}
__decorate([
class_transformer_1.Expose(),
class_validator_1.IsNotEmpty({ message: '登录用户名不能为空' }),
__metadata("design:type", String)
], PostAdminMemberDto.prototype, "username", void 0);
__decorate([
class_transformer_1.Expose(),
class_validator_1.IsNotEmpty({ message: '登录密码不能为空' }),
__metadata("design:type", String)
], PostAdminMemberDto.prototype, "password", void 0);
return PostAdminMemberDto;
}());
exports.PostAdminMemberDto = PostAdminMemberDto;

View File

@ -1,4 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
require("es6-shim");

4
example.env Normal file
View File

@ -0,0 +1,4 @@
PORT=5500
GITHUB_CLIENTID=xxx
GITHUB_SECRET=xxx
AES=xxx

34
middlewares/auth.js Normal file
View File

@ -0,0 +1,34 @@
const AuthUtils = require('../utils/auth')
const { Account } = require('../entity/account')
const { getManager } = require('typeorm')
module.exports = async function (req,res,next) {
try{
const session = req.cookies.IM_SESS
if(!session) return res.error('未登录',401)
try{
var payload = AuthUtils.decode(session)
}catch(err) {
return res.error(err.message,401)
}
req.auth_session = payload
const manager = getManager()
const detail = await manager.findOne(Account,{ aid:payload.aid })
if(!detail.isActive) return res.error('账号不可用',403)
req.account_detail = detail
}catch(err) {
console.error('登录认证中间件报错:',err);
return res.error('登录凭证已过期',401)
}
next()
}

27
middlewares/page_auth.js Normal file
View File

@ -0,0 +1,27 @@
const AuthUtils = require('../utils/auth')
const { Account } = require('../entity/account')
const { getManager } = require('typeorm')
module.exports = async function (req,res,next) {
const session = req.cookies.IM_SESS
if(!session) return res.redirect('/oauth/login')
try{
var payload = AuthUtils.decode(session)
}catch(err) {
return res.redirect('/oauth/login')
}
req.auth_session = payload
const manager = getManager()
const detail = await manager.findOne(Account,{ aid:payload.aid })
req.account_detail = detail
next()
}

View File

@ -4,16 +4,14 @@
".vscode",
".git",
"node_modules/*",
"views/*",
"entity/**/*.js",
"dto/**/*.js",
".gitignore",
"ormconfig.example.json",
"package.json"
"dist/*",
"bin/*"
],
"env": {
"NODE_ENV": "development"
},
"ext":"js,json,ts",
"exec":"tsc && node ./bin/www"
"exec":"ts-node ./bin/www"
}

View File

@ -4,8 +4,8 @@
"private": true,
"repository": "git@git.zcj.plus:zhouchijian/express-my-admin.git",
"scripts": {
"build": "tsc",
"start": "node ./bin/www",
"build": "rm -rf dist && tsc && cp .env dist/.env && cp ormconfig.json dist/ormconfig.json && cp -r bin dist/bin && cp -r views ./dist/views",
"start:prod": "cd dist && node ./bin/www",
"dev": "nodemon"
},
"dependencies": {
@ -23,6 +23,7 @@
"mysql": "^2.18.1",
"mysql2": "^2.2.5",
"reflect-metadata": "^0.1.13",
"ts-node": "^10.1.0",
"typeorm": "^0.2.34"
},
"devDependencies": {

View File

@ -7,14 +7,14 @@
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": ["es5","es6"], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
"allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "dist", /* Redirect output structure to the directory. */
"outDir": "dist", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */

57
utils/auth.js Normal file
View File

@ -0,0 +1,57 @@
const isJSON = require('is-json')
const CryptoJS = require('crypto-js')
const keyHex = process.env.AES
function encode (payload, timestamp = 0) {
const data = {
payload,
expired_timestamp: timestamp ? timestamp + Date.now() : 0,
}
const messageHex = CryptoJS.enc.Utf8.parse(JSON.stringify(data))
var encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
})
return encrypted.toString()
}
function decode (encrypted) {
const errmsg = '登录凭证无效'
try{
var decrypt = CryptoJS.enc.Utf8.stringify(
CryptoJS.AES.decrypt(encrypted, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}),
)
}catch(err) {
throw new Error(errmsg)
}
if(!isJSON(decrypt)) {
throw new Error(errmsg)
}
var payload = JSON.parse(decrypt)
if (!payload.payload) {
throw new Error(errmsg)
}
if (Date.now() >= payload.expired_timestamp) {
throw new Error('登录凭证已过期')
}
return payload.payload
}
module.exports = {
encode,
decode
}

6
utils/id.ts Normal file
View File

@ -0,0 +1,6 @@
import { v4 as uuid } from 'uuid'
import md5 from 'md5'
export function md5_uuid ():string {
return md5(uuid())
}

3082
yarn.lock Normal file

File diff suppressed because it is too large Load Diff