This commit is contained in:
aozhiwei 2022-03-15 13:15:30 +08:00
commit 6ef05cfee1
10 changed files with 1681 additions and 0 deletions

131
app.js Normal file
View File

@ -0,0 +1,131 @@
const express = require('express');
const mysql = require("mysql");
const utils = require('./utils');
const event = require('./event');
const config = require('./config');
const db = require('./db');
const app = express();
const handlers = {};
const middlewares = {};
const dbPools = {};
let sessionClass = null;
let useMiddlewares = [];
function listen(port) {
app.listen(port);
}
function get() {
}
function init() {
event.emitEvent(event.APP_INITIALIZED_EVENT);
}
function registerHandler(c, a, cb) {
handlers[a + '@' + c] = {
'cb': cb,
'middlewares': useMiddlewares
};
}
function injectionSession(sessionCls) {
sessionClass = sessionCls;
}
function addMiddleware(name, cb) {
middlewares[name] = cb;
}
function useMiddleware(list, cb) {
try {
useMiddlewares = [];
list.forEach((name) => {
useMiddlewares.push(middlewares[name]);
});
cb();
} finally {
useMiddlewares = [];
}
}
function registerDb(name, options) {
dbPools[name] = {
'options': options,
'pool': mysql.createPool({
host : options['host'],
user : options['user'],
password : options['passwd'],
database : options['database'],
stringifyObjects : true
})
};
}
function getDbConn(name) {
const ret = {
err: null,
conn: null,
};
return new Promise((resolve) => {
if (!(name in dbPools)) {
ret.err = 'dbname not exists ' + name;
resolve(ret);
return;
}
const pool = dbPools[name]['pool'];
pool.getConnection(function(err, conn) {
ret.err = err;
ret.conn = new db(conn);
resolve(ret);
});
});
}
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', promise, 'reason:', reason);
throw reason;
});
app.get('/webapp/index.php', async (req, rsp) => {
const c = req.query.c;
const a = req.query.a;
const handler = handlers[a + '@' + c];
if (handler) {
const cb = handler['cb'];
const middlewares = handler['middlewares'];
if (sessionClass) {
const session = new sessionClass(req, rsp);
middlewares.forEach(async (m) => {
await m(session);
});
await cb(session);
} else {
middlewares.forEach(async (m) => {
await m(req, rsp);
});
await cb(req, rsp);
}
} else {
utils.rspErr(rsp, 100, 'not found');
}
});
registerHandler('Ops', 'selfChecking', (req, rsp) => {
rsp.send(utils.jsonEncode({
'errcode': 0,
'errmsg': ''
}));
});
exports.init = init;
exports.listen = listen;
exports.get = get;
exports.registerHandler = registerHandler;
exports.injectionSession = injectionSession;
exports.addMiddleware = addMiddleware;
exports.useMiddleware = useMiddleware;
exports.registerDb = registerDb;
exports.getDbConn = getDbConn;

1
channel.js Normal file
View File

@ -0,0 +1 @@
exports.SELF_SDK = 6000;

18
config.js Normal file
View File

@ -0,0 +1,18 @@
const utils = require('./utils');
let loaded = false;
let configJson = null;
function config(name) {
if (!loaded) {
let configDir = './config/';
if (utils.isOnlineEnv()) {
configDir = '../config/';
}
loaded = true;
configJson = utils.readJsonFromFile(configDir + 'config.json');
}
return configJson ? configJson[name] : null;
}
module.exports = config;

155
db.js Normal file
View File

@ -0,0 +1,155 @@
const util = require("util");
const log = require("./log");
class DB {
constructor(conn) {
this.conn = conn;
}
execQuery(sql, params) {
return new Promise((resolve) => {
const ret = {
err: null,
rows: null,
};
this.conn.query(sql, params, (err, rows) => {
try {
if (err) {
ret.err = err;
resolve(ret);
log.error(util.format(
'sql:%s err:%s',
sql, err
));
} else {
ret.err = err;
ret.rows = rows;
resolve(ret);
}
} finally {
//this.conn.release();
}
});
});
}
async execQueryOne(sql, params) {
const {err, rows} = await this.execQuery(sql, params);
return {
'err': err,
'row': rows && rows.length > 0 ? rows[0] : null
};
}
async execScript(sql, params) {
const {err, rows} = await this.execQuery(sql, params);
return err;
}
async update(tblName, whereList, fieldList) {
const params = [];
let sql = 'UPDATE `' + tblName + '` SET ';
fieldList.forEach((item, index) => {
const suffix = (index + 1 < fieldList.length ? ',': '');
sql += ' `' + item[0] + '`=?' + suffix;
params.push(item[1]);
});
sql += ' WHERE 1=1';
whereList.forEach((item, index) => {
sql += ' AND ' + item[0] + '=?';
params.push(item[1]);
});
this.execScript(sql, params);
}
async insert(tblName, fieldList) {
const params = [];
let sql = 'INSERT INTO `' + tblName + '` (';
fieldList.forEach((item, index) => {
const suffix = (index + 1 < fieldList.length ? ',': '');
sql += '`' + item[0] + '`' + suffix;
});
sql += ') VALUES (';
fieldList.forEach((item, index) => {
const suffix = (index + 1 < fieldList.length ? ',': '');
sql += '?' + suffix;
params.push(item[1]);
});
sql += ')';
this.execScript(sql, params);
}
async upsert(tblName, whereList, updateList, insertList, opts = null) {
const params = [];
let sql = 'SELECT * FROM `' + tblName + '` ';
{
sql += ' WHERE 1=1';
whereList.forEach((item, index) => {
sql += ' AND ' + item[0] + '=?';
params.push(item[1]);
});
sql += ' LIMIT 1;'
}
const {err, row} = await this.execQueryOne
(
sql,
params
);
if (err) {
return;
}
if (row) {
if (opts && utils.getVal(opts, 'onQueryOk')) {
opts['onQueryOk'](row);
}
await this.update(tblName, whereList, updateList);
} else {
await this.insert(tblName, insertList);
}
}
async _delete(tblName, whereList) {
const params = [];
let sql = 'DELETE FROM `' + tblName + '` ';
sql += ' WHERE 1=1';
whereList.forEach((item, index) => {
sql += ' AND ' + item[0] + '=?';
params.push(item[1]);
});
this.execScript(sql, params);
}
async ormSelect(tblName, whereList) {
const params = [];
let sql = 'SELECT * FROM `' + tblName + '` ';
sql += ' WHERE 1=1';
whereList.forEach((item, index) => {
sql += ' AND ' + item[0] + '=?';
params.push(item[1]);
});
return this.execQuery(sql, params);
}
async ormSelectOne(tblName, whereList) {
const {err, rows} = await this.ormSelect(tblName, whereList);
return {
'err': err,
'row': rows.length > 0 ? rows[0] : null
};
}
}
module.exports = DB;

17
event.js Normal file
View File

@ -0,0 +1,17 @@
const events = require('events');
const event = new events.EventEmitter();
const APP_INITIALIZED_EVENT = '!app.initialized';
function addListener(eventName, listener) {
event.on(eventName, listener);
}
function emitEvent(eventName, ...args) {
event.emit(eventName, ...args);
}
exports.addListener = addListener;
exports.emitEvent = emitEvent;
exports.APP_INITIALIZED_EVENT = APP_INITIALIZED_EVENT;

33
log.js Normal file
View File

@ -0,0 +1,33 @@
const utils = require('./utils');
function warning(msg) {
internalLog('[WARNING]', msg);
}
function info(msg) {
internalLog('[INFO]', msg);
}
function error(msg) {
internalLog('[ERROR]', msg);
}
function alert(msg) {
internalLog('[ALERT]', msg);
}
function debug(msg) {
if (!utils.isOnlineEnv()) {
internalLog('[DEBUG]', msg);
}
}
function internalLog(logClass, msg) {
console.log(utils.formatDate(new Date()) + ' ' + logClass + ' ' + msg);
}
exports.warning = warning;
exports.info = info;
exports.alert = alert;
exports.error = error;
exports.debug = debug;

1101
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

12
package.json Normal file
View File

@ -0,0 +1,12 @@
{
"name": "j7",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {},
"dependencies": {
"crc-32": "^1.2.1",
"express": "^4.17.2",
"mysql": "~2.18.1"
}
}

40
sync.js Normal file
View File

@ -0,0 +1,40 @@
const utils = require('./utils');
class Cond {
constructor() {
this.waitList = [];
}
async wait(timeout) {
return new Promise((resolve) => {
const waitIdx = this.waitList.length;
this.waitList.push({
'resolve': resolve,
'timer': setTimeout(() => {
if (waitIdx < this.waitList.length &&
this.waitList[waitIdx]['resolve'] == resolve) {
this.waitList = this.waitList.splice(waitIdx, 1);
} else {
utils.throwError('cond waitIdx error');
}
resolve();
}, timeout)
});
});
}
notifyAll() {
if (this.waitList.length > 0) {
const waitListCopy = this.waitList;
this.waitList = [];
waitListCopy.forEach((v) => {
clearTimeout(v['timer']);
v['resolve']();
});
}
}
};
exports.Cond = Cond;

173
utils.js Normal file
View File

@ -0,0 +1,173 @@
const fs = require('fs');
const crypto = require('crypto');
const crc32 = require('crc-32');
const serverEnv = process.env['SERVER_ENV'];
function rspErr(rsp, errCode, errMsg) {
rsp.send(jsonEncode({
'errcode': errCode,
'errmsg': errMsg
}));
}
function rspOk(rsp) {
rsp.send(jsonEncode({
'errcode': 0,
'errmsg': ''
}));
}
function rspData(rsp, data) {
data['errcode'] = 0;
data['errmsg'] = '';
rsp.send(jsonEncode(data));
}
function readJsonFromFile(url) {
const jsondata = fs.readFileSync(url, "utf8");
const json = JSON.parse(jsondata);
return json;
}
async function sleep(timeout) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, timeout);
});
}
function emptyReplace(val, newVal) {
return !val ? newVal : val;
}
function throwError(msg) {
console.log(msg);
throw msg;
}
function isOnlineEnv() {
return !serverEnv;
}
function getUtcTime() {
return Math.floor((new Date()).getTime() / 1000);
}
function formatDate(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;//月份是从0开始的
const day = date.getDate();
const hour = date.getHours();
const min = date.getMinutes();
const sec = date.getSeconds();
return year + '-' +
(month < 10 ? '0' + month : month) + '-' +
(day < 10 ? '0' + day : day) + ' ' +
(hour < 10 ? '0' + hour : hour) + ':' +
(min < 10 ? '0' + min : min) + ':' +
(sec < 10 ? '0' + sec : sec);
}
function pad(num, n) {
let result = num.toString();
let len = result.length;
while (len < n) {
result = '0' + result;
len++;
}
return result;
}
function randRange(min, max) {
if (min >= max) {
return min;
}
return min + Math.random() * max;
}
function jsonEncode(obj) {
return JSON.stringify(obj);
}
function isArray(val) {
return Array.isArray(val);
}
function isObject(val) {
return typeof(obj) == "object";
}
function crc32Str(str) {
return crc32.str('' + str);
}
function createAccountId(channel, gameId, openId) {
const accountId = `${channel}_${gameId}_${openId}`;
return accountId;
}
function extractChannel(accountId) {
const ss = accountId.split('_');
return ss[0];
}
function extractGameId(accountId) {
const ss = accountId.split('_');
return ss[1];
}
function extractOpenId(accountId) {
const channel = extractChannel(accountId);
const gameId = extractGameId(accountId);
const openId = accountId.substr(accountId.indexOf(`${channel}_${gameId}_`));
return openId;
}
function createSessionId(accountId, registerTime, secretKey) {
const nowTime = getUtcTime();
const rand = randRange(1, 1000000000);
const sessionId = '' +
nowTime + '_' +
registerTime + '_' +
rand + '_' +
md5Str('' + accountId + secretKey + registerTime + nowTime);
return sessionId;
}
function md5Str(data) {
const hash = crypto.createHash('md5');
return hash.update(data).digest('hex');
}
function getVal(obj, key, defVal = null) {
if (!obj){
return val;
}
return key in obj ? obj[key] : defVal;
}
exports.rspErr = rspErr;
exports.rspOk = rspOk;
exports.rspData = rspData;
exports.readJsonFromFile = readJsonFromFile;
exports.sleep = sleep;
exports.emptyReplace = emptyReplace;
exports.throwError = throwError;
exports.isOnlineEnv = isOnlineEnv;
exports.getUtcTime = getUtcTime;
exports.formatDate = formatDate;
exports.pad = pad;
exports.randRange = randRange;
exports.jsonEncode = jsonEncode;
exports.isArray = isArray;
exports.isObject = isObject;
exports.crc32Str = crc32Str;
exports.createAccountId = createAccountId;
exports.extractChannel = extractChannel;
exports.extractGameId = extractGameId;
exports.extractOpenId = extractOpenId;
exports.createSessionId = createSessionId;
exports.md5Str = md5Str;
exports.getVal = getVal;