@nodefony/http 10.0.0-alpha.9 → 10.0.0-beta.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 (94) hide show
  1. package/README.md +7 -0
  2. package/dist/index.js +4 -2
  3. package/dist/nodefony/command/assetsPublishCommand.js +1 -1
  4. package/dist/nodefony/command/certificatesCommand.js +1 -1
  5. package/dist/nodefony/command/networkCommand.js +1 -1
  6. package/dist/nodefony/command/proxyGenerateCommand.js +1 -1
  7. package/dist/nodefony/config/config.js +22 -1
  8. package/dist/nodefony/interfaces/IRouting.js +1 -0
  9. package/dist/nodefony/interfaces/ISecurity.js +1 -0
  10. package/dist/nodefony/service/ProfilerAdminApi.js +2 -1
  11. package/dist/nodefony/service/audit-logger.js +16 -13
  12. package/dist/nodefony/service/certificates.js +25 -13
  13. package/dist/nodefony/service/error-renderer.js +11 -8
  14. package/dist/nodefony/service/http-kernel.js +340 -163
  15. package/dist/nodefony/service/pretty-request-logger.js +3 -10
  16. package/dist/nodefony/service/servers/clientError.js +2 -2
  17. package/dist/nodefony/service/servers/server-http.js +20 -20
  18. package/dist/nodefony/service/servers/server-https.js +38 -39
  19. package/dist/nodefony/service/servers/server-static.js +13 -17
  20. package/dist/nodefony/service/servers/server-websocket-secure.js +8 -7
  21. package/dist/nodefony/service/servers/server-websocket.js +8 -7
  22. package/dist/nodefony/service/servers/wsHeartbeat.js +2 -2
  23. package/dist/nodefony/service/sessions/sessions-service.js +19 -12
  24. package/dist/nodefony/service/trace.js +1 -1
  25. package/dist/nodefony/service/upload/upload-service.js +8 -7
  26. package/dist/nodefony/src/assets/prebuiltUi.js +1 -1
  27. package/dist/nodefony/src/context/Context.js +34 -19
  28. package/dist/nodefony/src/context/forwarded.js +4 -4
  29. package/dist/nodefony/src/context/http/HttpContext.js +133 -88
  30. package/dist/nodefony/src/context/http/Request.js +93 -44
  31. package/dist/nodefony/src/context/http/Response.js +107 -51
  32. package/dist/nodefony/src/context/http/parser.js +9 -10
  33. package/dist/nodefony/src/context/http/urlFastPath.js +1 -2
  34. package/dist/nodefony/src/context/http2/Response.js +53 -25
  35. package/dist/nodefony/src/context/metaData.js +1 -1
  36. package/dist/nodefony/src/context/trustProxy.js +4 -3
  37. package/dist/nodefony/src/context/websocket/Response.js +13 -6
  38. package/dist/nodefony/src/context/websocket/WebsocketContext.js +59 -26
  39. package/dist/nodefony/src/context/websocket/wsCloseReason.js +41 -0
  40. package/dist/nodefony/src/cookies/cookie.js +3 -3
  41. package/dist/nodefony/src/errors/httpError.js +6 -6
  42. package/dist/nodefony/src/errors/thrownMessage.js +27 -0
  43. package/dist/nodefony/src/profiler/FrameProfile.js +4 -3
  44. package/dist/nodefony/src/profiler/Profiler.js +4 -4
  45. package/dist/nodefony/src/servers/kernelServers.js +29 -0
  46. package/dist/nodefony/src/servers/portBinder.js +8 -21
  47. package/dist/nodefony/src/session/session.js +18 -10
  48. package/dist/nodefony/src/session/sessionStoreFailure.js +2 -1
  49. package/dist/nodefony/src/session/storage/RevocationGuardStorage.js +24 -9
  50. package/dist/types/index.d.ts +16 -0
  51. package/dist/types/nodefony/config/config.d.ts +22 -0
  52. package/dist/types/nodefony/interfaces/IContext.d.ts +24 -7
  53. package/dist/types/nodefony/interfaces/ICookie.d.ts +18 -18
  54. package/dist/types/nodefony/interfaces/IHttpKernel.d.ts +10 -4
  55. package/dist/types/nodefony/interfaces/IResponse.d.ts +1 -1
  56. package/dist/types/nodefony/interfaces/IRouting.d.ts +87 -0
  57. package/dist/types/nodefony/interfaces/ISecurity.d.ts +45 -0
  58. package/dist/types/nodefony/interfaces/ISession.d.ts +8 -8
  59. package/dist/types/nodefony/interfaces/IUpload.d.ts +9 -9
  60. package/dist/types/nodefony/interfaces/index.d.ts +2 -0
  61. package/dist/types/nodefony/service/audit-logger.d.ts +14 -10
  62. package/dist/types/nodefony/service/certificates.d.ts +10 -10
  63. package/dist/types/nodefony/service/http-kernel.d.ts +192 -42
  64. package/dist/types/nodefony/service/servers/server-http.d.ts +4 -1
  65. package/dist/types/nodefony/service/servers/server-https.d.ts +4 -1
  66. package/dist/types/nodefony/service/servers/server-websocket-secure.d.ts +4 -1
  67. package/dist/types/nodefony/service/servers/server-websocket.d.ts +4 -1
  68. package/dist/types/nodefony/service/sessions/sessions-service.d.ts +6 -2
  69. package/dist/types/nodefony/service/upload/upload-service.d.ts +1 -1
  70. package/dist/types/nodefony/src/context/Context.d.ts +21 -10
  71. package/dist/types/nodefony/src/context/forwarded.d.ts +3 -3
  72. package/dist/types/nodefony/src/context/http/HttpContext.d.ts +75 -18
  73. package/dist/types/nodefony/src/context/http/Request.d.ts +39 -2
  74. package/dist/types/nodefony/src/context/http/Response.d.ts +47 -7
  75. package/dist/types/nodefony/src/context/http/parser.d.ts +1 -1
  76. package/dist/types/nodefony/src/context/http2/Response.d.ts +32 -2
  77. package/dist/types/nodefony/src/context/websocket/Response.d.ts +4 -4
  78. package/dist/types/nodefony/src/context/websocket/WebsocketContext.d.ts +11 -2
  79. package/dist/types/nodefony/src/context/websocket/wsCloseReason.d.ts +21 -0
  80. package/dist/types/nodefony/src/cookies/cookie.d.ts +9 -9
  81. package/dist/types/nodefony/src/errors/httpError.d.ts +7 -7
  82. package/dist/types/nodefony/src/errors/thrownMessage.d.ts +12 -0
  83. package/dist/types/nodefony/src/profiler/Profiler.d.ts +28 -28
  84. package/dist/types/nodefony/src/servers/kernelServers.d.ts +20 -0
  85. package/dist/types/nodefony/src/servers/portBinder.d.ts +6 -19
  86. package/dist/types/nodefony/src/session/session.d.ts +12 -12
  87. package/dist/types/nodefony/src/session/storage/RevocationGuardStorage.d.ts +1 -1
  88. package/docs/cookies.md +20 -20
  89. package/docs/observabilite.md +25 -25
  90. package/docs/rate-limit.md +18 -18
  91. package/docs/servers.md +52 -52
  92. package/docs/session.md +65 -60
  93. package/docs/upload.md +36 -30
  94. package/package.json +7 -7
@@ -1,6 +1,5 @@
1
- import { severityFromStatus } from "./audit-logger.js";
1
+ import { computeDurationMs, severityFromStatus } from "./audit-logger.js";
2
2
  import { logColor } from "nodefony";
3
- import { performance } from "node:perf_hooks";
4
3
  //#region nodefony/service/pretty-request-logger.ts
5
4
  /**
6
5
  * Pretty single-line logger for dev (P3.2) — the biggest gain for humans.
@@ -28,7 +27,7 @@ var PrettyRequestLogger = class {
28
27
  const method = ctx.method ?? "?";
29
28
  const duration = computeDurationMs(ctx.phases);
30
29
  return {
31
- text: `${logColor.cyan(method.padEnd(4))} ${colorizeStatus(status)} ${ctx.url} ${logColor.blackBright(formatDuration(duration))} ${logColor.blackBright(ctx.remoteAddress ?? "-")} ${logColor.magenta(`[${shortId(ctx.requestId)}]`)}` + (err ? ` ${logColor.red(err.message)}` : ""),
30
+ text: `${logColor.cyan(method.padEnd(4))} ${colorizeStatus(status)} ${ctx.url} ${logColor.blackBright(formatDuration(duration))} ${logColor.blackBright(ctx.remoteAddress ?? "-")} ` + logColor.magenta(`[${shortId(ctx.requestId)}]`) + (err ? ` ${logColor.red(err.message)}` : ""),
32
31
  severity: severityFromStatus(status),
33
32
  msgid: "req"
34
33
  };
@@ -39,7 +38,7 @@ var PrettyRequestLogger = class {
39
38
  const duration = computeDurationMs(ctx.phases);
40
39
  const proto = acceptedProtocol ? `[${acceptedProtocol}]` : "";
41
40
  return {
42
- text: `${logColor.cyan("WS ")} ${colorizeStatus(status)} ${ctx.url} ${logColor.blackBright(proto)} ${logColor.blackBright(formatDuration(duration))} ${logColor.blackBright(ctx.remoteAddress ?? "-")} ${logColor.magenta(`[${shortId(ctx.requestId)}]`)}` + (error ? ` ${logColor.red(error.message)}` : ""),
41
+ text: `${logColor.cyan("WS ")} ${colorizeStatus(status)} ${ctx.url} ${logColor.blackBright(proto)} ${logColor.blackBright(formatDuration(duration))} ${logColor.blackBright(ctx.remoteAddress ?? "-")} ` + logColor.magenta(`[${shortId(ctx.requestId)}]`) + (error ? ` ${logColor.red(error.message)}` : ""),
43
42
  severity: error ? "ERROR" : "INFO",
44
43
  msgid: "req"
45
44
  };
@@ -62,11 +61,5 @@ function formatDuration(ms) {
62
61
  function shortId(id) {
63
62
  return id.length > 8 ? id.slice(0, 8) : id;
64
63
  }
65
- function computeDurationMs(phases) {
66
- if (!phases.length) return null;
67
- const first = phases[0];
68
- if (typeof first.startMs !== "number") return null;
69
- return performance.now() - first.startMs;
70
- }
71
64
  //#endregion
72
65
  export { PrettyRequestLogger as default };
@@ -12,8 +12,8 @@
12
12
  * @param socket - flux client brut (l'event `clientError` fournit un `Duplex`).
13
13
  */
14
14
  function handleClientError(error, socket) {
15
- if (error?.code === "ECONNRESET" || !socket.writable) return;
16
- const statusLine = error?.code === "HPE_HEADER_OVERFLOW" ? "431 Request Header Fields Too Large" : "400 Bad Request";
15
+ if (error.code === "ECONNRESET" || !socket.writable) return;
16
+ const statusLine = error.code === "HPE_HEADER_OVERFLOW" ? "431 Request Header Fields Too Large" : "400 Bad Request";
17
17
  socket.end(`HTTP/1.1 ${statusLine}\r\nConnection: close\r\n\r\n`);
18
18
  }
19
19
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { asServersConfig, configuredServerPort } from "../../src/servers/kernelServers.js";
1
2
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
2
3
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
4
  import http_kernel_default from "../http-kernel.js";
@@ -27,13 +28,12 @@ let ServerHttp = class ServerHttp extends Service {
27
28
  super("server-http", module.container, module.notificationsCenter, module.options.http);
28
29
  this.httpKernel = httpKernel;
29
30
  this.module = module;
30
- this.active = !!module.kernel?.options.servers.http;
31
+ this.active = !!asServersConfig(module.kernel?.options.servers)?.http;
31
32
  this.port = this.setPort();
32
33
  this.domain = this.module.kernel?.domain;
33
34
  }
34
35
  setPort() {
35
- if (this.module.kernel?.options.servers?.http) return this.module.kernel?.options.servers?.http?.port || 0;
36
- return 0;
36
+ return configuredServerPort(asServersConfig(this.module.kernel?.options.servers), "http") ?? 0;
37
37
  }
38
38
  createServer() {
39
39
  return new Promise((resolve, reject) => {
@@ -42,23 +42,19 @@ let ServerHttp = class ServerHttp extends Service {
42
42
  const opt = extend({ requestTimeout: this.options.requestTimeout });
43
43
  this.server = http.createServer(opt);
44
44
  this.httpTerminator = createDrainTerminator(this.server, this.options.shutdownTimeout);
45
- if (this.options.maxHeadersCount) {
46
- if (this.server) this.server.maxHeadersCount = this.options.maxHeadersCount;
47
- }
45
+ if (this.options.maxHeadersCount) this.server.maxHeadersCount = this.options.maxHeadersCount;
48
46
  if (this.options.timeout) {
49
- if (this.server) {
50
- this.server.setTimeout(this.options.timeout, () => {
51
- this.fire("onTimeout", this);
52
- });
53
- this.server.timeout = this.options.timeout;
54
- }
47
+ this.server.setTimeout(this.options.timeout, () => {
48
+ this.fire("onTimeout", this);
49
+ });
50
+ this.server.timeout = this.options.timeout;
55
51
  }
56
- if (this.options.keepAliveTimeout) {
57
- if (this.server) this.server.keepAliveTimeout = this.options.keepAliveTimeout;
58
- }
59
- this.server.on("request", (request, response) => this.httpKernel?.onHttpRequest(request, response, this.type).catch(() => {}));
52
+ if (this.options.keepAliveTimeout) this.server.keepAliveTimeout = this.options.keepAliveTimeout;
53
+ this.server.on("request", (request, response) => {
54
+ this.httpKernel.onHttpRequest(request, response, this.type);
55
+ });
60
56
  this.module.fire("onCreateServer", this.type, this);
61
- bindWithFallback(this.server, this.domain, buildBindPlan("http", this.module.kernel?.options.servers, this.module.kernel?.environment)).then(({ address, shiftedFrom }) => {
57
+ bindWithFallback(this.server, this.domain, buildBindPlan("http", asServersConfig(this.module.kernel?.options.servers), this.module.kernel?.environment)).then(({ address, shiftedFrom }) => {
62
58
  this.infos = address;
63
59
  this.port = address.port;
64
60
  this.address = address.address;
@@ -68,7 +64,8 @@ let ServerHttp = class ServerHttp extends Service {
68
64
  this.module.fire("onServersReady", this.type, this);
69
65
  this.attachErrorHandler();
70
66
  resolve(this.server);
71
- }).catch((error) => {
67
+ }).catch((e) => {
68
+ const error = e instanceof Error ? e : new Error(String(e));
72
69
  this.reportBindError(error);
73
70
  reject(error);
74
71
  });
@@ -87,7 +84,7 @@ let ServerHttp = class ServerHttp extends Service {
87
84
  });
88
85
  } catch (e) {
89
86
  this.log(e, "CRITIC");
90
- return reject(e);
87
+ return reject(e instanceof Error ? e : new Error(String(e)));
91
88
  }
92
89
  });
93
90
  }
@@ -120,10 +117,13 @@ let ServerHttp = class ServerHttp extends Service {
120
117
  this.log(`Port ${this.port} déjà occupé (domaine ${this.domain}) — le serveur HTTP ne peut pas écouter. Libérer le port, en choisir un autre (servers.http.port), ou autoriser le repli automatique (servers.portPolicy = "auto", défaut en développement).`, "ERROR");
121
118
  this.log(myError, "CRITIC");
122
119
  break;
120
+ case void 0:
123
121
  default: this.log(myError, "CRITIC");
124
122
  }
125
123
  this.server?.close();
126
- setTimeout(() => this.kernel?.terminate(1), 1e3);
124
+ setTimeout(() => {
125
+ this.kernel?.terminate(1);
126
+ }, 1e3);
127
127
  }
128
128
  showBanner() {
129
129
  if (this.infos) this.log(`Server Listen on ${this.scheme}://${this.infos.address}:${this.infos.port} Family: ${this.infos.family} Protocol : ${this.protocol}`);
@@ -1,3 +1,4 @@
1
+ import { asServersConfig, configuredServerPort } from "../../src/servers/kernelServers.js";
1
2
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
2
3
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
4
  import http_kernel_default from "../http-kernel.js";
@@ -29,7 +30,7 @@ let ServerHttps = class ServerHttps extends Service {
29
30
  super("server-https", module.container, module.notificationsCenter, module.options.https);
30
31
  this.httpKernel = httpKernel;
31
32
  this.module = module;
32
- this.active = !!this.kernel?.options.servers.https;
33
+ this.active = !!asServersConfig(this.kernel?.options.servers)?.https;
33
34
  this.port = this.setPort();
34
35
  this.domain = this.kernel?.domain;
35
36
  }
@@ -38,45 +39,42 @@ let ServerHttps = class ServerHttps extends Service {
38
39
  throw new Error(`Server not found`);
39
40
  }
40
41
  setPort() {
41
- if (this.kernel?.options.servers?.https) return this.kernel?.options.servers?.https?.port || 0;
42
- return 0;
42
+ return configuredServerPort(asServersConfig(this.kernel?.options.servers), "https") ?? 0;
43
43
  }
44
44
  createServer() {
45
45
  return new Promise((resolve, reject) => {
46
46
  try {
47
47
  if (!this.active) return reject(/* @__PURE__ */ new Error(`Server https is not allowed in config file `));
48
- this.protocol = this.kernel?.options.servers.https.protocol;
48
+ const httpsCfg = asServersConfig(this.kernel?.options.servers)?.https;
49
+ const protocol = httpsCfg ? httpsCfg.protocol : void 0;
50
+ if (protocol) this.protocol = protocol;
49
51
  if (this.protocol === "2.0") return resolve(this.createServerH2());
50
52
  const opt = extend({
51
53
  requestTimeout: this.options.requestTimeout,
52
54
  rejectUnauthorized: this.options.rejectUnauthorized,
53
- key: this.httpKernel?.serviceCerticats?.key,
54
- cert: this.httpKernel?.serviceCerticats?.cert,
55
- ca: this.httpKernel?.serviceCerticats?.ca ? this.httpKernel?.serviceCerticats?.ca : void 0
55
+ key: this.httpKernel.serviceCerticats?.key,
56
+ cert: this.httpKernel.serviceCerticats?.cert,
57
+ ca: this.httpKernel.serviceCerticats?.ca ? this.httpKernel.serviceCerticats.ca : void 0
56
58
  });
57
- this.server = https.createServer(opt);
59
+ const server = https.createServer(opt);
60
+ this.server = server;
58
61
  this.httpTerminator = this.terminator();
59
62
  if (this.options.timeout) {
60
- if (this.server) {
61
- this.server.setTimeout(this.options.timeout, () => {
62
- this.fire("onTimeout", this);
63
- });
64
- this.server.timeout = this.options.timeout;
65
- }
66
- }
67
- if (this.options.maxHeadersCount) {
68
- if (this.server) this.server.maxHeadersCount = this.options.maxHeadersCount;
69
- }
70
- if (this.options.keepAliveTimeout) {
71
- if (this.server) this.server.keepAliveTimeout = this.options.keepAliveTimeout;
63
+ server.setTimeout(this.options.timeout, () => {
64
+ this.fire("onTimeout", this);
65
+ });
66
+ server.timeout = this.options.timeout;
72
67
  }
68
+ if (this.options.maxHeadersCount) server.maxHeadersCount = this.options.maxHeadersCount;
69
+ if (this.options.keepAliveTimeout) server.keepAliveTimeout = this.options.keepAliveTimeout;
73
70
  this.module.fire("onCreateServer", this.type, this);
74
- this.listenWithPolicy().then(() => resolve(this.server)).catch((error) => {
71
+ this.listenWithPolicy().then(() => resolve(this.server)).catch((e) => {
72
+ const error = e instanceof Error ? e : new Error(String(e));
75
73
  this.reportBindError(error);
76
74
  reject(error);
77
75
  });
78
76
  this.server.on("request", (request, response) => {
79
- this.httpKernel?.onHttpRequest(request, response, this.type).catch(() => {});
77
+ this.httpKernel.onHttpRequest(request, response, this.type);
80
78
  });
81
79
  this.kernel?.once("onTerminate", async () => {
82
80
  if (!this.server) return;
@@ -93,20 +91,20 @@ let ServerHttps = class ServerHttps extends Service {
93
91
  });
94
92
  } catch (e) {
95
93
  this.log(e, "CRITIC");
96
- return reject(e);
94
+ return reject(e instanceof Error ? e : new Error(String(e)));
97
95
  }
98
96
  });
99
97
  }
100
98
  createServerH2() {
101
99
  return new Promise((resolve, reject) => {
102
100
  try {
103
- const h2Cfg = (this.module?.options)?.http2 ?? {};
101
+ const h2Cfg = this.module.options.http2 ?? {};
104
102
  const opt = extend({
105
103
  allowHTTP1: true,
106
104
  rejectUnauthorized: this.options.rejectUnauthorized,
107
- key: this.httpKernel?.serviceCerticats?.key,
108
- cert: this.httpKernel?.serviceCerticats?.cert,
109
- ca: this.httpKernel?.serviceCerticats?.ca ? this.httpKernel?.serviceCerticats?.ca : void 0
105
+ key: this.httpKernel.serviceCerticats?.key,
106
+ cert: this.httpKernel.serviceCerticats?.cert,
107
+ ca: this.httpKernel.serviceCerticats?.ca ? this.httpKernel.serviceCerticats.ca : void 0
110
108
  });
111
109
  if (h2Cfg.maxSessionMemory) opt.maxSessionMemory = h2Cfg.maxSessionMemory;
112
110
  if (h2Cfg.maxConcurrentStreams) opt.settings = {
@@ -120,16 +118,14 @@ let ServerHttps = class ServerHttps extends Service {
120
118
  });
121
119
  this.server.on("request", (request, response) => {
122
120
  let alpnProtocol = false;
123
- if (request && request.stream && request.stream.session?.socket) {
124
- if (request.stream.session.socket instanceof TLSSocket) alpnProtocol = request.stream.session.socket.alpnProtocol;
125
- }
126
- if (request.socket) {
127
- if (request.socket instanceof TLSSocket) alpnProtocol = request.socket.alpnProtocol;
128
- }
129
- if (alpnProtocol === "h2") return this.httpKernel?.onHttpRequest(request, response, "http2").catch(() => {});
130
- else return this.httpKernel?.onHttpRequest(request, response, "https").catch(() => {});
121
+ const sessionSocket = request.stream?.session?.socket;
122
+ if (sessionSocket instanceof TLSSocket) alpnProtocol = sessionSocket.alpnProtocol;
123
+ if (request.socket instanceof TLSSocket) alpnProtocol = request.socket.alpnProtocol;
124
+ if (alpnProtocol === "h2") this.httpKernel.onHttpRequest(request, response, "http2");
125
+ else this.httpKernel.onHttpRequest(request, response, "https");
131
126
  });
132
- this.listenWithPolicy().then(() => resolve(this.server)).catch((error) => {
127
+ this.listenWithPolicy().then(() => resolve(this.server)).catch((e) => {
128
+ const error = e instanceof Error ? e : new Error(String(e));
133
129
  this.reportBindError(error);
134
130
  reject(error);
135
131
  });
@@ -149,7 +145,7 @@ let ServerHttps = class ServerHttps extends Service {
149
145
  this.log(error, "ERROR", "HTTP2 Server streamError");
150
146
  });
151
147
  } catch (e) {
152
- return reject(e);
148
+ return reject(e instanceof Error ? e : new Error(String(e)));
153
149
  }
154
150
  });
155
151
  }
@@ -161,7 +157,7 @@ let ServerHttps = class ServerHttps extends Service {
161
157
  * `EADDRINUSE` de repli, qui ne sont pas des pannes).
162
158
  */
163
159
  async listenWithPolicy() {
164
- const { address, shiftedFrom } = await bindWithFallback(this.server, this.domain, buildBindPlan("https", this.module.kernel?.options.servers, this.module.kernel?.environment));
160
+ const { address, shiftedFrom } = await bindWithFallback(this.server, this.domain, buildBindPlan("https", asServersConfig(this.module.kernel?.options.servers), this.module.kernel?.environment));
165
161
  this.infos = address;
166
162
  this.port = address.port;
167
163
  this.address = address.address;
@@ -189,10 +185,13 @@ let ServerHttps = class ServerHttps extends Service {
189
185
  this.log(`Port ${this.port} déjà occupé (domaine ${this.domain}) — le serveur HTTPS ne peut pas écouter. Libérer le port, en choisir un autre (servers.https.port), ou autoriser le repli automatique (servers.portPolicy = "auto", défaut en développement).`, "ERROR");
190
186
  this.log(myError, "CRITIC");
191
187
  break;
188
+ case void 0:
192
189
  default: this.log(myError, "CRITIC");
193
190
  }
194
191
  this.server?.close();
195
- setTimeout(() => this.kernel?.terminate(1), 1e3);
192
+ setTimeout(() => {
193
+ this.kernel?.terminate(1);
194
+ }, 1e3);
196
195
  }
197
196
  showBanner() {
198
197
  if (this.infos) this.log(`Server Listen on ${this.scheme}://${this.infos.address}:${this.infos.port} Family: ${this.infos.family} Protocol : ${this.protocol}`);
@@ -1,6 +1,6 @@
1
1
  import { Service, extend } from "nodefony";
2
- import { URL } from "node:url";
3
2
  import http from "node:http";
3
+ import { URL } from "node:url";
4
4
  import { existsSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  import mime from "mime-types";
@@ -25,7 +25,7 @@ var Statics = class extends Service {
25
25
  enabled = true;
26
26
  defaultOptions = defaultOptions;
27
27
  constructor(module) {
28
- const container = module.container || void 0;
28
+ const container = module.container ?? void 0;
29
29
  const options = module.options.statics || {};
30
30
  let event;
31
31
  if (container) event = container.get("notificationsCenter");
@@ -68,10 +68,9 @@ var Statics = class extends Service {
68
68
  if (!modules) return;
69
69
  const frontend = this.container?.get("frontend");
70
70
  const frontManaged = frontend?.listEntries ? new Set(frontend.listEntries().map((e) => e.moduleName)) : null;
71
- for (const name in modules) {
72
- const mod = modules[name];
73
- if (!mod || mod.isApp) continue;
74
- const cfg = mod.options?.publicMount;
71
+ for (const mod of Object.values(modules)) {
72
+ if (mod.isApp) continue;
73
+ const cfg = mod.options.publicMount;
75
74
  if (cfg === false) continue;
76
75
  if (cfg == null && frontManaged?.has(mod.name)) continue;
77
76
  const dir = join(mod.path, cfg?.dir || "public");
@@ -82,10 +81,10 @@ var Statics = class extends Service {
82
81
  }
83
82
  initStaticFiles() {
84
83
  for (const staticRoot in this.options) {
85
- let Path = this.options[staticRoot].path;
86
- Path = this.kernel?.checkPath(Path);
84
+ const root = this.options[staticRoot];
85
+ const Path = this.kernel?.checkPath(root.path);
87
86
  let setHeaders = null;
88
- const opt = this.options[staticRoot].options || {};
87
+ const opt = root.options ?? {};
89
88
  if (opt.setHeaders) {
90
89
  if (typeof opt.setHeaders === "function") {
91
90
  setHeaders = opt.setHeaders;
@@ -97,7 +96,7 @@ var Statics = class extends Service {
97
96
  this.fire("onServeStatic", res, path, staticRoot, this);
98
97
  };
99
98
  if (setHeaders) this.on("onServeStatic", setHeaders);
100
- this.addDirectory(Path, opt);
99
+ this.addDirectory(Path ?? "", opt);
101
100
  }
102
101
  }
103
102
  /**
@@ -147,11 +146,11 @@ var Statics = class extends Service {
147
146
  getUrl(request) {
148
147
  let scheme, host;
149
148
  if (request instanceof http.IncomingMessage) {
150
- scheme = request.connection instanceof tls.TLSSocket && request.connection.encrypted ? "https" : "http";
149
+ scheme = request.socket instanceof tls.TLSSocket ? "https" : "http";
151
150
  host = request.headers.host;
152
151
  return scheme + "://" + host;
153
152
  } else if (request instanceof http2.Http2ServerRequest) {
154
- scheme = request.socket instanceof tls.TLSSocket && request.socket.encrypted ? "https" : "http";
153
+ scheme = request.socket instanceof tls.TLSSocket ? "https" : "http";
155
154
  host = request.headers[":authority"];
156
155
  return scheme + "://" + host;
157
156
  }
@@ -172,18 +171,15 @@ var Statics = class extends Service {
172
171
  request.url = raw;
173
172
  } catch (e) {
174
173
  request.url = raw;
175
- return Promise.reject(e);
174
+ throw e;
176
175
  }
177
176
  break;
178
177
  }
179
178
  }
180
- for (const server in this.servers) try {
181
- let ele = this.servers[server];
179
+ for (const ele of Object.values(this.servers)) {
182
180
  await this.getStatic(ele, request, response);
183
181
  const type = mime.lookup(pathname);
184
182
  response.setHeader("Content-Type", type);
185
- } catch (e) {
186
- return Promise.reject(e);
187
183
  }
188
184
  return Promise.resolve(response);
189
185
  }
@@ -1,3 +1,4 @@
1
+ import { asServersConfig, configuredServerPort } from "../../src/servers/kernelServers.js";
1
2
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
2
3
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
4
  import http_kernel_default from "../http-kernel.js";
@@ -30,13 +31,13 @@ let WebsocketSecure = class WebsocketSecure extends Service {
30
31
  this.ready = false;
31
32
  }
32
33
  setPort() {
33
- if (this.kernel?.options.servers?.https) return this.kernel?.options.servers?.https?.port || 0;
34
- return 0;
34
+ return configuredServerPort(asServersConfig(this.kernel?.options.servers), "https") ?? 0;
35
35
  }
36
36
  async createServer(serverHttps) {
37
37
  return new Promise((resolve, reject) => {
38
38
  try {
39
- this.infos = serverHttps.server.address();
39
+ const address = serverHttps.server.address();
40
+ this.infos = typeof address === "object" ? address : null;
40
41
  if (this.infos) {
41
42
  this.port = this.infos.port;
42
43
  this.address = this.infos.address;
@@ -44,19 +45,19 @@ let WebsocketSecure = class WebsocketSecure extends Service {
44
45
  this.protocol = serverHttps.protocol;
45
46
  }
46
47
  this.server = new WebSocketServer({
47
- ...this.options ?? {},
48
+ ...this.options,
48
49
  server: serverHttps.server,
49
50
  clientTracking: true
50
51
  });
51
52
  this.server.on("connection", this.onConnection.bind(this));
52
53
  this.heartbeatTimer = startHeartbeat(this.server, this.options);
53
54
  this.kernel?.prependOnceListener("onTerminate", this.terminate.bind(this));
54
- if (this.server) this.ready = true;
55
+ this.ready = true;
55
56
  this.module.fire("onServersReady", this.type, this);
56
57
  return resolve(this.server);
57
58
  } catch (e) {
58
59
  this.log(e, "ERROR");
59
- return reject(e);
60
+ return reject(e instanceof Error ? e : new Error(String(e)));
60
61
  }
61
62
  });
62
63
  }
@@ -86,7 +87,7 @@ let WebsocketSecure = class WebsocketSecure extends Service {
86
87
  this.log(` SHUTDOWN WEBSOCKET Server is listening on DOMAIN : ${this.domain} PORT : ${this.port}`, "INFO");
87
88
  return resolve(true);
88
89
  } catch (e) {
89
- return reject(e);
90
+ return reject(e instanceof Error ? e : new Error(String(e)));
90
91
  }
91
92
  }, 300);
92
93
  return;
@@ -1,3 +1,4 @@
1
+ import { asServersConfig, configuredServerPort } from "../../src/servers/kernelServers.js";
1
2
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
2
3
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
4
  import http_kernel_default from "../http-kernel.js";
@@ -30,13 +31,13 @@ let Websocket = class Websocket extends Service {
30
31
  this.ready = false;
31
32
  }
32
33
  setPort() {
33
- if (this.kernel?.options.servers?.http) return this.kernel?.options.servers?.http?.port || 0;
34
- return 0;
34
+ return configuredServerPort(asServersConfig(this.kernel?.options.servers), "http") ?? 0;
35
35
  }
36
36
  async createServer(serverHttp) {
37
37
  return new Promise((resolve, reject) => {
38
38
  try {
39
- this.infos = serverHttp.server.address();
39
+ const address = serverHttp.server.address();
40
+ this.infos = typeof address === "object" ? address : null;
40
41
  if (this.infos) {
41
42
  this.port = this.infos.port;
42
43
  this.address = this.infos.address;
@@ -44,19 +45,19 @@ let Websocket = class Websocket extends Service {
44
45
  this.protocol = serverHttp.protocol;
45
46
  }
46
47
  this.server = new WebSocketServer({
47
- ...this.options ?? {},
48
+ ...this.options,
48
49
  server: serverHttp.server,
49
50
  clientTracking: true
50
51
  });
51
52
  this.server.on("connection", this.onConnection.bind(this));
52
53
  this.heartbeatTimer = startHeartbeat(this.server, this.options);
53
54
  this.kernel?.prependOnceListener("onTerminate", this.terminate.bind(this));
54
- if (this.server) this.ready = true;
55
+ this.ready = true;
55
56
  this.module.fire("onServersReady", this.type, this);
56
57
  return resolve(this.server);
57
58
  } catch (e) {
58
59
  this.log(e, "ERROR");
59
- return reject(e);
60
+ return reject(e instanceof Error ? e : new Error(String(e)));
60
61
  }
61
62
  });
62
63
  }
@@ -86,7 +87,7 @@ let Websocket = class Websocket extends Service {
86
87
  this.log(` SHUTDOWN WEBSOCKET Server is listening on DOMAIN : ${this.domain} PORT : ${this.port}`, "INFO");
87
88
  return resolve(true);
88
89
  } catch (e) {
89
- return reject(e);
90
+ return reject(e instanceof Error ? e : new Error(String(e)));
90
91
  }
91
92
  }, 300);
92
93
  return;
@@ -46,7 +46,7 @@ const startHeartbeat = (server, options) => {
46
46
  for (const client of server.clients) {
47
47
  if (client.readyState !== Ws.OPEN) continue;
48
48
  const sock = client;
49
- if (sock._nfLastPong === void 0) sock._nfLastPong = now;
49
+ sock._nfLastPong ??= now;
50
50
  if ((sock._nfPingedAt ?? 0) > sock._nfLastPong) {
51
51
  if (now - sock._nfPingedAt > grace) client.terminate();
52
52
  continue;
@@ -57,7 +57,7 @@ const startHeartbeat = (server, options) => {
57
57
  }
58
58
  }
59
59
  }, Math.max(250, grace > 0 ? Math.min(interval, grace) : interval));
60
- timer.unref?.();
60
+ timer.unref();
61
61
  return timer;
62
62
  };
63
63
  //#endregion
@@ -106,7 +106,8 @@ let SessionsService = class SessionsService extends Service {
106
106
  }
107
107
  /** Storage enregistré pour un store, ou `undefined`. */
108
108
  static getStorage(name) {
109
- return _SessionsService.storages.get(String(name ?? "").toLowerCase());
109
+ const key = name;
110
+ return _SessionsService.storages.get((key ?? "").toLowerCase());
110
111
  }
111
112
  /** Noms des handlers de session enregistrés. */
112
113
  static storageHandlers() {
@@ -177,8 +178,9 @@ let SessionsService = class SessionsService extends Service {
177
178
  connector: readStoreConnector(innerStorage)
178
179
  });
179
180
  await storage.open();
181
+ const gcIntervalS = this.options.gcIntervalS;
180
182
  this.gcScheduler = new GcScheduler({
181
- intervalS: Number(this.options.gcIntervalS ?? 600),
183
+ intervalS: Number(gcIntervalS ?? 600),
182
184
  jitter: this.options.gcJitter !== false,
183
185
  run: () => this.runGc(),
184
186
  onError: (e) => this.log(e, "WARNING", "SESSION-GC")
@@ -203,8 +205,11 @@ let SessionsService = class SessionsService extends Service {
203
205
  return;
204
206
  }
205
207
  context.once("onSessionStart", (session, error) => {
206
- if (session) return resolve(session);
207
- return reject(error || /* @__PURE__ */ new Error("Bad Session"));
208
+ if (session) {
209
+ resolve(session);
210
+ return;
211
+ }
212
+ reject(error ?? /* @__PURE__ */ new Error("Bad Session"));
208
213
  });
209
214
  return;
210
215
  }
@@ -221,27 +226,29 @@ let SessionsService = class SessionsService extends Service {
221
226
  inst.readOnly = readOnly === true;
222
227
  } catch (e) {
223
228
  context.fire("onSessionStart", null, e);
224
- return reject(e);
229
+ return reject(e instanceof Error ? e : new Error(String(e)));
225
230
  }
226
231
  inst.start(context).then((session) => {
227
232
  try {
228
233
  context.session = session;
229
234
  const method = context.method;
230
235
  const request = context.request;
231
- if (method !== "WEBSOCKET" && request && request.request) request.request.session = session;
236
+ if (method !== "WEBSOCKET" && request?.request) request.request.session = session;
232
237
  context.sessionStarting = false;
233
238
  if (context.cleaned) return reject(/* @__PURE__ */ new Error("context already cleaned"));
234
239
  context.fire("onSessionStart", session, null);
235
240
  return resolve(session);
236
241
  } catch (e) {
237
- if (context.cleaned) return reject(e);
242
+ const error = e instanceof Error ? e : new Error(String(e));
243
+ if (context.cleaned) return reject(error);
238
244
  context.fire("onSessionStart", null, e);
239
- return reject(e);
245
+ return reject(error);
240
246
  }
241
247
  }).catch((err) => {
242
- if (context.cleaned) return reject(err);
248
+ const error = err instanceof Error ? err : new Error(String(err));
249
+ if (context.cleaned) return reject(error);
243
250
  context.fire("onSessionStart", null, err);
244
- return reject(err);
251
+ return reject(error);
245
252
  });
246
253
  });
247
254
  }
@@ -253,8 +260,8 @@ let SessionsService = class SessionsService extends Service {
253
260
  return session;
254
261
  }
255
262
  createSession(name, options) {
256
- options = extend({}, this.options, options);
257
- return new Session(name, options, this);
263
+ const merged = extend({}, this.options, options);
264
+ return new Session(name, merged, this);
258
265
  }
259
266
  setSessionStrategy(strategy) {
260
267
  this.sessionStrategy = strategy;
@@ -29,7 +29,7 @@ function parseTraceparent(header) {
29
29
  if (typeof header !== "string") return null;
30
30
  const m = TRACEPARENT_RE.exec(header.trim().toLowerCase());
31
31
  if (!m) return null;
32
- const [, version, traceId, parentId, flags] = m;
32
+ const [, version = "", traceId = "", parentId = "", flags = ""] = m;
33
33
  if (version === "ff") return null;
34
34
  if (/^0+$/.test(traceId)) return null;
35
35
  if (/^0+$/.test(parentId)) return null;
@@ -21,18 +21,19 @@ let upload = class upload extends Service {
21
21
  path;
22
22
  module;
23
23
  constructor(module, httpKernel) {
24
- super("upload", httpKernel?.container, httpKernel.notificationsCenter);
24
+ super("upload", httpKernel.container, httpKernel.notificationsCenter);
25
25
  this.httpKernel = httpKernel;
26
26
  this.module = module;
27
27
  this.kernel?.once("onBoot", async () => {
28
28
  this.options = this.httpKernel.options;
29
- if (path.isAbsolute(this.options.upload.uploadDir)) this.path = this.options.upload.uploadDir;
30
- else this.path = path.resolve(`${this.kernel?.path}/${this.options.upload.uploadDir}`);
29
+ const uploadCfg = this.httpKernel.options.upload;
30
+ if (path.isAbsolute(uploadCfg.uploadDir)) this.path = uploadCfg.uploadDir;
31
+ else this.path = path.resolve(`${this.kernel?.path}/${uploadCfg.uploadDir}`);
31
32
  try {
32
33
  await fsp.mkdir(this.path, { recursive: true });
33
34
  } catch (e) {
34
35
  this.path = "/tmp";
35
- this.options.upload.uploadDir = this.path;
36
+ uploadCfg.uploadDir = this.path;
36
37
  this.log(e, "DEBUG");
37
38
  }
38
39
  });
@@ -102,8 +103,7 @@ var UploadedFile = class UploadedFile extends FileClass {
102
103
  return this.parsedFile.originalFilename || name || this.parsedFile.newFilename;
103
104
  }
104
105
  getMimeType() {
105
- if (this.parsedFile) return this.parsedFile.mimetype || super.getMimeType(this.filename);
106
- return super.getMimeType();
106
+ return this.parsedFile.mimetype || super.getMimeType(this.filename);
107
107
  }
108
108
  /**
109
109
  * Nom de fichier SÛR à poser dans un dossier de destination.
@@ -141,7 +141,8 @@ var UploadedFile = class UploadedFile extends FileClass {
141
141
  return super.move(name);
142
142
  } else return super.move(target);
143
143
  }
144
- throw fs.lstatSync(dirname);
144
+ fs.lstatSync(dirname);
145
+ throw new Error(`Upload target directory not found: ${dirname}`);
145
146
  }
146
147
  /**
147
148
  * Variante **async** de `move()` — déplace le fichier uploadé sans bloquer
@@ -99,7 +99,7 @@ var PrebuiltUi = class {
99
99
  return true;
100
100
  }
101
101
  kernel?.once("onReady", () => {
102
- (container?.get?.("server-static"))?.addMount?.(this.publicPath, this.distDir);
102
+ (container?.get?.("server-static"))?.addMount(this.publicPath, this.distDir);
103
103
  });
104
104
  return false;
105
105
  }