huxy-node-server 1.1.2 → 1.1.4

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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/index.js +86 -80
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huxy-node-server",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "一个精炼、高性能的 Express.js 服务器模板,为现代 Node.js 应用程序设计,提供灵活的功能和最佳实践。",
5
5
  "type": "module",
6
6
  "module": "./src/index.js",
@@ -35,12 +35,12 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "compression": "^1.8.1",
38
- "cors": "^2.8.5",
39
- "dotenv": "^17.2.3",
38
+ "cors": "^2.8.6",
39
+ "dotenv": "^17.3.1",
40
40
  "express": "^5.2.1",
41
41
  "express-rate-limit": "^8.2.1",
42
42
  "helmet": "^8.1.0",
43
- "pino": "^10.2.1",
43
+ "pino": "^10.3.1",
44
44
  "pino-http": "^11.0.0",
45
45
  "pino-pretty": "^13.1.3"
46
46
  },
package/src/index.js CHANGED
@@ -10,18 +10,18 @@ import k from 'node:net';
10
10
  var l = (t = new Date()) => t.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai', hour12: !1}),
11
11
  w = t => Object.prototype.toString.call(t).slice(8, -1).toLowerCase(),
12
12
  f = t => {
13
- let r = t ? 'https' : 'http',
13
+ let s = t ? 'https' : 'http',
14
14
  o = H.networkInterfaces(),
15
15
  e = [];
16
16
  return (Object.keys(o).map(n => e.push(...o[n])), e.filter(n => n.family === 'IPv4').map(n => n.address));
17
17
  },
18
18
  y = t => {
19
- let r = t ?? process.argv.slice(2) ?? [],
19
+ let s = t ?? process.argv.slice(2) ?? [],
20
20
  o = {};
21
21
  return (
22
- r.map(e => {
23
- let [s, n] = e.split('=');
24
- o[s] = n;
22
+ s.map(e => {
23
+ let [r, n] = e.split('=');
24
+ o[r] = n;
25
25
  }),
26
26
  o
27
27
  );
@@ -40,42 +40,42 @@ var l = (t = new Date()) => t.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
40
40
  JWT_SECRET: 'secret',
41
41
  AUTH_TOKEN: 'authToken',
42
42
  },
43
- j = (t, r, o) => {
44
- let [e, s] = t.split('.');
45
- e && s ? (o[e] || (o[e] = {}), (o[e][s] = r)) : (o[e] = r);
43
+ j = (t, s, o) => {
44
+ let [e, r] = t.split('.');
45
+ e && r ? (o[e] || (o[e] = {}), (o[e][r] = s)) : (o[e] = s);
46
46
  },
47
47
  G = t => {
48
- let {connectSrc: r, ...o} = t;
49
- if (!r) return o;
48
+ let {connectSrc: s, ...o} = t;
49
+ if (!s) return o;
50
50
  (o.helmet.contentSecurityPolicy || (o.helmet.contentSecurityPolicy = {}), o.helmet.contentSecurityPolicy.directives || (o.helmet.contentSecurityPolicy.directives = {}));
51
- let e = typeof r == 'string' ? r.split(',').map(s => s.trim()) : Array.isArray(r) ? r : [];
51
+ let e = typeof s == 'string' ? s.split(',').map(r => r.trim()) : Array.isArray(s) ? s : [];
52
52
  return ((o.helmet.contentSecurityPolicy.directives.connectSrc = [...o.helmet.contentSecurityPolicy.directives.connectSrc, ...e]), o);
53
53
  },
54
- h = (t = {}, r = U) => {
54
+ h = (t = {}, s = U) => {
55
55
  let {env: o} = process;
56
- Object.keys(r).map(s => {
57
- let n = o[s] ?? t[s];
58
- n && j(r[s], n, t);
56
+ Object.keys(s).map(r => {
57
+ let n = o[r] ?? t[r];
58
+ n && j(s[r], n, t);
59
59
  });
60
60
  let e = {...t, ...y()};
61
61
  return ((e.port = e.staticPort || e.port), (e.isDev = e.nodeEnv === 'development'), (e.protocol = 'http'), G(e));
62
62
  },
63
- g = (t, r = '127.0.0.1') =>
63
+ g = (t, s = '127.0.0.1') =>
64
64
  new Promise(o => {
65
65
  let e = k.createServer();
66
- (e.once('error', s => {
67
- (e.close(), o((s.code === 'EADDRINUSE', !1)));
66
+ (e.once('error', r => {
67
+ (e.close(), o((r.code === 'EADDRINUSE', !1)));
68
68
  }),
69
69
  e.once('listening', () => {
70
70
  (e.close(), o(!0));
71
71
  }),
72
- e.listen(Number(t), r));
72
+ e.listen(Number(t), s));
73
73
  }),
74
- I = (t, r = {}, o) => {
75
- let e = s => {
76
- (o.warn(`\u6536\u5230 ${s} \u4FE1\u53F7, \u{1F6D1} \u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668...`),
74
+ I = (t, s = {}, o) => {
75
+ let e = r => {
76
+ (o.warn(`\u6536\u5230 ${r} \u4FE1\u53F7, \u{1F6D1} \u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668...`),
77
77
  t.close(async () => {
78
- (o.info('\u{1F44B} \u670D\u52A1\u5668\u5DF2\u5173\u95ED'), await r.shutdown?.(), process.exit(0));
78
+ (o.info('\u{1F44B} \u670D\u52A1\u5668\u5DF2\u5173\u95ED'), await s.shutdown?.(), process.exit(0));
79
79
  }),
80
80
  setTimeout(() => {
81
81
  (o.error('\u274C \u5F3A\u5236\u5173\u95ED\u670D\u52A1\u5668'), process.exit(1));
@@ -83,17 +83,17 @@ var l = (t = new Date()) => t.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
83
83
  };
84
84
  (process.on('SIGTERM', () => e('SIGTERM')),
85
85
  process.on('SIGINT', () => e('SIGINT')),
86
- process.on('uncaughtException', s => {
87
- (o.fatal(s, `\u{1F4A5} \u672A\u6355\u83B7\u7684\u5F02\u5E38: ${s.message}`), process.exit(1));
86
+ process.on('uncaughtException', r => {
87
+ (o.fatal(r, `\u{1F4A5} \u672A\u6355\u83B7\u7684\u5F02\u5E38: ${r.message}`), process.exit(1));
88
88
  }),
89
- process.on('unhandledRejection', (s, n) => {
90
- (o.fatal({reason: s, promise: n}, '\u26A0\uFE0F \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD'), process.exit(1));
89
+ process.on('unhandledRejection', (r, n) => {
90
+ (o.fatal({reason: r, promise: n}, '\u26A0\uFE0F \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD'), process.exit(1));
91
91
  }));
92
92
  },
93
- L = (t, {port: r, host: o = '0.0.0.0'} = {}) =>
94
- new Promise((e, s) => {
93
+ L = (t, {port: s, host: o = '0.0.0.0'} = {}) =>
94
+ new Promise((e, r) => {
95
95
  let n = c => {
96
- (a(), s(c));
96
+ (a(), r(c));
97
97
  },
98
98
  i = () => {
99
99
  (a(), e(t));
@@ -101,102 +101,102 @@ var l = (t = new Date()) => t.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
101
101
  a = () => {
102
102
  (t.off('error', n), t.off('listening', i));
103
103
  };
104
- (t.once('error', n), t.once('listening', i), t.listen(r, o));
104
+ (t.once('error', n), t.once('listening', i), t.listen(s, o));
105
105
  }),
106
- A = (t, r = 56) => {
106
+ A = (t, s = 56) => {
107
107
  let o = t.length,
108
- e = r - o,
109
- s = ~~(e / 2);
110
- return `${'-'.repeat(s)}${t}${'-'.repeat(e - s)}`;
108
+ e = s - o,
109
+ r = ~~(e / 2);
110
+ return `${'-'.repeat(r)}${t}${'-'.repeat(e - r)}`;
111
111
  };
112
112
  var F =
113
113
  (t = {}) =>
114
- async (r = 'huxy') => {
115
- let {logLevel: o, transportOpt: e, ...s} = t,
114
+ async (s = 'huxy') => {
115
+ let {logLevel: o, transportOpt: e, ...r} = t,
116
116
  n = (await import('pino')).default,
117
117
  i = n({
118
- name: r,
118
+ name: s,
119
119
  level: o ?? 'info',
120
120
  formatters: {level: a => ({level: a})},
121
121
  timestamp: n.stdTimeFunctions.isoTime,
122
122
  base: null,
123
123
  transport: {target: 'pino-pretty', options: {colorize: !0, levelFirst: !0, ...e}, ignore: 'pid,hostname,level,time', translateTime: 'SYS:yyyy-mm-dd HH:MM:ss'},
124
- ...s,
124
+ ...r,
125
125
  });
126
126
  return ((i.isPino = !0), i);
127
127
  };
128
128
  var v = F;
129
- var $ = (t, r) => (o, e, s) => {
130
- (r.error({message: 'Not Found', timestamp: l(), url: o.originalUrl, method: o.method, ip: o.ip, userAgent: o.get('User-Agent')}, '\u627E\u4E0D\u5230\u8DEF\u5F84'),
129
+ var $ = (t, s) => (o, e, r) => {
130
+ (s.error({message: 'Not Found', timestamp: l(), url: o.originalUrl, method: o.method, ip: o.ip, userAgent: o.get('User-Agent')}, '\u627E\u4E0D\u5230\u8DEF\u5F84'),
131
131
  e.status(404).json({success: !1, status: 404, url: o.originalUrl, message: `\u8DEF\u7531 [${o.method} ${o.originalUrl}] \u4E0D\u5B58\u5728`, timestamp: l()}));
132
132
  },
133
- R = (t, r) => (o, e, s, n) => {
133
+ R = (t, s) => (o, e, r, n) => {
134
134
  let i = o.status || 500,
135
135
  a = o.message;
136
- (r.error({message: a, timestamp: l(), stack: o.stack, url: e.originalUrl, method: e.method, ip: e.ip, userAgent: e.get('User-Agent')}, '\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF'),
137
- s.status(i).json({success: !1, message: (t.isDev, a), stack: t.isDev ? o.stack : void 0, timestamp: l()}));
136
+ (s.error({message: a, timestamp: l(), stack: o.stack, url: e.originalUrl, method: e.method, ip: e.ip, userAgent: e.get('User-Agent')}, '\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF'),
137
+ r.status(i).json({success: !1, message: (t.isDev, a), stack: t.isDev ? o.stack : void 0, timestamp: l()}));
138
138
  };
139
139
  import {Router as V} from 'express';
140
140
  var W = t => {
141
- let r = V();
141
+ let s = V();
142
142
  return (
143
- r.use('/health', (o, e) => {
143
+ s.use('/health', (o, e) => {
144
144
  e.status(200).json({status: 'OK', timestamp: l(), environment: t.nodeEnv, uptime: process.uptime(), memoryUsage: process.memoryUsage(), pid: process.pid});
145
145
  }),
146
- r.get('/', (o, e) => {
146
+ s.get('/', (o, e) => {
147
147
  e.status(200).json({message: 'Node.js \u670D\u52A1\u5668\u8FD0\u884C\u4E2D', timestamp: l(), environment: t.nodeEnv});
148
148
  }),
149
- r
149
+ s
150
150
  );
151
151
  },
152
152
  b = W;
153
- var Y = async (t, r = {}, o) => {
154
- if ((t.disable('x-powered-by'), t.set('trust proxy', r.trustProxy ?? 1), o.isPino)) {
153
+ var Y = async (t, s = {}, o) => {
154
+ if ((t.disable('x-powered-by'), t.set('trust proxy', s.trustProxy ?? 1), o.isPino)) {
155
155
  let e = (await import('pino-http')).default;
156
156
  t.use(e({logger: o, quietReqLogger: !0, autoLogging: !1, genReqId: !1}));
157
157
  } else
158
- t.use((e, s, n) => {
158
+ t.use((e, r, n) => {
159
159
  e.log = o;
160
160
  });
161
161
  (t.use(Q()),
162
- t.use(K(r.helmet)),
163
- t.use(z(r.cors)),
164
- t.use(r.apiPrefix, B({keyGenerator: e => X(e.ip) || e.headers['x-huxy-auth'] || e.headers['x-api-key'] || e.headers.authorization, ...r.rateLimit})),
162
+ t.use(K(s.helmet)),
163
+ t.use(z(s.cors)),
164
+ s.isStatic || t.use(s.apiPrefix, B({keyGenerator: e => X(e.ip) || e.headers['x-huxy-auth'] || e.headers['x-api-key'] || e.headers.authorization, ...s.rateLimit})),
165
165
  t.use(T.json({limit: '20mb'})),
166
166
  t.use(T.urlencoded({extended: !0, limit: '20mb'})));
167
167
  },
168
- Z = (t, r = {}, o) => {
169
- (t.use(b(r)), t.use($(r, o)), t.use(R(r, o)));
168
+ Z = (t, s = {}, o) => {
169
+ (t.use(b(s)), t.use($(s, o)), t.use(R(s, o)));
170
170
  },
171
- q = async (t = {}, r) => {
171
+ q = async (t = {}, s) => {
172
172
  let {logger: o, ...e} = h(t),
173
- s = o ?? (await v(e.loggerConfig)('huxy')),
173
+ r = o ?? (await v(e.loggerConfig)('huxy')),
174
174
  {port: n, ssl: i} = e;
175
- (await g(n, e.host)) || ((e.port = Number(n) + 1), s.warn(`\u7AEF\u53E3 ${n} \u5DF2\u88AB\u5360\u7528\uFF0C\u73B0\u5728\u4F7F\u7528\u7AEF\u53E3 ${e.port}`));
175
+ (await g(n, e.host)) || ((e.port = Number(n) + 1), r.warn(`\u7AEF\u53E3 ${n} \u5DF2\u88AB\u5360\u7528\uFF0C\u73B0\u5728\u4F7F\u7528\u7AEF\u53E3 ${e.port}`));
176
176
  let c = T();
177
- await Y(c, e, s);
177
+ await Y(c, e, r);
178
178
  let p;
179
179
  (i
180
180
  ? (w(i) === 'object' ||
181
- (s.error({ssl: {key: '/path/to/name.key', cert: '/path/to/name.pem'}}, '\u26A0\uFE0F \u8BF7\u8BBE\u7F6E\u6709\u6548 SSL \u6216\u8BBE\u7F6E {ssl: false}'), process.exit(1)),
181
+ (r.error({ssl: {key: '/path/to/name.key', cert: '/path/to/name.pem'}}, '\u26A0\uFE0F \u8BF7\u8BBE\u7F6E\u6709\u6548 SSL \u6216\u8BBE\u7F6E {ssl: false}'), process.exit(1)),
182
182
  (e.protocol = 'https'),
183
183
  (p = J.createServer(i, c)),
184
184
  O((u, d) => {
185
185
  (d.writeHead(301, {Location: `${e.protocol}://${u.headers.host}${u.url}`}), d.end());
186
186
  }).listen(80))
187
187
  : (p = O(c)),
188
- I(p, e, s));
188
+ I(p, e, r));
189
189
  try {
190
190
  await L(p, e);
191
191
  } catch (m) {
192
- (s.error({err: m}, '\u26A0\uFE0F \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25'), process.exit(1));
192
+ (r.error({err: m}, '\u26A0\uFE0F \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25'), process.exit(1));
193
193
  }
194
194
  try {
195
- await r?.(e, c, p, s);
195
+ await s?.(e, c, p, r);
196
196
  } catch (m) {
197
- (s.error({err: m}, `\u274C \u56DE\u8C03\u51FD\u6570\u9519\u8BEF\uFF1A${m.message}`), process.exit(1));
197
+ (r.error({err: m}, `\u274C \u56DE\u8C03\u51FD\u6570\u9519\u8BEF\uFF1A${m.message}`), process.exit(1));
198
198
  }
199
- return (Z(c, e, s), {app: c, httpServer: p, config: e, logger: s});
199
+ return (Z(c, e, r), {app: c, httpServer: p, config: e, logger: r});
200
200
  },
201
201
  _ = q;
202
202
  import 'dotenv';
@@ -204,26 +204,32 @@ var ee = {
204
204
  nodeEnv: process.env.NODE_ENV || 'development',
205
205
  isDev: process.env.NODE_ENV === 'development',
206
206
  port: parseInt(process.env.PORT || '3000', 10),
207
- host: process.env.HOST || '0.0.0.0',
207
+ host: process.env.HOST || 'localhost',
208
208
  basepath: process.env.BASEPATH || '/',
209
209
  apiPrefix: '/',
210
- cors: {origin: process.env.CORS_ORIGIN?.split(',') || '*', credentials: !0},
210
+ cors: {origin: process.env.CORS_ORIGIN?.split(',') || '*'},
211
211
  rateLimit: {
212
212
  windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '300000', 10),
213
- limit: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '500', 10),
213
+ limit: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '150', 10),
214
214
  message: {message: '\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5'},
215
215
  },
216
216
  helmet: {
217
217
  contentSecurityPolicy: {
218
- directives: {defaultSrc: ["'self'"], connectSrc: ['*'], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'", "'unsafe-eval'"], imgSrc: ["'self'", 'data:', 'https:']},
218
+ directives: {
219
+ defaultSrc: ["'self'"],
220
+ connectSrc: ['*'],
221
+ styleSrc: ["'self'", "'unsafe-inline'"],
222
+ scriptSrc: ["'self'", "'unsafe-eval'", "'unsafe-inline'"],
223
+ imgSrc: ["'self'", 'data:', 'https:'],
224
+ },
219
225
  },
220
226
  crossOriginEmbedderPolicy: !1,
221
227
  },
222
228
  logLevel: process.env.LOG_LEVEL || 30,
223
229
  },
224
230
  N = ee;
225
- var te = (t, r, o) =>
226
- _({...N, ...t}, async (e, s, n, i) => {
231
+ var te = (t, s, o) =>
232
+ _({...N, ...t}, async (e, r, n, i) => {
227
233
  let {port: a, host: c, nodeEnv: p, basepath: m, appName: u = 'HuxyServer', protocol: d} = e;
228
234
  if (!o) {
229
235
  let D = f()
@@ -234,20 +240,20 @@ var te = (t, r, o) =>
234
240
  i.info(`-----------------[${l()}]------------------`),
235
241
  i.info({ips: D}, '\u672C\u5730\u5730\u5740'));
236
242
  }
237
- await r?.(e, s, n, i);
243
+ await s?.(e, r, n, i);
238
244
  }),
239
245
  x = te;
240
246
  import ne from 'express';
241
247
  import {fileURLToPath as oe} from 'node:url';
242
- import {dirname as re, resolve as se} from 'node:path';
243
- var E = (t = import.meta.url) => re(oe(t)),
244
- P = (...t) => se(E(), ...t),
248
+ import {dirname as se, resolve as re} from 'node:path';
249
+ var E = (t = import.meta.url) => se(oe(t)),
250
+ P = (...t) => re(E(), ...t),
245
251
  C = P;
246
- var ie = {port: 9e3, host: 'localhost', basepath: '/', buildPath: './build'},
252
+ var ie = {port: 9e3, host: 'localhost', basepath: '/', buildPath: './build', isStatic: !0},
247
253
  ae = t => (t ? (t.endsWith('/') ? t : `${t}/`) : '/'),
248
- ce = (t, r) =>
249
- x({...ie, ...t}, async (o, e, s, n) => {
250
- await r?.(o, e, s, n);
254
+ ce = (t, s) =>
255
+ x({...ie, ...t}, async (o, e, r, n) => {
256
+ await s?.(o, e, r, n);
251
257
  let {basepath: i, buildPath: a} = o;
252
258
  (i !== '/' &&
253
259
  e.get('/', (m, u, d) => {