huxy-node-server 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +106 -110
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huxy-node-server",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "一个精炼、高性能的 Express.js 服务器模板,为现代 Node.js 应用程序设计,提供灵活的功能和最佳实践。",
5
5
  "type": "module",
6
6
  "module": "./src/index.js",
package/src/index.js CHANGED
@@ -1,27 +1,27 @@
1
- import T from 'express';
2
- import W from 'helmet';
3
- import K from 'cors';
4
- import {rateLimit as z, ipKeyGenerator as X} from 'express-rate-limit';
5
- import B from 'compression';
6
- import Q from 'pino-http';
7
- import {createServer as J} from 'node:http';
8
- import w from 'pino';
9
- import C from 'node:os';
10
- import k from 'node:net';
1
+ import S from 'express';
2
+ import K from 'helmet';
3
+ import z from 'cors';
4
+ import {rateLimit as B, ipKeyGenerator as X} from 'express-rate-limit';
5
+ import Q from 'compression';
6
+ import J from 'pino-http';
7
+ import {createServer as Y} from 'node:http';
8
+ import A from 'pino';
9
+ import k from 'node:os';
10
+ import C from 'node:net';
11
11
  var c = (e = new Date()) => e.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai', hour12: !1}),
12
12
  d = e => {
13
13
  let o = e ? 'https' : 'http',
14
- t = C.networkInterfaces(),
14
+ t = k.networkInterfaces(),
15
15
  r = [];
16
16
  return (Object.keys(t).map(n => r.push(...t[n])), r.filter(n => n.family === 'IPv4').map(n => `${o}://${n.address}`));
17
17
  },
18
- E = e => {
18
+ T = e => {
19
19
  let o = e ?? process.argv.slice(2) ?? [],
20
20
  t = {};
21
21
  return (
22
22
  o.map(r => {
23
- let [s, a] = r.split('=');
24
- t[s] = a;
23
+ let [s, i] = r.split('=');
24
+ t[s] = i;
25
25
  }),
26
26
  t
27
27
  );
@@ -44,18 +44,19 @@ var c = (e = new Date()) => e.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
44
44
  let [r, s] = e.split('.');
45
45
  r && s ? (t[r] || (t[r] = {}), (t[r][s] = o)) : (t[r] = o);
46
46
  },
47
+ j = e => (e ? (e.endsWith('/') ? e : `${e}/`) : '/'),
47
48
  f = (e = {}, o = U) => {
48
49
  let {env: t} = process;
49
50
  Object.keys(o).map(s => {
50
- let a = t[s] ?? e[s];
51
- a && G(o[s], a, e);
51
+ let i = t[s] ?? e[s];
52
+ i && G(o[s], i, e);
52
53
  });
53
- let r = {...e, ...E()};
54
- return ((r.port = r.staticPort || r.port), (r.isDev = r.NODE_ENV === 'development'), r);
54
+ let r = {...e, ...T()};
55
+ return ((r.port = r.staticPort || r.port), (r.isDev = r.NODE_ENV === 'development'), (r.basepath = j(r.basepath)), r);
55
56
  },
56
57
  h = (e, o = '127.0.0.1') =>
57
58
  new Promise(t => {
58
- let r = k.createServer();
59
+ let r = C.createServer();
59
60
  (r.once('error', s => {
60
61
  (r.close(), t((s.code === 'EADDRINUSE', !1)));
61
62
  }),
@@ -64,7 +65,7 @@ var c = (e = new Date()) => e.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
64
65
  }),
65
66
  r.listen(Number(e), o));
66
67
  }),
67
- I = (e, o = {}, t) => {
68
+ y = (e, o = {}, t) => {
68
69
  let r = s => {
69
70
  (t.warn(`\u6536\u5230 ${s} \u4FE1\u53F7, \u{1F6D1} \u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668...`),
70
71
  e.close(async () => {
@@ -79,25 +80,25 @@ var c = (e = new Date()) => e.toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'
79
80
  process.on('uncaughtException', s => {
80
81
  (t.fatal(s, `\u{1F4A5} \u672A\u6355\u83B7\u7684\u5F02\u5E38: ${s.message}`), process.exit(1));
81
82
  }),
82
- process.on('unhandledRejection', (s, a) => {
83
- (t.fatal({reason: s, promise: a}, '\u26A0\uFE0F \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD'), process.exit(1));
83
+ process.on('unhandledRejection', (s, i) => {
84
+ (t.fatal({reason: s, promise: i}, '\u26A0\uFE0F \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD'), process.exit(1));
84
85
  }));
85
86
  },
86
- A = (e, {port: o, host: t = '0.0.0.0'} = {}) =>
87
+ w = (e, {port: o, host: t = '0.0.0.0'} = {}) =>
87
88
  new Promise((r, s) => {
88
- let a = p => {
89
- (i(), s(p));
89
+ let i = p => {
90
+ (a(), s(p));
90
91
  },
91
92
  n = () => {
92
- (i(), r(e));
93
+ (a(), r(e));
93
94
  },
94
- i = () => {
95
- (e.off('error', a), e.off('listening', n));
95
+ a = () => {
96
+ (e.off('error', i), e.off('listening', n));
96
97
  };
97
- (e.once('error', a), e.once('listening', n), e.listen(o, t));
98
+ (e.once('error', i), e.once('listening', n), e.listen(o, t));
98
99
  });
99
100
  import 'dotenv';
100
- var j = {
101
+ var F = {
101
102
  nodeEnv: process.env.NODE_ENV || 'development',
102
103
  isDev: process.env.NODE_ENV === 'development',
103
104
  port: parseInt(process.env.PORT || '3000', 10),
@@ -116,141 +117,136 @@ var j = {
116
117
  },
117
118
  logLevel: process.env.LOG_LEVEL || 30,
118
119
  },
119
- g = j;
120
+ g = F;
120
121
  var u = (e, o) =>
121
- w({
122
+ A({
122
123
  name: e,
123
124
  level: g.logLevel,
124
125
  formatters: {level: t => ({level: t})},
125
- timestamp: w.stdTimeFunctions.isoTime,
126
+ timestamp: A.stdTimeFunctions.isoTime,
126
127
  base: null,
127
128
  transport: {target: 'pino-pretty', options: {colorize: !0, sync: !0, levelFirst: !0}, ignore: 'pid,hostname,level,time', translateTime: 'SYS:yyyy-mm-dd HH:MM:ss'},
128
129
  ...o,
129
130
  });
130
131
  var m = u('huxy');
131
132
  var L = u('error-handler'),
132
- b = e => (o, t, r) => {
133
+ R = e => (o, t, r) => {
133
134
  (L.error({message: 'Not Found', timestamp: c(), url: o.originalUrl, method: o.method, ip: o.ip, userAgent: o.get('User-Agent')}, '\u627E\u4E0D\u5230\u8DEF\u5F84'),
134
- t.status(404).json({success: !1, timestamp: c(), status: 404, message: `\u8DEF\u7531 ${o.method} ${o.originalUrl} \u4E0D\u5B58\u5728`, url: o.originalUrl}));
135
+ t.status(404).json({success: !1, status: 404, url: o.originalUrl, message: `\u8DEF\u7531 [${o.method} ${o.originalUrl}] \u4E0D\u5B58\u5728`, timestamp: c()}));
135
136
  },
136
- R = e => (o, t, r, s) => {
137
- let a = o.status || 500,
137
+ $ = e => (o, t, r, s) => {
138
+ let i = o.status || 500,
138
139
  n = o.message;
139
140
  (L.error({message: n, timestamp: c(), stack: o.stack, url: t.originalUrl, method: t.method, ip: t.ip, userAgent: t.get('User-Agent')}, '\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF'),
140
- r.status(a).json({success: !1, timestamp: c(), message: e.isDev ? n : '\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF', stack: e.isDev ? o.stack : void 0}));
141
+ r.status(i).json({success: !1, message: (e.isDev, n), stack: e.isDev ? o.stack : void 0, timestamp: c()}));
141
142
  };
142
- var N = e => (o, t, r) => {
143
+ var b = e => (o, t, r) => {
143
144
  (t.set('Cache-Control', `public, max-age=${e.cacheMaxAge ?? 300}, stale-while-revalidate=60`), r());
144
145
  };
145
- import {Router as F} from 'express';
146
- var V = e => {
147
- let o = F();
146
+ import {Router as V} from 'express';
147
+ var W = e => {
148
+ let o = V();
148
149
  return (
149
150
  o.use('/health', (t, r) => {
150
151
  r.status(200).json({status: 'OK', timestamp: c(), environment: e.nodeEnv, uptime: process.uptime(), memoryUsage: process.memoryUsage(), pid: process.pid});
151
152
  }),
152
- o.get('/status', (t, r) => {
153
+ o.get('/', (t, r) => {
153
154
  r.status(200).json({message: 'Node.js \u670D\u52A1\u5668\u8FD0\u884C\u4E2D', timestamp: c(), environment: e.nodeEnv});
154
155
  }),
155
156
  o
156
157
  );
157
158
  },
158
- _ = V;
159
- var Y = (e, o = {}) => {
159
+ N = W;
160
+ var Z = (e, o = {}) => {
160
161
  (e.disable('x-powered-by'),
161
162
  e.set('trust proxy', 1),
162
- e.use(Q({logger: m, quietReqLogger: !0, autoLogging: !1, genReqId: !1})),
163
- e.use(B()),
164
- e.use(W(o.helmet)),
165
- e.use(K(o.cors)),
166
- e.use(o.apiPrefix, z({keyGenerator: t => X(t.ip) || t.headers['x-huxy-auth'] || t.headers['x-api-key'] || t.headers.authorization, ...o.rateLimit})),
167
- e.use(T.json({limit: '20mb'})),
168
- e.use(T.urlencoded({extended: !0, limit: '20mb'})),
169
- e.use(o.apiPrefix, N(o)));
163
+ e.use(J({logger: m, quietReqLogger: !0, autoLogging: !1, genReqId: !1})),
164
+ e.use(Q()),
165
+ e.use(K(o.helmet)),
166
+ e.use(z(o.cors)),
167
+ e.use(o.apiPrefix, B({keyGenerator: t => X(t.ip) || t.headers['x-huxy-auth'] || t.headers['x-api-key'] || t.headers.authorization, ...o.rateLimit})),
168
+ e.use(S.json({limit: '20mb'})),
169
+ e.use(S.urlencoded({extended: !0, limit: '20mb'})),
170
+ e.use(o.apiPrefix, b(o)));
170
171
  },
171
- Z = (e, o = {}) => {
172
- (e.use(_(o)), e.use(b(o)), e.use(R(o)));
172
+ q = (e, o = {}) => {
173
+ (e.use(N(o)), e.use(R(o)), e.use($(o)));
173
174
  },
174
- q = async (e, o) => {
175
+ ee = async (e, o) => {
175
176
  let t = f(e),
176
177
  {port: r} = t;
177
178
  (await h(r, t.host)) || ((t.port = Number(r) + 1), m.warn(`\u7AEF\u53E3 ${r} \u5DF2\u88AB\u5360\u7528\uFF0C\u73B0\u5728\u4F7F\u7528\u7AEF\u53E3 ${t.port}`));
178
- let a = T();
179
- Y(a, t);
180
- let n = J(a);
181
- I(n, t, m);
179
+ let i = S();
180
+ Z(i, t);
181
+ let n = Y(i);
182
+ y(n, t, m);
182
183
  try {
183
- await A(n, t);
184
- } catch (i) {
185
- (m.error({err: i}, '\u26A0\uFE0F \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25'), process.exit(1));
184
+ await w(n, t);
185
+ } catch (a) {
186
+ (m.error({err: a}, '\u26A0\uFE0F \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25'), process.exit(1));
186
187
  }
187
188
  try {
188
- await o?.(t, a, n, m);
189
- } catch (i) {
190
- (m.error({err: i}, `\u56DE\u8C03\u51FD\u6570\u9519\u8BEF\uFF1A${i.message}`), process.exit(1));
189
+ await o?.(t, i, n, m);
190
+ } catch (a) {
191
+ (m.error({err: a}, `\u56DE\u8C03\u51FD\u6570\u9519\u8BEF\uFF1A${a.message}`), process.exit(1));
191
192
  }
192
- return (Z(a, t), {app: a, httpServer: n, config: t, logger: m});
193
+ return (q(i, t), {app: i, httpServer: n, config: t, logger: m});
193
194
  },
194
- $ = q;
195
- var ee = (e, o = 56) => {
195
+ _ = ee;
196
+ var te = (e, o = 56) => {
196
197
  let t = e.length,
197
198
  r = o - t,
198
199
  s = ~~(r / 2);
199
200
  return `${'-'.repeat(s)}${e}${'-'.repeat(r - s)}`;
200
201
  },
201
- te = (e, o, t) =>
202
- $({...g, ...e}, async (r, s, a, n) => {
203
- let {port: i, host: p, nodeEnv: l, basepath: y, appName: H = 'HuxyServer'} = r;
202
+ oe = (e, o, t) =>
203
+ _({...g, ...e}, async (r, s, i, n) => {
204
+ let {port: a, host: p, nodeEnv: x, basepath: l, appName: D = 'HuxyServer'} = r;
204
205
  if (!t) {
205
- let M = d()
206
- .filter(x => x !== `http://${p}`)
207
- .map(x => `http://${x}:${i}${y}`);
208
- (n.info(ee(H)),
209
- n.info(`\u{1F680} \u670D\u52A1\u8FD0\u884C\u5728\u3010${l}\u3011\u73AF\u5883: http://${p}:${i}${y}`),
206
+ let H = d()
207
+ .filter(E => E !== `http://${p}`)
208
+ .map(E => `http://${E}:${a}${l}`);
209
+ (n.info(te(D)),
210
+ n.info(`\u{1F680} \u670D\u52A1\u8FD0\u884C\u5728\u3010${x}\u3011\u73AF\u5883: http://${p}:${a}${l}`),
210
211
  n.info(`-----------------[${c()}]------------------`),
211
- n.info({ips: M}, '\u672C\u5730\u5730\u5740\uFF1A'));
212
+ n.info({ips: H}, '\u672C\u5730\u5730\u5740\uFF1A'));
212
213
  }
213
- await o?.(r, s, a, n);
214
+ await o?.(r, s, i, n);
214
215
  }),
215
- v = te;
216
- import ne from 'express';
217
- import {fileURLToPath as oe} from 'node:url';
218
- import {dirname as re, resolve as se} from 'node:path';
219
- var S = (e = import.meta.url) => re(oe(e)),
220
- P = e => se(S(), e),
221
- O = P;
216
+ v = oe;
217
+ import ie from 'express';
218
+ import {fileURLToPath as re} from 'node:url';
219
+ import {dirname as se, resolve as ne} from 'node:path';
220
+ var P = (e = import.meta.url) => se(re(e)),
221
+ I = (...e) => ne(P(), ...e),
222
+ O = I;
222
223
  var ae = {port: 9e3, host: 'localhost', basepath: '/', buildPath: './build'},
223
- ie = (e, o) =>
224
- v({...ae, ...e}, async (t, r, s, a) => {
225
- await o?.(t, r, s, a);
226
- let {basepath: n, buildPath: i} = t;
227
- (r.use(
228
- n,
229
- ne.static(i, {
230
- maxAge: '1y',
231
- immutable: !0,
232
- setHeaders: (p, l) => {
233
- l.endsWith('.html') && p.setHeader('Cache-Control', 'no-cache, must-revalidate');
234
- },
235
- }),
236
- ),
237
- r.get(`${n}/{*splat}`.replace('//', '/'), (p, l) => {
238
- l.sendFile(O(i, 'index.html'));
239
- }));
224
+ ce = (e, o) =>
225
+ v({...ae, ...e}, async (t, r, s, i) => {
226
+ await o?.(t, r, s, i);
227
+ let {basepath: n, buildPath: a} = t;
228
+ (r.get('/', (x, l) => {
229
+ l.redirect(n);
230
+ }),
231
+ r.use(n, ie.static(a, {})));
232
+ let p = new RegExp(`^${n.replace(/\//g, '\\/')}(.*)$`);
233
+ r.get(p, (x, l) => {
234
+ l.sendFile(O(a, 'index.html'));
235
+ });
240
236
  }),
241
- D = ie;
242
- var Ze = {startServer: v, startStatic: D, logger: m, createLogger: u, dateTime: c, localIPs: d, nodeArgs: E, getEnvConfig: f, checkPort: h, getDirName: S, resolvePath: P};
237
+ M = ce;
238
+ var qe = {startServer: v, startStatic: M, logger: m, createLogger: u, dateTime: c, localIPs: d, nodeArgs: T, getEnvConfig: f, checkPort: h, getDirName: P, resolvePath: I};
243
239
  export {
244
240
  h as checkPort,
245
241
  u as createLogger,
246
242
  c as dateTime,
247
- Ze as default,
248
- S as getDirName,
243
+ qe as default,
244
+ P as getDirName,
249
245
  f as getEnvConfig,
250
246
  d as localIPs,
251
247
  m as logger,
252
- E as nodeArgs,
253
- P as resolvePath,
248
+ T as nodeArgs,
249
+ I as resolvePath,
254
250
  v as startServer,
255
- D as startStatic,
251
+ M as startStatic,
256
252
  };