@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
package/docs/upload.md CHANGED
@@ -62,10 +62,10 @@ flowchart TD
62
62
 
63
63
  Trois idées portent tout le reste :
64
64
 
65
- 1. **Le `Content-Type` décide, pas la méthode.** `parseRequest()` (`context/http/Request.ts:429`)
65
+ 1. **Le `Content-Type` décide, pas la méthode.** `parseRequest()` (`context/http/Request.ts:451`)
66
66
  aiguille vers `ParserJson` / `ParserQs` / `ParserXml` / **busboy** / parser brut selon l'en-tête.
67
67
  2. **Seul le multipart écrit sur disque.** Les fichiers sont **streamés** au fil de l'eau vers un
68
- fichier temporaire (`parseMultipart()`, `context/http/Request.ts:499`) — jamais bufferisés en RAM.
68
+ fichier temporaire (`parseMultipart()`, `context/http/Request.ts:523`) — jamais bufferisés en RAM.
69
69
  JSON / urlencoded / XML restent en mémoire (petits corps).
70
70
  3. **Deux budgets distincts, jamais confondus.** Le corps **non-multipart** est borné par `maxBodySize`
71
71
  (défaut **1 MiB**) ; le multipart a **ses propres** limites busboy (`maxFileSize`, `maxTotalFileSize`,
@@ -117,11 +117,11 @@ Trois choix structurent l'implémentation, et chacun a une raison de sécurité
117
117
 
118
118
  **Le multipart ne touche jamais la RAM.** Là où l'ancien chemin bufferisait le corps entier, busboy lit
119
119
  le flux et écrit chaque fichier au fil de l'eau dans le dossier temporaire (`streamMultipart()`,
120
- `context/http/Request.ts:537`). Un upload de 1 Go ne coûte donc pas 1 Go de heap — seuls les petits
120
+ `context/http/Request.ts:564`). Un upload de 1 Go ne coûte donc pas 1 Go de heap — seuls les petits
121
121
  champs texte restent en mémoire. C'est ce qui rend un endpoint d'upload public tenable.
122
122
 
123
123
  **Le nom du fichier temporaire n'est jamais celui du client.** Chaque fichier reçu est écrit sous un nom
124
- `randomUUID()` + extension d'origine (`context/http/Request.ts:594`) : un nom malveillant
124
+ `randomUUID()` + extension d'origine (`context/http/Request.ts:627`) : un nom malveillant
125
125
  (`../../etc/passwd`) ne peut pas influencer le **chemin** d'écriture. Le nom d'origine est conservé en
126
126
  **métadonnée** (`filename`), pas dans le chemin.
127
127
 
@@ -257,14 +257,14 @@ sequenceDiagram
257
257
  Les points d'implémentation qui expliquent des comportements surprenants :
258
258
 
259
259
  1. **L'aiguillage lit le `Content-Type`, pas la méthode** — `parseRequest()`
260
- (`context/http/Request.ts:429`). `PATCH` porte un corps comme `POST`/`PUT` : il figure dans la table
261
- des méthodes parsées (`context/http/Request.ts:79`) — l'oubli laissait tout `PATCH` avec un corps vide.
260
+ (`context/http/Request.ts:451`). `PATCH` porte un corps comme `POST`/`PUT` : il figure dans la table
261
+ des méthodes parsées (`context/http/Request.ts:94`) — l'oubli laissait tout `PATCH` avec un corps vide.
262
262
  2. **Le multipart draine sur un `finish`, après flush de tous les writes** — `streamMultipart()`
263
- (`context/http/Request.ts:537`) accumule les `Promise` d'écriture disque et ne résout `{ fields, files }`
264
- qu'une fois tous les fichiers fermés (`context/http/Request.ts:538`).
263
+ (`context/http/Request.ts:564`) accumule les `Promise` d'écriture disque et ne résout `{ fields, files }`
264
+ qu'une fois tous les fichiers fermés (`bb.on("finish")`, `context/http/Request.ts:707`).
265
265
  3. **Une limite dépassée nettoie les temporaires déjà posés** — `abort()`
266
- (`context/http/Request.ts:557`) délie le flux, détruit les write-streams ouverts et `unlink` les temp
267
- déjà écrits (`context/http/Request.ts:568`) avant de rejeter en `413` : pas d'orphelins sur le disque.
266
+ (`context/http/Request.ts:584`) délie le flux, détruit les write-streams ouverts et `unlink` les temp
267
+ déjà écrits (`context/http/Request.ts:601`) avant de rejeter en `413` : pas d'orphelins sur le disque.
268
268
  4. **Les autres formats drainent AVANT de concaténer** — la base `Parser.parse()` attend `end`
269
269
  (`context/http/parser.ts:111`) avant `Buffer.concat` : sans ce drain, `ParserQs`/`ParserXml`
270
270
  lisaient un corps partiel → `queryPost` vide (bug de régression, cf tests).
@@ -283,11 +283,17 @@ non-multipart n'écoute pas `upload.*`.
283
283
  | `maxBodySize` | octets | `1_048_576` (1 MiB) | Plafond d'un corps **JSON / urlencoded / XML / brut** → `413`. `0` = illimité. |
284
284
 
285
285
  Deux rideaux, tous deux `runtimeMutable` (éditable à chaud) : un **pré-check** sur `Content-Length`
286
- qui rejette **avant** de lire (`enforceBodyLimit()`, `context/http/Request.ts:407`), puis un **compteur
286
+ qui rejette **avant** de lire (`enforceBodyLimit()`, `context/http/Request.ts:428`), puis un **compteur
287
287
  en streaming** qui coupe le socket si le corps déborde sans `Content-Length` honnête — chunked ou
288
288
  menteur (`Parser.write()`, `context/http/parser.ts:33`, dépassement `context/http/parser.ts:33`).
289
289
  Champ `maxBodySize` du schéma : `config/config.ts:1026`.
290
290
 
291
+ **Par requête** : `maxBodySize` et les limites `upload.*` (hors `uploadDir`) sont sur la liste blanche
292
+ du calque de configuration — une application peut les changer pour une requête
293
+ (`overlayConfig("@nodefony/http", { maxBodySize: … })`, posé dans un écouteur `onRequestScope`). Ils
294
+ sont lus au moment de lire le corps (`Request.readBodyLimits()`), donc un calque posé après ce moment
295
+ (au pare-feu, dans un contrôleur) n'agit pas. Détail : [configuration](../../../../../docs/guides/configuration.md).
296
+
291
297
  ### Fichiers multipart — `upload.*`
292
298
 
293
299
  Table dérivée de `uploadSchema` (`config/config.ts:159`). Toutes les bornes sont `runtimeMutable`.
@@ -316,16 +322,16 @@ recommandé) et les **getters** de `Controller` (impératif). Les signatures exa
316
322
 
317
323
  | Accès | Source lue | Ancrage |
318
324
  | -------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------- |
319
- | `@UploadedFiles() f: IUploadedFile[]` | tous les fichiers (`queryFile`) | `resolveParamArg` `"files"` (`routerDecorators.ts:1240`) |
320
- | `@UploadedFile() f: IUploadedFile` | le **premier** fichier | `resolveParamArg` `"file"` (`routerDecorators.ts:1239`) |
321
- | `@Body() body` | tous les champs parsés (`queryPost`) | `resolveParamArg` `"body"` (`routerDecorators.ts:1178`) |
325
+ | `@UploadedFiles() f: IUploadedFile[]` | tous les fichiers (`queryFile`) | `resolveParamArg` `"files"` (`routerDecorators.ts:1283`) |
326
+ | `@UploadedFile() f: IUploadedFile` | le **premier** fichier | `resolveParamArg` `"file"` (`routerDecorators.ts:1282`) |
327
+ | `@Body() body` | tous les champs parsés (`queryPost`) | `resolveParamArg` `"body"` (`routerDecorators.ts:1232`) |
322
328
  | `@Body("label") v` | un seul champ du body | même source, clé (`routerDecorators.ts:1223`) |
323
- | `@Body({ stream: true }) s: NodeJS.ReadableStream` | le **flux brut**, parse **sauté** | `resolveParamArg` stream (`routerDecorators.ts:1297`) |
324
- | `this.queryFile` | équivalent getter des fichiers | `Controller.queryFile` (`framework/nodefony/src/Controller.ts:239`) |
325
- | `this.queryPost` | équivalent getter des champs | `Controller.queryPost` (`framework/nodefony/src/Controller.ts:248`) |
329
+ | `@Body({ stream: true }) s: NodeJS.ReadableStream` | le **flux brut**, parse **sauté** | `resolveParamArg` stream (`routerDecorators.ts:1326`) |
330
+ | `this.queryFile` | équivalent getter des fichiers | `Controller.queryFile` (`framework/nodefony/src/Controller.ts:341`) |
331
+ | `this.queryPost` | équivalent getter des champs | `Controller.queryPost` (`framework/nodefony/src/Controller.ts:351`) |
326
332
 
327
333
  Les décorateurs `@UploadedFile` / `@UploadedFiles` sont des fabriques de paramètre
328
- (`routerDecorators.ts:1254`), exportées par `@nodefony/framework` ; leurs interfaces `IUploadedFile` /
334
+ (`routerDecorators.ts:1287`), exportées par `@nodefony/framework` ; leurs interfaces `IUploadedFile` /
329
335
  `IParsedUploadFile` viennent de `@nodefony/http` (`interfaces/IUpload.ts:49`, `interfaces/IUpload.ts:7`).
330
336
 
331
337
  ### Un fichier uploadé — `UploadedFile`
@@ -340,8 +346,8 @@ sur disque. Ses membres utiles :
340
346
  | `prettySize` | Taille lisible (`« 1.2 MB »`). | `getPrettySize()` (`service/upload/upload-service.ts:143`) |
341
347
  | `mimeType` | Type MIME déclaré (`image/png`…), sinon deviné de l'extension. | `getMimeType()` (`service/upload/upload-service.ts:153`) |
342
348
  | `hash` / `hashAlgorithm` | Empreinte d'intégrité si `upload.hashAlgorithm` est réglé. | `interfaces/IUpload.ts:55` |
343
- | `moveAsync(target)` | Déplace le temp — **non bloquant, recommandé** dans le pipeline. | `moveAsync()` (`service/upload/upload-service.ts:193`) |
344
- | `move(target)` | Variante **synchrone** (compat) — bloque l'event-loop. | `move()` (`service/upload/upload-service.ts:160`) |
349
+ | `moveAsync(target)` | Déplace le temp — **non bloquant, recommandé** dans le pipeline. | `moveAsync()` (`service/upload/upload-service.ts:218`) |
350
+ | `move(target)` | Variante **synchrone** (compat) — bloque l'event-loop. | `move()` (`service/upload/upload-service.ts:186`) |
345
351
 
346
352
  `move`/`moveAsync` acceptent un **fichier cible** ou un **dossier existant** : sur un dossier, la
347
353
  destination est bâtie avec `filename` — d'où l'avertissement de sécurité ci-dessous.
@@ -351,7 +357,7 @@ destination est bâtie avec `filename` — d'où l'avertissement de sécurité c
351
357
  Pour piper directement un très gros corps (vidéo, backup) vers le disque ou S3 sans passer par busboy ni
352
358
  par la RAM, `@Body({ stream: true })` court-circuite le parse et injecte l'`IncomingMessage` brut (un
353
359
  `Readable`). Le pipeline sait le sauter en amont via `routeExpectsBodyStream()`
354
- (`routerDecorators.ts:1379`), mémoïsé sur la route.
360
+ (`routerDecorators.ts:1408`), mémoïsé sur la route.
355
361
 
356
362
  ```ts
357
363
  // fragment — le contrôleur pipe le flux lui-même (0 parse, 0 pic RAM)
@@ -370,10 +376,10 @@ piégé. Les défenses en place, et **ce qui reste à ta charge**.
370
376
  <!-- prettier-ignore -->
371
377
  | Menace | Défense côté framework | À ta charge |
372
378
  | --- | --- | --- |
373
- | **Path traversal** (chemin d'écriture) | Le temp est nommé `randomUUID()` + extension — jamais le nom client (`context/http/Request.ts:594`). | La **destination** de `move()` (voir avertissement). |
379
+ | **Path traversal** (chemin d'écriture) | Le temp est nommé `randomUUID()` + extension — jamais le nom client (`context/http/Request.ts:627`). | La **destination** de `move()` (voir avertissement). |
374
380
  | **Saturation RAM** | Multipart streamé (jamais bufferisé) ; corps non-multipart borné (`maxBodySize`). | Resserrer `maxBodySize` selon l'endpoint. |
375
- | **Saturation disque** | `maxFileSize` + `maxTotalFileSize` + `maxFiles` ; `abort()` nettoie les temp à l'abandon (`context/http/Request.ts:557`). | Purger les temp non déplacés (TTL / cron). |
376
- | **DoS par quantité** | `maxFields` / `maxFiles` / `parts` → `413` (`context/http/Request.ts:610`). | — |
381
+ | **Saturation disque** | `maxFileSize` + `maxTotalFileSize` + `maxFiles` ; `abort()` nettoie les temp à l'abandon (`context/http/Request.ts:584`). | Purger les temp non déplacés (TTL / cron). |
382
+ | **DoS par quantité** | `maxFields` / `maxFiles` / `parts` → `413` (`context/http/Request.ts:754`). | — |
377
383
  | **Type de fichier hostile** | `mimeType` **déclaré** est exposé tel quel. | Valider le type/contenu réel (le MIME client est déclaratif). |
378
384
 
379
385
  > [!WARNING]
@@ -406,12 +412,12 @@ pipeline : `npm run test:memory` (skill `nodefony-check-memory-health`).
406
412
 
407
413
  | Domaine | Norme | Ancrage |
408
414
  | ---------------------------------- | -------------------------------- | ------------------------------------------------------------- |
409
- | Formulaire avec fichiers | RFC 7578 (`multipart/form-data`) | `parseMultipart()` via busboy (`context/http/Request.ts:499`) |
410
- | Corps trop gros → 413 | RFC 9110 §15.5.14 | `enforceBodyLimit()` (`context/http/Request.ts:407`) |
415
+ | Formulaire avec fichiers | RFC 7578 (`multipart/form-data`) | `parseMultipart()` via busboy (`context/http/Request.ts:523`) |
416
+ | Corps trop gros → 413 | RFC 9110 §15.5.14 | `enforceBodyLimit()` (`context/http/Request.ts:428`) |
411
417
  | 413 en streaming (chunked/menteur) | RFC 9110 §15.5.14 | `Parser.write()` (`context/http/parser.ts:33`) |
412
418
  | Bornes multipart → 413 | RFC 9110 §15.5.14 | `stream.on("limit")` (`context/http/Request.ts:481`) |
413
- | Défense path traversal (nom temp) | OWASP — File Upload | `randomUUID()` (`context/http/Request.ts:594`) |
414
- | Charset du corps honoré | RFC 9110 (Content-Type) | `getCharset()` (`context/http/Request.ts:799`) |
419
+ | Défense path traversal (nom temp) | OWASP — File Upload | `randomUUID()` (`context/http/Request.ts:627`) |
420
+ | Charset du corps honoré | RFC 9110 (Content-Type) | `getCharset()` (`context/http/Request.ts:824`) |
415
421
 
416
422
  ## ⚠️ Pièges
417
423
 
@@ -423,8 +429,8 @@ pipeline : `npm run test:memory` (skill `nodefony-check-memory-health`).
423
429
  | `413` sur upload sans message clair | Une borne busboy atteinte en streaming (fichier, cumul, nombre) | Vérifier les bornes `upload.*` — 413 émis sur `stream.on("limit")` (`context/http/Request.ts:481`) |
424
430
  | Un fichier écrit `../../etc/…` après un `move` | `move(dossier)` utilise le nom **client** (`upload-service.ts:197`) | Passer une cible complète, ou `path.basename(file.filename)` |
425
431
  | Des fichiers temporaires s'accumulent dans `uploadDir` | Le contrôleur ne déplace jamais le temp | Appeler `moveAsync()` (ou purger l'ancien temp par TTL) |
426
- | `queryPost` vide sur `PATCH` | Déjà géré : `PATCH` est dans la table des méthodes parsées | Aucune — corps `PATCH` parsé comme `POST` (`context/http/Request.ts:78`) |
427
- | Corps `latin1` mal décodé | Déjà géré : le `charset=` du `Content-Type` est honoré | Aucune — `getCharset()` normalise (`context/http/Request.ts:799`) |
432
+ | `queryPost` vide sur `PATCH` | Déjà géré : `PATCH` est dans la table des méthodes parsées | Aucune — corps `PATCH` parsé comme `POST` (`context/http/Request.ts:93`) |
433
+ | Corps `latin1` mal décodé | Déjà géré : le `charset=` du `Content-Type` est honoré | Aucune — `getCharset()` normalise (`context/http/Request.ts:824`) |
428
434
  | `multipart` sans boundary fait planter | `new Busboy()` throw synchrone | Déjà géré : bascule sur le parser brut (`context/http/Request.ts:502`) |
429
435
 
430
436
  ## 🧪 Tests & couverture
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodefony/http",
3
- "version": "10.0.0-alpha.9",
3
+ "version": "10.0.0-beta.1",
4
4
  "description": "Serveurs HTTP, HTTPS, HTTP/2 et WebSocket natifs pour Nodefony : sessions, contextes de requête, certificats TLS",
5
5
  "author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
6
6
  "main": "./dist/index.js",
@@ -60,31 +60,31 @@
60
60
  "qs": "^6.15.3",
61
61
  "serve-static": "2.2.1",
62
62
  "tslib": "2.8.1",
63
- "ws": "8.21.3",
63
+ "ws": "8.22.0",
64
64
  "xml2js": "0.6.2"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/chai": "5.2.3",
68
68
  "@types/mime-types": "3.0.1",
69
69
  "@types/ms": "2.1.0",
70
- "@types/node": "26.6.2",
70
+ "@types/node": "26.6.3",
71
71
  "@types/node-forge": "1.3.14",
72
72
  "@types/qs": "6.15.1",
73
73
  "@types/serve-static": "2.2.0",
74
74
  "@types/websocket": "1.0.10",
75
75
  "@types/ws": "8.18.1",
76
76
  "@types/xml2js": "0.4.14",
77
- "@vitest/coverage-v8": "5.0.1",
77
+ "@vitest/coverage-v8": "5.0.2",
78
78
  "chai": "6.2.2",
79
- "nodefony": "^10.0.0-alpha.9",
79
+ "nodefony": "^10.0.0-beta.1",
80
80
  "tsx": "4.23.15",
81
- "vitest": "5.0.1"
81
+ "vitest": "5.0.2"
82
82
  },
83
83
  "license": "Apache-2.0",
84
84
  "readmeFilename": "README.md",
85
85
  "contributors": [],
86
86
  "peerDependencies": {
87
- "nodefony": "^10.0.0-alpha.9",
87
+ "nodefony": "^10.0.0-beta.1",
88
88
  "zod": "^4.6.5"
89
89
  },
90
90
  "files": [