Skip to content

Commit c9d20f7

Browse files
author
kaiyu.kong
committed
feat: 新增koa-template
1 parent b328f78 commit c9d20f7

File tree

16 files changed

+481
-0
lines changed

16 files changed

+481
-0
lines changed

packages/koa-template/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# README
2+
3+
koa-template

packages/koa-template/package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@enode/koa-template",
3+
"version": "1.0.0",
4+
"keywords": [],
5+
"description": "",
6+
"author": "kaiyu.kong",
7+
"maintainers": [
8+
"kaiyu.kong"
9+
],
10+
"main": "template.json",
11+
"license": "MIT",
12+
"files": [
13+
"template",
14+
"template.json"
15+
],
16+
"publishConfig": {
17+
"access": "public"
18+
},
19+
"gitHead": "9a14bb5597f99422559907fa9ae33e3a75bf4818"
20+
}

packages/koa-template/template.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"package": {
3+
"description": "",
4+
"keywords": [],
5+
"license": "MIT",
6+
"private": true,
7+
"author": "",
8+
"scripts": {
9+
"dev": "DEPLOYMENT_ENV=production node scripts/dev.js ts-node --files src/index.ts",
10+
"tsc": "rimraf dist && tsc",
11+
"start": "yarn tsc && nodemon ./dist/index.js --ignore 'result'",
12+
"build-test": "yarn tsc && DEPLOYMENT_ENV=test node scripts/build.js",
13+
"build-prod": "yarn tsc && DEPLOYMENT_ENV=production node scripts/build.js"
14+
},
15+
"dependencies": {
16+
"fs-extra": "^10.0.0",
17+
"xprofiler": "^2.6.1",
18+
"clarion": "^3.9.0",
19+
"chalk": "^4.1.2",
20+
"@koa/router": "^12.0.0",
21+
"koa": "^2.14.1",
22+
"koa-bodyparser": "^4.3.0",
23+
"koa-helmet": "^6.1.0",
24+
"koa-logger": "^3.2.1",
25+
"koa2-cors": "^2.0.6"
26+
},
27+
"devDependencies": {
28+
"@types/koa": "^2.13.5",
29+
"@types/koa-bodyparser": "^4.3.10",
30+
"@types/koa-logger": "^3.1.2",
31+
"@types/koa2-cors": "^2.0.2",
32+
"@types/koa__router": "^12.0.0",
33+
"@types/node": "^18.11.18",
34+
"rimraf": "^3.0.2",
35+
"ts-node": "^10.9.1",
36+
"typescript": "^4.9.4"
37+
},
38+
"prettier": {
39+
"trailingComma": "es5",
40+
"tabWidth": 2,
41+
"semi": true,
42+
"singleQuote": false
43+
}
44+
}
45+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
*.local
13+
14+
# pm2 config file
15+
ecosystem.config.js
16+
17+
# Editor directories and files
18+
.vscode/*
19+
!.vscode/extensions.json
20+
.idea
21+
.DS_Store
22+
*.suo
23+
*.ntvs*
24+
*.njsproj
25+
*.sln
26+
*.sw?
27+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# koa-template
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports = {
2+
apps: [
3+
{
4+
name: "__PROJECT_NAME__",
5+
script: "./dist/index.js",
6+
autorestart: true,
7+
watch: false,
8+
max_memory_restart: "1G",
9+
log_date_format: "YYYY-MM-DD HH:mm:ss:SS",
10+
error_file: "/var/log/__PROJECT_NAME__/error.log",
11+
out_file: "/var/log/__PROJECT_NAME__/out.log",
12+
env: {
13+
NODE_ENV: "production",
14+
EM_LOG_DIR: "/var/log/__PROJECT_NAME__",
15+
},
16+
},
17+
{
18+
name: "__PROJECT_NAME__ xtransit process",
19+
script: "dist/emtransit.js",
20+
exec_mode: "fork",
21+
error_file: `/var/log/__PROJECT_NAME__/error.out`,
22+
out_file: `/var/log/__PROJECT_NAME__/log.out`,
23+
env: {
24+
EM_ID: "110",
25+
EM_SECRET: "xxx",
26+
EM_SOCKET: "ws://xx.xx.xx.local",
27+
EM_ERRORS: [
28+
`/var/log/__PROJECT_NAME__/error.out`, // 生产、UAT PM2 错误日志
29+
`/var/log/trace/logs/log-__PROJECT_NAME__-log.out`, // 生产、UAT XDCS 错误日志
30+
`/logs/trace/logs/log-__PROJECT_NAME__-log.out`, // 测试错误日志
31+
],
32+
EM_LOG_DIR: "/var/log/__PROJECT_NAME__",
33+
},
34+
},
35+
],
36+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports = {
2+
apps: [
3+
{
4+
name: "__PROJECT_NAME__",
5+
script: "./dist/index.js",
6+
autorestart: true,
7+
watch: false,
8+
max_memory_restart: "1G",
9+
log_date_format: "YYYY-MM-DD HH:mm:ss:SS",
10+
error_file: "/var/log/__PROJECT_NAME__/error.log",
11+
out_file: "/var/log/__PROJECT_NAME__/out.log",
12+
env: {
13+
NODE_ENV: "production",
14+
EM_LOG_DIR: "/var/log/__PROJECT_NAME__",
15+
},
16+
},
17+
{
18+
name: "__PROJECT_NAME__ xtransit process",
19+
script: "dist/emtransit.js",
20+
exec_mode: "fork",
21+
error_file: `/logs/trace/logs/log-__PROJECT_NAME__-log.out`,
22+
out_file: `/logs/trace/logs/dynamic-__PROJECT_NAME__-log.out`,
23+
env: {
24+
EM_ID: "99",
25+
EM_SECRET: "xxx",
26+
EM_SOCKET: "ws://xx.xx.xx.local",
27+
EM_ERRORS: [
28+
`/var/log/__PROJECT_NAME__/error.out`, // 生产、UAT PM2 错误日志
29+
`/var/log/trace/logs/log-__PROJECT_NAME__-log.out`, // 生产、UAT XDCS 错误日志
30+
`/logs/trace/logs/log-__PROJECT_NAME__-log.out`, // 测试错误日志
31+
],
32+
EM_LOG_DIR: "/var/log/__PROJECT_NAME__",
33+
},
34+
},
35+
],
36+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
const fs = require("fs-extra");
5+
const chalk = require("chalk"); // eslint-disable-line
6+
const pkg = require("../package.json");
7+
8+
process.on("unhandledRejection", (err) => {
9+
throw err;
10+
});
11+
12+
// 部署环境
13+
const DEPLOYMENT_ENV = process.env.DEPLOYMENT_ENV;
14+
const appDirectory = fs.realpathSync(process.cwd());
15+
16+
// 复制 pm2 配置文件
17+
const ecosystemFilePath = path.resolve(
18+
appDirectory,
19+
`ecosystem/ecosystem.config-${DEPLOYMENT_ENV}.js`
20+
);
21+
22+
if (checkRequiredFiles([ecosystemFilePath])) {
23+
console.log(chalk.cyan(`Current deploy environment: ${DEPLOYMENT_ENV}.\n`));
24+
const input = fs.readFileSync(ecosystemFilePath, "utf8");
25+
const output = input.replace(/__PROJECT_NAME__/g, pkg.name);
26+
fs.writeFileSync(
27+
path.resolve(appDirectory, "ecosystem.config.js"),
28+
output,
29+
"utf8"
30+
);
31+
fs.copy(
32+
path.resolve(appDirectory, "src/origin"),
33+
path.resolve(appDirectory, "dist/origin")
34+
);
35+
} else {
36+
process.exitCode = 1;
37+
}
38+
39+
function checkRequiredFiles(files) {
40+
let currentFilePath;
41+
try {
42+
files.forEach((filePath) => {
43+
currentFilePath = filePath;
44+
fs.accessSync(filePath, fs.F_OK);
45+
});
46+
return true;
47+
} catch (err) {
48+
const dirName = path.dirname(currentFilePath);
49+
const fileName = path.basename(currentFilePath);
50+
console.log(chalk.red("Could not find a required file."));
51+
console.log(chalk.red(" Name: ") + chalk.cyan(fileName));
52+
console.log(chalk.red(" Searched in: ") + chalk.cyan(dirName));
53+
return false;
54+
}
55+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { spawn } = require("child_process");
2+
const { apps } = require("../ecosystem/ecosystem.config-test");
3+
const pkg = require("../package.json");
4+
5+
// 读取测试环境 env
6+
const { env } = apps[0];
7+
8+
const pm2Env = Object.keys(env).reduce(
9+
(prev, key) => ({ ...prev, [key]: env[key] }),
10+
{}
11+
);
12+
13+
/**
14+
* 启动程序
15+
* @returns
16+
*/
17+
function run() {
18+
// 启动子进程,主要目的是为了和测试环境共享环境变量
19+
const [command, ...args] = process.argv.slice(2);
20+
21+
const tsNode = spawn(command, args, {
22+
stdio: "inherit",
23+
detached: true, // 可以不和主进程放在一个 process group,从而防止子进程监听到 signal 事件
24+
env: Object.assign(pm2Env, {
25+
...process.env,
26+
name: pkg.name,
27+
NODE_ENV: "development",
28+
}),
29+
});
30+
31+
const shutdown = new Promise((resolve) => {
32+
tsNode.on("exit", () => {
33+
console.log("[spawn] process ends.");
34+
resolve();
35+
});
36+
37+
tsNode.on("error", () => {
38+
console.error("[spawn] init child process error.");
39+
resolve();
40+
});
41+
});
42+
43+
return { tsNode, shutdown };
44+
}
45+
46+
const { tsNode, shutdown } = run();
47+
48+
const gracefulShutdown = async () => {
49+
tsNode.kill();
50+
await shutdown;
51+
};
52+
53+
process.on("SIGTERM", gracefulShutdown);
54+
process.on("SIGINT", gracefulShutdown);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Koa from "koa";
2+
import bodyParser from "koa-bodyparser";
3+
import helmet from "koa-helmet";
4+
import logger from "koa-logger";
5+
const cors = require("koa2-cors");
6+
import { traceIds, requestTrace, healthcheck } from "clarion";
7+
8+
import router from "./routes";
9+
10+
const app = new Koa();
11+
12+
// 初始化日志串联
13+
app.use(traceIds.koaMiddleware());
14+
// 流量监控
15+
app.use(requestTrace.koaMiddleware());
16+
// 无损发布(包含健康检查接口)
17+
app.use(healthcheck.koaMiddleware());
18+
// 请求日志
19+
app.use(logger());
20+
app.use(bodyParser());
21+
app.use(helmet({ contentSecurityPolicy: false }));
22+
app.use(cors());
23+
app.use(router.routes());
24+
app.use(router.allowedMethods());
25+
// app.use(ctx => {
26+
// ctx.body = 'Hello Koa';
27+
// });
28+
29+
export default app;

0 commit comments

Comments
 (0)