@jayfong/x-server 2.57.1 → 2.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_cjs/core/ctx_storage.js +6 -0
- package/lib/_cjs/core/handler.js +4 -2
- package/lib/_cjs/core/server.js +11 -8
- package/lib/_cjs/plugins/cors.js +1 -0
- package/lib/_cjs/services/log.js +8 -2
- package/lib/_cjs/x.js +4 -0
- package/lib/core/ctx_storage.d.ts +4 -0
- package/lib/core/ctx_storage.js +2 -0
- package/lib/core/handler.js +4 -2
- package/lib/core/server.js +3 -0
- package/lib/core/types.d.ts +4 -0
- package/lib/plugins/cors.js +1 -0
- package/lib/services/log.d.ts +1 -0
- package/lib/services/log.js +8 -2
- package/lib/x.d.ts +2 -0
- package/lib/x.js +4 -0
- package/package.json +1 -1
package/lib/_cjs/core/handler.js
CHANGED
|
@@ -10,6 +10,7 @@ var vae = _interopRequireWildcard(require("vtils/vae"));
|
|
|
10
10
|
var _validator = require("vtils/validator");
|
|
11
11
|
var _http_error = require("../core/http_error");
|
|
12
12
|
var _dispose = require("../services/dispose");
|
|
13
|
+
var _ctx_storage = require("./ctx_storage");
|
|
13
14
|
var _http_redirect = require("./http_redirect");
|
|
14
15
|
var _server = require("./server");
|
|
15
16
|
_validator.yup.setLocale((0, _validator.getZhCN)({
|
|
@@ -25,10 +26,11 @@ class Handler {
|
|
|
25
26
|
if (Handler.hooks.length) {
|
|
26
27
|
await Promise.all(Handler.hooks.map(hook => hook(this.options, data, ctx)));
|
|
27
28
|
}
|
|
29
|
+
ctx.setHeader('x-trace-id', ctx.traceId);
|
|
28
30
|
if (this.options.requestMethod === 'WS') {
|
|
29
|
-
return this.handleWs(data, ctx);
|
|
31
|
+
return _ctx_storage.ctxStorage.run(ctx, () => this.handleWs(data, ctx));
|
|
30
32
|
}
|
|
31
|
-
return this.handleHttp(data, ctx);
|
|
33
|
+
return _ctx_storage.ctxStorage.run(ctx, () => this.handleHttp(data, ctx));
|
|
32
34
|
};
|
|
33
35
|
this.handleHttp = async (data, ctx) => {
|
|
34
36
|
// 请求数据解析
|
package/lib/_cjs/core/server.js
CHANGED
|
@@ -7,7 +7,8 @@ var _interopRequireWildcard2 = _interopRequireDefault(require("@babel/runtime/he
|
|
|
7
7
|
var _nodeProcess = _interopRequireDefault(require("node:process"));
|
|
8
8
|
var _fastify = _interopRequireDefault(require("fastify"));
|
|
9
9
|
var _vtils = require("vtils");
|
|
10
|
-
var _x = require("
|
|
10
|
+
var _x = require("vtils/x");
|
|
11
|
+
var _x2 = require("../x");
|
|
11
12
|
var _http_error = require("./http_error");
|
|
12
13
|
var _http_method = require("./http_method");
|
|
13
14
|
class Server {
|
|
@@ -66,7 +67,7 @@ class Server {
|
|
|
66
67
|
await Promise.resolve().then(() => (0, _interopRequireWildcard2.default)(require('.x/hooks')));
|
|
67
68
|
}
|
|
68
69
|
applyServices() {
|
|
69
|
-
|
|
70
|
+
_x2.x.register(...(this.options.services || []));
|
|
70
71
|
}
|
|
71
72
|
applyPlugins() {
|
|
72
73
|
const plugins = this.options.plugins || [];
|
|
@@ -76,7 +77,7 @@ class Server {
|
|
|
76
77
|
}
|
|
77
78
|
async applyRoutes() {
|
|
78
79
|
await this.fastify.register(async fastify => {
|
|
79
|
-
const appUrl =
|
|
80
|
+
const appUrl = _x2.x.env.APP_URL.replace(/\/+$/, '');
|
|
80
81
|
const routeMap = (0, _vtils.keyBy)(this.routes, item => item.path);
|
|
81
82
|
const handleRoute = async (item, req, res, path) => {
|
|
82
83
|
const handlerOptions = item.handler.options;
|
|
@@ -86,6 +87,7 @@ class Server {
|
|
|
86
87
|
path != null ? path : isWS ? res.url : req.url}`;
|
|
87
88
|
if (isWS) {
|
|
88
89
|
await item.handler.handle(undefined, {
|
|
90
|
+
traceId: (0, _x.cuid2)(),
|
|
89
91
|
url: url,
|
|
90
92
|
headers: res.headers,
|
|
91
93
|
setHeader: _vtils.noop,
|
|
@@ -113,6 +115,7 @@ class Server {
|
|
|
113
115
|
...req.body,
|
|
114
116
|
...files
|
|
115
117
|
}, {
|
|
118
|
+
traceId: (0, _x.cuid2)(),
|
|
116
119
|
url,
|
|
117
120
|
headers: req.headers,
|
|
118
121
|
setHeader: (k, v) => res.header(k, v),
|
|
@@ -168,11 +171,11 @@ class Server {
|
|
|
168
171
|
url: '/$',
|
|
169
172
|
handler: async req => {
|
|
170
173
|
const payload = req.body;
|
|
171
|
-
if (payload && typeof payload === 'object' &&
|
|
174
|
+
if (payload && typeof payload === 'object' && _x2.x.env.APP_TOKEN && payload.token === _x2.x.env.APP_TOKEN) {
|
|
172
175
|
if (payload.type === 'ping') {
|
|
173
176
|
return 'ping:success';
|
|
174
177
|
} else if (payload.type === 'updateEnv') {
|
|
175
|
-
Object.assign(
|
|
178
|
+
Object.assign(_x2.x.env, payload.data);
|
|
176
179
|
|
|
177
180
|
// 更新静态文件服务
|
|
178
181
|
this.applyStatic();
|
|
@@ -183,8 +186,8 @@ class Server {
|
|
|
183
186
|
});
|
|
184
187
|
}
|
|
185
188
|
async applyStatic() {
|
|
186
|
-
if (Array.isArray(
|
|
187
|
-
const staticContent =
|
|
189
|
+
if (Array.isArray(_x2.x.env.APP_STATIC_CONTENT)) {
|
|
190
|
+
const staticContent = _x2.x.env.APP_STATIC_CONTENT;
|
|
188
191
|
for (const item of staticContent) {
|
|
189
192
|
if (!item.method) {
|
|
190
193
|
item.method = 'GET';
|
|
@@ -212,7 +215,7 @@ class Server {
|
|
|
212
215
|
await Promise.resolve().then(() => (0, _interopRequireWildcard2.default)(require('.x/crons')));
|
|
213
216
|
}
|
|
214
217
|
async applyAutoClose() {
|
|
215
|
-
|
|
218
|
+
_x2.x.dispose.add(() => this.close());
|
|
216
219
|
}
|
|
217
220
|
}
|
|
218
221
|
exports.Server = Server;
|
package/lib/_cjs/plugins/cors.js
CHANGED
|
@@ -30,6 +30,7 @@ class CorsPlugin {
|
|
|
30
30
|
fastify.register(_cors.default, {
|
|
31
31
|
origin: (origin, cb) => allowAll ? cb(null, true) : cb(null, origin ? check(origin) : true),
|
|
32
32
|
maxAge: (0, _vtils.ms)(this.options.ttl, true),
|
|
33
|
+
exposedHeaders: ['x-trace-id'],
|
|
33
34
|
...(0, _vtils.omitStrict)(this.options, ['allow', 'ttl'])
|
|
34
35
|
});
|
|
35
36
|
}
|
package/lib/_cjs/services/log.js
CHANGED
|
@@ -74,9 +74,15 @@ class LogService {
|
|
|
74
74
|
return this.getLogFile(new Date());
|
|
75
75
|
}
|
|
76
76
|
parseLogLineText(text, keysMap = {}) {
|
|
77
|
-
const
|
|
77
|
+
const segments = text.split(/\t+/);
|
|
78
|
+
// 没有 traceId 的注入一下
|
|
79
|
+
if (segments[1].length < 10) {
|
|
80
|
+
segments.splice(1, 0, '');
|
|
81
|
+
}
|
|
82
|
+
const [time, traceId, level, title, ...desc] = segments;
|
|
78
83
|
return {
|
|
79
84
|
time: time,
|
|
85
|
+
traceId: traceId,
|
|
80
86
|
level: level,
|
|
81
87
|
title: title,
|
|
82
88
|
desc: desc.reduce((res, item, index) => {
|
|
@@ -91,7 +97,7 @@ class LogService {
|
|
|
91
97
|
};
|
|
92
98
|
}
|
|
93
99
|
log(payload) {
|
|
94
|
-
const getContent = () => `${[(0, _date.formatDate)(new Date(), 'yyyy-mm-dd hh:ii:ss'), payload.level, payload.title, ...(!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map(key => `${key}:${payload.desc[key]}`))].map(item => String(item).replace(/[\r\n\t]+/g, ' ')).join('\t')}`;
|
|
100
|
+
const getContent = () => `${[(0, _date.formatDate)(new Date(), 'yyyy-mm-dd hh:ii:ss'), ...(!_x.x.ctx ? [] : [_x.x.ctx.traceId]), payload.level, payload.title, ...(!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map(key => `${key}:${payload.desc[key]}`))].map(item => String(item).replace(/[\r\n\t]+/g, ' ')).join('\t')}`;
|
|
95
101
|
if (payload.writer === 'console') {
|
|
96
102
|
console[payload.level === 'error' ? 'error' : 'log'](getContent());
|
|
97
103
|
} else {
|
package/lib/_cjs/x.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.x = void 0;
|
|
|
6
6
|
var _os = _interopRequireDefault(require("os"));
|
|
7
7
|
var _path = _interopRequireDefault(require("path"));
|
|
8
8
|
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
9
|
+
var _ctx_storage = require("./core/ctx_storage");
|
|
9
10
|
var _db_value = require("./services/db_value");
|
|
10
11
|
var _dispose = require("./services/dispose");
|
|
11
12
|
var _emoji = require("./services/emoji");
|
|
@@ -15,6 +16,9 @@ const x = exports.x = {
|
|
|
15
16
|
appId: env.APP_ID,
|
|
16
17
|
env: env,
|
|
17
18
|
dataDir: _path.default.join(_os.default.homedir(), `.xs/${env.APP_ID}`),
|
|
19
|
+
get ctx() {
|
|
20
|
+
return _ctx_storage.ctxStorage.getStore();
|
|
21
|
+
},
|
|
18
22
|
register: (...services) => {
|
|
19
23
|
for (const service of services) {
|
|
20
24
|
// @ts-ignore
|
package/lib/core/handler.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as vae from 'vtils/vae';
|
|
|
4
4
|
import { getZhCN, yup } from 'vtils/validator';
|
|
5
5
|
import { HttpError } from "../core/http_error";
|
|
6
6
|
import { DisposeService } from "../services/dispose";
|
|
7
|
+
import { ctxStorage } from "./ctx_storage";
|
|
7
8
|
import { HttpRedirect } from "./http_redirect";
|
|
8
9
|
import { Server } from "./server";
|
|
9
10
|
yup.setLocale(getZhCN({
|
|
@@ -19,10 +20,11 @@ export class Handler {
|
|
|
19
20
|
if (Handler.hooks.length) {
|
|
20
21
|
await Promise.all(Handler.hooks.map(hook => hook(this.options, data, ctx)));
|
|
21
22
|
}
|
|
23
|
+
ctx.setHeader('x-trace-id', ctx.traceId);
|
|
22
24
|
if (this.options.requestMethod === 'WS') {
|
|
23
|
-
return this.handleWs(data, ctx);
|
|
25
|
+
return ctxStorage.run(ctx, () => this.handleWs(data, ctx));
|
|
24
26
|
}
|
|
25
|
-
return this.handleHttp(data, ctx);
|
|
27
|
+
return ctxStorage.run(ctx, () => this.handleHttp(data, ctx));
|
|
26
28
|
};
|
|
27
29
|
this.handleHttp = async (data, ctx) => {
|
|
28
30
|
// 请求数据解析
|
package/lib/core/server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import Fastify from 'fastify';
|
|
3
3
|
import { base64UrlDecode, castArray, keyBy, noop, rot13 } from 'vtils';
|
|
4
|
+
import { cuid2 } from 'vtils/x';
|
|
4
5
|
import { x } from "../x";
|
|
5
6
|
import { HttpError } from "./http_error";
|
|
6
7
|
import { HandlerMethodToHttpMethod } from "./http_method";
|
|
@@ -80,6 +81,7 @@ export class Server {
|
|
|
80
81
|
path != null ? path : isWS ? res.url : req.url}`;
|
|
81
82
|
if (isWS) {
|
|
82
83
|
await item.handler.handle(undefined, {
|
|
84
|
+
traceId: cuid2(),
|
|
83
85
|
url: url,
|
|
84
86
|
headers: res.headers,
|
|
85
87
|
setHeader: noop,
|
|
@@ -107,6 +109,7 @@ export class Server {
|
|
|
107
109
|
...req.body,
|
|
108
110
|
...files
|
|
109
111
|
}, {
|
|
112
|
+
traceId: cuid2(),
|
|
110
113
|
url,
|
|
111
114
|
headers: req.headers,
|
|
112
115
|
setHeader: (k, v) => res.header(k, v),
|
package/lib/core/types.d.ts
CHANGED
package/lib/plugins/cors.js
CHANGED
|
@@ -26,6 +26,7 @@ export class CorsPlugin {
|
|
|
26
26
|
fastify.register(FastifyCors, {
|
|
27
27
|
origin: (origin, cb) => allowAll ? cb(null, true) : cb(null, origin ? check(origin) : true),
|
|
28
28
|
maxAge: ms(this.options.ttl, true),
|
|
29
|
+
exposedHeaders: ['x-trace-id'],
|
|
29
30
|
...omitStrict(this.options, ['allow', 'ttl'])
|
|
30
31
|
});
|
|
31
32
|
}
|
package/lib/services/log.d.ts
CHANGED
package/lib/services/log.js
CHANGED
|
@@ -69,9 +69,15 @@ export class LogService {
|
|
|
69
69
|
return this.getLogFile(new Date());
|
|
70
70
|
}
|
|
71
71
|
parseLogLineText(text, keysMap = {}) {
|
|
72
|
-
const
|
|
72
|
+
const segments = text.split(/\t+/);
|
|
73
|
+
// 没有 traceId 的注入一下
|
|
74
|
+
if (segments[1].length < 10) {
|
|
75
|
+
segments.splice(1, 0, '');
|
|
76
|
+
}
|
|
77
|
+
const [time, traceId, level, title, ...desc] = segments;
|
|
73
78
|
return {
|
|
74
79
|
time: time,
|
|
80
|
+
traceId: traceId,
|
|
75
81
|
level: level,
|
|
76
82
|
title: title,
|
|
77
83
|
desc: desc.reduce((res, item, index) => {
|
|
@@ -86,7 +92,7 @@ export class LogService {
|
|
|
86
92
|
};
|
|
87
93
|
}
|
|
88
94
|
log(payload) {
|
|
89
|
-
const getContent = () => `${[formatDate(new Date(), 'yyyy-mm-dd hh:ii:ss'), payload.level, payload.title, ...(!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map(key => `${key}:${payload.desc[key]}`))].map(item => String(item).replace(/[\r\n\t]+/g, ' ')).join('\t')}`;
|
|
95
|
+
const getContent = () => `${[formatDate(new Date(), 'yyyy-mm-dd hh:ii:ss'), ...(!x.ctx ? [] : [x.ctx.traceId]), payload.level, payload.title, ...(!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map(key => `${key}:${payload.desc[key]}`))].map(item => String(item).replace(/[\r\n\t]+/g, ' ')).join('\t')}`;
|
|
90
96
|
if (payload.writer === 'console') {
|
|
91
97
|
console[payload.level === 'error' ? 'error' : 'log'](getContent());
|
|
92
98
|
} else {
|
package/lib/x.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { XHandler } from './core/types';
|
|
2
3
|
import { BaseService } from './services/base';
|
|
3
4
|
import './services/db_value';
|
|
4
5
|
import './services/dispose';
|
|
@@ -8,6 +9,7 @@ export interface X {
|
|
|
8
9
|
readonly appId: string;
|
|
9
10
|
readonly env: NodeJS.ProcessEnv;
|
|
10
11
|
readonly dataDir: string;
|
|
12
|
+
readonly ctx: XHandler.Context;
|
|
11
13
|
readonly register: (...services: BaseService[]) => void;
|
|
12
14
|
}
|
|
13
15
|
export declare const x: X;
|
package/lib/x.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
|
+
import { ctxStorage } from "./core/ctx_storage";
|
|
4
5
|
import { DbValueService } from "./services/db_value";
|
|
5
6
|
import { DisposeService } from "./services/dispose";
|
|
6
7
|
import { EmojiService } from "./services/emoji";
|
|
@@ -10,6 +11,9 @@ export const x = {
|
|
|
10
11
|
appId: env.APP_ID,
|
|
11
12
|
env: env,
|
|
12
13
|
dataDir: path.join(os.homedir(), `.xs/${env.APP_ID}`),
|
|
14
|
+
get ctx() {
|
|
15
|
+
return ctxStorage.getStore();
|
|
16
|
+
},
|
|
13
17
|
register: (...services) => {
|
|
14
18
|
for (const service of services) {
|
|
15
19
|
// @ts-ignore
|