@nodefony/http 10.0.0-alpha.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/LICENSE +544 -0
- package/README.md +77 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js +6 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateParam.js +8 -0
- package/dist/index.js +108 -0
- package/dist/nodefony/command/assetsPublishCommand.js +102 -0
- package/dist/nodefony/command/certificatesCommand.js +47 -0
- package/dist/nodefony/command/networkCommand.js +27 -0
- package/dist/nodefony/command/proxyGenerateCommand.js +66 -0
- package/dist/nodefony/config/config.js +335 -0
- package/dist/nodefony/config/defineModuleConfig.js +93 -0
- package/dist/nodefony/interfaces/IContext.js +1 -0
- package/dist/nodefony/interfaces/ICookie.js +1 -0
- package/dist/nodefony/interfaces/IErrorRenderer.js +1 -0
- package/dist/nodefony/interfaces/IHttpConfig.js +1 -0
- package/dist/nodefony/interfaces/IHttpKernel.js +1 -0
- package/dist/nodefony/interfaces/IRequest.js +1 -0
- package/dist/nodefony/interfaces/IRequestLogger.js +1 -0
- package/dist/nodefony/interfaces/IResponse.js +1 -0
- package/dist/nodefony/interfaces/ISession.js +1 -0
- package/dist/nodefony/interfaces/IUpload.js +1 -0
- package/dist/nodefony/interfaces/index.js +1 -0
- package/dist/nodefony/service/HttpAdminApi.js +376 -0
- package/dist/nodefony/service/ProfilerAdminApi.js +73 -0
- package/dist/nodefony/service/audit-logger.js +159 -0
- package/dist/nodefony/service/certificates.js +545 -0
- package/dist/nodefony/service/error-renderer.js +320 -0
- package/dist/nodefony/service/http-kernel.js +948 -0
- package/dist/nodefony/service/pretty-request-logger.js +72 -0
- package/dist/nodefony/service/request-logger.js +54 -0
- package/dist/nodefony/service/servers/clientError.js +20 -0
- package/dist/nodefony/service/servers/server-http.js +135 -0
- package/dist/nodefony/service/servers/server-https.js +204 -0
- package/dist/nodefony/service/servers/server-static.js +192 -0
- package/dist/nodefony/service/servers/server-websocket-secure.js +104 -0
- package/dist/nodefony/service/servers/server-websocket.js +104 -0
- package/dist/nodefony/service/servers/serverShutdown.js +31 -0
- package/dist/nodefony/service/servers/wsHeartbeat.js +64 -0
- package/dist/nodefony/service/sessions/sessions-service.js +580 -0
- package/dist/nodefony/service/trace.js +72 -0
- package/dist/nodefony/service/upload/upload-service.js +171 -0
- package/dist/nodefony/src/assets/collectAssets.js +34 -0
- package/dist/nodefony/src/assets/prebuiltUi.js +125 -0
- package/dist/nodefony/src/context/Context.js +415 -0
- package/dist/nodefony/src/context/domainMatcher.js +88 -0
- package/dist/nodefony/src/context/forwarded.js +185 -0
- package/dist/nodefony/src/context/http/HttpContext.js +309 -0
- package/dist/nodefony/src/context/http/Request.js +543 -0
- package/dist/nodefony/src/context/http/Response.js +368 -0
- package/dist/nodefony/src/context/http/parser.js +188 -0
- package/dist/nodefony/src/context/http/urlFastPath.js +103 -0
- package/dist/nodefony/src/context/http2/Request.js +29 -0
- package/dist/nodefony/src/context/http2/Response.js +97 -0
- package/dist/nodefony/src/context/metaData.js +47 -0
- package/dist/nodefony/src/context/requestId.js +41 -0
- package/dist/nodefony/src/context/trustProxy.js +167 -0
- package/dist/nodefony/src/context/websocket/Response.js +181 -0
- package/dist/nodefony/src/context/websocket/WebsocketContext.js +389 -0
- package/dist/nodefony/src/context/websocket/wsBackpressure.js +56 -0
- package/dist/nodefony/src/context/websocket/wsLogContent.js +68 -0
- package/dist/nodefony/src/cookies/cookie.js +258 -0
- package/dist/nodefony/src/errors/httpError.js +69 -0
- package/dist/nodefony/src/profiler/FrameProfile.js +95 -0
- package/dist/nodefony/src/profiler/Profiler.js +139 -0
- package/dist/nodefony/src/proxy/generateProxyConfig.js +157 -0
- package/dist/nodefony/src/rateLimit/IRateLimitStore.js +1 -0
- package/dist/nodefony/src/rateLimit/MemoryRateLimitStore.js +146 -0
- package/dist/nodefony/src/rateLimit/WsConnectionCounter.js +64 -0
- package/dist/nodefony/src/rateLimit/rateLimitFilters.js +20 -0
- package/dist/nodefony/src/servers/portBinder.js +114 -0
- package/dist/nodefony/src/session/session.js +390 -0
- package/dist/nodefony/src/session/storage/MemorySessionStorage.js +185 -0
- package/dist/nodefony/src/session/storage/RevocationGuardStorage.js +137 -0
- package/dist/nodefony/src/session/storage/sessionFilters.js +83 -0
- package/dist/nodefony/src/session/storage/sessionSort.js +53 -0
- package/dist/types/index.d.ts +83 -0
- package/dist/types/nodefony/command/assetsPublishCommand.d.ts +23 -0
- package/dist/types/nodefony/command/certificatesCommand.d.ts +17 -0
- package/dist/types/nodefony/command/networkCommand.d.ts +8 -0
- package/dist/types/nodefony/command/proxyGenerateCommand.d.ts +19 -0
- package/dist/types/nodefony/config/config.d.ts +197 -0
- package/dist/types/nodefony/config/defineModuleConfig.d.ts +39 -0
- package/dist/types/nodefony/interfaces/IContext.d.ts +138 -0
- package/dist/types/nodefony/interfaces/ICookie.d.ts +47 -0
- package/dist/types/nodefony/interfaces/IErrorRenderer.d.ts +55 -0
- package/dist/types/nodefony/interfaces/IHttpConfig.d.ts +12 -0
- package/dist/types/nodefony/interfaces/IHttpKernel.d.ts +10 -0
- package/dist/types/nodefony/interfaces/IRequest.d.ts +35 -0
- package/dist/types/nodefony/interfaces/IRequestLogger.d.ts +31 -0
- package/dist/types/nodefony/interfaces/IResponse.d.ts +39 -0
- package/dist/types/nodefony/interfaces/ISession.d.ts +283 -0
- package/dist/types/nodefony/interfaces/IUpload.d.ts +66 -0
- package/dist/types/nodefony/interfaces/index.d.ts +7 -0
- package/dist/types/nodefony/service/HttpAdminApi.d.ts +18 -0
- package/dist/types/nodefony/service/ProfilerAdminApi.d.ts +23 -0
- package/dist/types/nodefony/service/audit-logger.d.ts +143 -0
- package/dist/types/nodefony/service/certificates.d.ts +246 -0
- package/dist/types/nodefony/service/error-renderer.d.ts +74 -0
- package/dist/types/nodefony/service/http-kernel.d.ts +377 -0
- package/dist/types/nodefony/service/pretty-request-logger.d.ts +25 -0
- package/dist/types/nodefony/service/request-logger.d.ts +18 -0
- package/dist/types/nodefony/service/servers/clientError.d.ts +14 -0
- package/dist/types/nodefony/service/servers/server-http.d.ts +42 -0
- package/dist/types/nodefony/service/servers/server-https.d.ts +41 -0
- package/dist/types/nodefony/service/servers/server-static.d.ts +62 -0
- package/dist/types/nodefony/service/servers/server-websocket-secure.d.ts +29 -0
- package/dist/types/nodefony/service/servers/server-websocket.d.ts +29 -0
- package/dist/types/nodefony/service/servers/serverShutdown.d.ts +27 -0
- package/dist/types/nodefony/service/servers/wsHeartbeat.d.ts +46 -0
- package/dist/types/nodefony/service/sessions/sessions-service.d.ts +218 -0
- package/dist/types/nodefony/service/trace.d.ts +39 -0
- package/dist/types/nodefony/service/upload/upload-service.d.ts +61 -0
- package/dist/types/nodefony/src/assets/collectAssets.d.ts +35 -0
- package/dist/types/nodefony/src/assets/prebuiltUi.d.ts +99 -0
- package/dist/types/nodefony/src/context/Context.d.ts +195 -0
- package/dist/types/nodefony/src/context/domainMatcher.d.ts +67 -0
- package/dist/types/nodefony/src/context/forwarded.d.ts +95 -0
- package/dist/types/nodefony/src/context/http/HttpContext.d.ts +85 -0
- package/dist/types/nodefony/src/context/http/Request.d.ts +203 -0
- package/dist/types/nodefony/src/context/http/Response.d.ts +68 -0
- package/dist/types/nodefony/src/context/http/parser.d.ts +65 -0
- package/dist/types/nodefony/src/context/http/urlFastPath.d.ts +52 -0
- package/dist/types/nodefony/src/context/http2/Request.d.ts +14 -0
- package/dist/types/nodefony/src/context/http2/Response.d.ts +20 -0
- package/dist/types/nodefony/src/context/metaData.d.ts +58 -0
- package/dist/types/nodefony/src/context/requestId.d.ts +28 -0
- package/dist/types/nodefony/src/context/trustProxy.d.ts +77 -0
- package/dist/types/nodefony/src/context/websocket/Response.d.ts +53 -0
- package/dist/types/nodefony/src/context/websocket/WebsocketContext.d.ts +125 -0
- package/dist/types/nodefony/src/context/websocket/wsBackpressure.d.ts +73 -0
- package/dist/types/nodefony/src/context/websocket/wsLogContent.d.ts +37 -0
- package/dist/types/nodefony/src/cookies/cookie.d.ts +88 -0
- package/dist/types/nodefony/src/errors/httpError.d.ts +15 -0
- package/dist/types/nodefony/src/profiler/FrameProfile.d.ts +110 -0
- package/dist/types/nodefony/src/profiler/Profiler.d.ts +192 -0
- package/dist/types/nodefony/src/proxy/generateProxyConfig.d.ts +76 -0
- package/dist/types/nodefony/src/rateLimit/IRateLimitStore.d.ts +98 -0
- package/dist/types/nodefony/src/rateLimit/MemoryRateLimitStore.d.ts +40 -0
- package/dist/types/nodefony/src/rateLimit/WsConnectionCounter.d.ts +37 -0
- package/dist/types/nodefony/src/rateLimit/rateLimitFilters.d.ts +18 -0
- package/dist/types/nodefony/src/servers/portBinder.d.ts +102 -0
- package/dist/types/nodefony/src/session/session.d.ts +171 -0
- package/dist/types/nodefony/src/session/storage/MemorySessionStorage.d.ts +77 -0
- package/dist/types/nodefony/src/session/storage/RevocationGuardStorage.d.ts +81 -0
- package/dist/types/nodefony/src/session/storage/sessionFilters.d.ts +102 -0
- package/dist/types/nodefony/src/session/storage/sessionSort.d.ts +45 -0
- package/docs/cookies.md +365 -0
- package/docs/index.md +163 -0
- package/docs/observabilite.md +460 -0
- package/docs/rate-limit.md +372 -0
- package/docs/servers.md +935 -0
- package/docs/session.md +768 -0
- package/docs/upload.md +460 -0
- package/package.json +101 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
//#region nodefony/src/session/storage/RevocationGuardStorage.ts
|
|
2
|
+
/**
|
|
3
|
+
* Durée de vie (ms) d'une pierre tombale de révocation. Couvre la fenêtre
|
|
4
|
+
* pendant laquelle une requête « en vol » — qui avait chargé la session AVANT
|
|
5
|
+
* sa révocation — pourrait tenter un `write` tardif (autosave de fin de requête)
|
|
6
|
+
* et la ressusciter. Une requête HTTP dure des secondes ; on prend large (5 min)
|
|
7
|
+
* pour couvrir les requêtes longues (upload/SSE) sans risque : un id révoqué
|
|
8
|
+
* n'est JAMAIS réémis (ids opaques CSPRNG), tombstoner ne bloque aucune session
|
|
9
|
+
* légitime.
|
|
10
|
+
*/
|
|
11
|
+
const TOMBSTONE_TTL_MS = 3e5;
|
|
12
|
+
/**
|
|
13
|
+
* Garde-fou de révocation **décoré au-dessus** de n'importe quel
|
|
14
|
+
* {@link ISessionStorage} (file, drizzle, redis, mongo…). Pose une « pierre
|
|
15
|
+
* tombale » sur tout id détruit et REFUSE un `write` ultérieur de ce même id
|
|
16
|
+
* pendant {@link TOMBSTONE_TTL_MS}.
|
|
17
|
+
*
|
|
18
|
+
* **Pourquoi ici, pas dans chaque store** : la résurrection est une propriété du
|
|
19
|
+
* CYCLE DE VIE de session — révoquer une session puis l'autosave de fin de
|
|
20
|
+
* requête (la requête la portait encore en mémoire, `dirty`) la ré-écrit — et
|
|
21
|
+
* NON d'un backend particulier. Un seul garde-fou décoré sur le storage actif
|
|
22
|
+
* couvre donc TOUS les backends, présents et futurs, **sans en modifier aucun**.
|
|
23
|
+
*
|
|
24
|
+
* Découvert en live le 2026-06-21 (« révoquer une session ne déconnecte pas ») ;
|
|
25
|
+
* le store réel était `drizzle`, pas `files` — d'où la décoration générique.
|
|
26
|
+
*
|
|
27
|
+
* Couvre deux scénarios :
|
|
28
|
+
* - **self** : l'admin révoque SA PROPRE session ; l'autosave de la requête de
|
|
29
|
+
* révocation tente de la réécrire → refusé.
|
|
30
|
+
* - **race** : un autre client du user révoqué a une requête en vol dont
|
|
31
|
+
* l'autosave arrive après la révocation → refusé.
|
|
32
|
+
*
|
|
33
|
+
* **Perf** : décorateur **singleton** (1 par service). Délégation directe sur le
|
|
34
|
+
* hot-path lecture (`read`/`start`/`listAll`) ; `write` ne paie qu'un test
|
|
35
|
+
* `=== null` tant qu'aucune session n'a été révoquée (Map **lazy**, jamais de
|
|
36
|
+
* `Date.now()` dans ce cas).
|
|
37
|
+
*/
|
|
38
|
+
var RevocationGuardStorage = class {
|
|
39
|
+
/** Storage réel décoré — exposé pour l'introspection admin (nom du driver). */
|
|
40
|
+
inner;
|
|
41
|
+
/** `id → epoch ms d'expiration`. **Lazy** : `null` tant qu'aucune révocation. */
|
|
42
|
+
#tombstones = null;
|
|
43
|
+
/**
|
|
44
|
+
* Énumération admin — (ré)assignée dans le constructeur **uniquement** si le
|
|
45
|
+
* backend décoré la supporte, pour que `SessionsService.supportsEnumeration`
|
|
46
|
+
* (`typeof storage.listAll === "function"`) reflète la vraie capacité du store.
|
|
47
|
+
*/
|
|
48
|
+
listAll;
|
|
49
|
+
/**
|
|
50
|
+
* Touch (prolongation d'idle) — (ré)assignée seulement si le backend décoré la
|
|
51
|
+
* supporte, pour que `Session.touchIfNeeded` (`typeof storage.touch`) reflète la
|
|
52
|
+
* vraie capacité. **Respecte la pierre tombale** : ne prolonge JAMAIS une session
|
|
53
|
+
* révoquée (cohérent avec `write` — une révocation ne doit pas être contournée
|
|
54
|
+
* par un touch tardif d'une requête en vol).
|
|
55
|
+
*/
|
|
56
|
+
touch;
|
|
57
|
+
/**
|
|
58
|
+
* Énumération admin **paginée** — (ré)assignée seulement si le backend décoré
|
|
59
|
+
* la supporte, même raison que {@link listAll} : `supportsEnumeration` teste la
|
|
60
|
+
* présence de la méthode, elle doit donc refléter la vraie capacité du store
|
|
61
|
+
* décoré et non celle du décorateur.
|
|
62
|
+
*/
|
|
63
|
+
listPage;
|
|
64
|
+
/** `COUNT` filtré — (ré)assigné seulement si le backend décoré le supporte. */
|
|
65
|
+
countSessions;
|
|
66
|
+
/**
|
|
67
|
+
* `COUNT(DISTINCT user)` — (ré)assigné seulement si le backend décoré le
|
|
68
|
+
* supporte, même raison que {@link countSessions} : une capacité perdue dans
|
|
69
|
+
* le décorateur ferait afficher « inconnu » là où la base sait répondre.
|
|
70
|
+
*/
|
|
71
|
+
countDistinctUsers;
|
|
72
|
+
/**
|
|
73
|
+
* Capacité de tri du backend décoré, relayée telle quelle.
|
|
74
|
+
*
|
|
75
|
+
* Une capacité qui se PERD dans un décorateur est pire qu'une capacité
|
|
76
|
+
* absente : elle est déclarée par le store réel, invisible au-dessus, et le
|
|
77
|
+
* data plane refuse alors (400) un tri que la base sait parfaitement faire.
|
|
78
|
+
* Comme ce décorateur est posé en production dès qu'une révocation est
|
|
79
|
+
* possible, l'oubli aurait désactivé le tri **partout**.
|
|
80
|
+
*/
|
|
81
|
+
sortableFields;
|
|
82
|
+
constructor(inner) {
|
|
83
|
+
this.inner = inner;
|
|
84
|
+
this.sortableFields = inner.sortableFields;
|
|
85
|
+
if (typeof inner.listAll === "function") this.listAll = (filter) => inner.listAll(filter);
|
|
86
|
+
if (typeof inner.listPage === "function") this.listPage = (query) => inner.listPage(query);
|
|
87
|
+
if (typeof inner.countSessions === "function") this.countSessions = (query) => inner.countSessions(query);
|
|
88
|
+
if (typeof inner.countDistinctUsers === "function") this.countDistinctUsers = (query) => inner.countDistinctUsers(query);
|
|
89
|
+
if (typeof inner.touch === "function") this.touch = (id, idleSeconds) => {
|
|
90
|
+
if (this.#isRevoked(id)) return Promise.resolve();
|
|
91
|
+
return inner.touch(id, idleSeconds);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
read(id) {
|
|
95
|
+
return this.inner.read(id);
|
|
96
|
+
}
|
|
97
|
+
start(id) {
|
|
98
|
+
return this.inner.start(id);
|
|
99
|
+
}
|
|
100
|
+
open() {
|
|
101
|
+
return this.inner.open();
|
|
102
|
+
}
|
|
103
|
+
close() {
|
|
104
|
+
return this.inner.close();
|
|
105
|
+
}
|
|
106
|
+
gc(idleSeconds, absoluteSeconds) {
|
|
107
|
+
return this.inner.gc(idleSeconds, absoluteSeconds);
|
|
108
|
+
}
|
|
109
|
+
async destroy(id) {
|
|
110
|
+
this.#revoke(id);
|
|
111
|
+
return this.inner.destroy(id);
|
|
112
|
+
}
|
|
113
|
+
write(id, data) {
|
|
114
|
+
if (this.#isRevoked(id)) return Promise.resolve(data);
|
|
115
|
+
return this.inner.write(id, data);
|
|
116
|
+
}
|
|
117
|
+
#revoke(id) {
|
|
118
|
+
const now = Date.now();
|
|
119
|
+
this.#purgeExpired(now);
|
|
120
|
+
if (this.#tombstones === null) this.#tombstones = /* @__PURE__ */ new Map();
|
|
121
|
+
this.#tombstones.set(id, now + TOMBSTONE_TTL_MS);
|
|
122
|
+
}
|
|
123
|
+
#isRevoked(id) {
|
|
124
|
+
const t = this.#tombstones;
|
|
125
|
+
if (t === null) return false;
|
|
126
|
+
const expiry = t.get(id);
|
|
127
|
+
return expiry !== void 0 && expiry > Date.now();
|
|
128
|
+
}
|
|
129
|
+
#purgeExpired(now) {
|
|
130
|
+
const t = this.#tombstones;
|
|
131
|
+
if (t === null) return;
|
|
132
|
+
for (const [id, expiry] of t) if (expiry <= now) t.delete(id);
|
|
133
|
+
if (t.size === 0) this.#tombstones = null;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
//#endregion
|
|
137
|
+
export { RevocationGuardStorage as default };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region nodefony/src/session/storage/sessionFilters.ts
|
|
2
|
+
/**
|
|
3
|
+
* **Le vocabulaire de filtre des sessions**, en noms PUBLICS — celui que la
|
|
4
|
+
* console d'administration écrit dans l'URL (`?user=alice`).
|
|
5
|
+
*
|
|
6
|
+
* Frère de `SESSION_SORTABLE_FIELDS` (`sessionSort.ts`), posé au même endroit
|
|
7
|
+
* pour la même raison : le vocabulaire appartient au module propriétaire du
|
|
8
|
+
* contrat, la mécanique de lecture au cœur (`parseFilters`).
|
|
9
|
+
*
|
|
10
|
+
* `user` est un filtre **portable par construction** (égalité stricte) : il
|
|
11
|
+
* s'exprime dans tous les backends — `WHERE` indexé en SQL et Mongo, prédicat en
|
|
12
|
+
* mémoire, filtre de batch en Redis — donc aucun store n'a besoin de matérialiser
|
|
13
|
+
* la collection pour l'honorer. C'est la propriété qui justifie qu'il soit au
|
|
14
|
+
* contrat plutôt que dans une couche de filtrage applicative.
|
|
15
|
+
*
|
|
16
|
+
* `tenantId` n'y figure pas parce qu'il appartient au **contrat de page**
|
|
17
|
+
* (`PAGE_QUERY_KEYS`, réserve multi-tenant) : le déclarer ici en ferait un
|
|
18
|
+
* second lecteur du même paramètre.
|
|
19
|
+
*/
|
|
20
|
+
const SESSION_FILTERS = {
|
|
21
|
+
/** Sessions d'un utilisateur donné (égalité stricte sur l'identifiant). */
|
|
22
|
+
user: "string",
|
|
23
|
+
/**
|
|
24
|
+
* `true` = sessions rattachées à un utilisateur, `false` = anonymes, absent =
|
|
25
|
+
* les deux. Le contrat le définit comme « `user` non vide » — tous les stores
|
|
26
|
+
* l'honorent déjà (c'est ainsi que `sessions/stats` compte ses facettes).
|
|
27
|
+
*
|
|
28
|
+
* Il n'était pas exposé à l'URL, et la console ne pouvait donc pas MONTRER la
|
|
29
|
+
* population qu'elle affichait en carte : cliquer « Anonymes » demandait un
|
|
30
|
+
* paramètre que la liste refusait. Une facette n'existe que si le contrat de
|
|
31
|
+
* liste sait la filtrer — celle-ci le savait partout sauf sur le fil.
|
|
32
|
+
*
|
|
33
|
+
* ⚠️ Redondant avec `user` **par construction** (même donnée). Les combiner
|
|
34
|
+
* de façon contradictoire (`?user=alice&authenticated=false`) rend l'ENSEMBLE
|
|
35
|
+
* VIDE, jamais la page de l'un des deux — garde posée dans le banc de contrat
|
|
36
|
+
* partagé, donc rejouée sur les six backends.
|
|
37
|
+
*/
|
|
38
|
+
authenticated: "boolean"
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* **Les facettes des sessions** — les questions fermées que la console pose à la
|
|
42
|
+
* collection ENTIÈRE, pour ses cartes de tête.
|
|
43
|
+
*
|
|
44
|
+
* Distinct de `SESSION_FILTERS`, qui dit ce qu'un client a le droit d'écrire
|
|
45
|
+
* dans l'URL : une facette n'est pas saisie, elle est posée par le serveur. Les
|
|
46
|
+
* deux se recoupent par construction — une facette n'existe que si le contrat de
|
|
47
|
+
* liste sait déjà la filtrer, sinon elle serait un compteur approximatif de plus.
|
|
48
|
+
*
|
|
49
|
+
* `authenticated` suffit à couvrir les deux populations : le contrat le définit
|
|
50
|
+
* comme « `user` non vide », donc `false` rend exactement les sessions anonymes.
|
|
51
|
+
* Aucune facette n'est déduite d'une soustraction (cf `countFacets`).
|
|
52
|
+
*
|
|
53
|
+
* Le décompte d'utilisateurs **distincts** n'est PAS ici : ce n'est pas un
|
|
54
|
+
* `COUNT` filtré mais une agrégation, qu'un store en curseur ne peut pas rendre.
|
|
55
|
+
* Il vit en capacité déclarée du backend (`ISessionStorage.countDistinctUsers`).
|
|
56
|
+
*/
|
|
57
|
+
const SESSION_FACETS = {
|
|
58
|
+
/** Toutes les sessions persistées, sans filtre. */
|
|
59
|
+
total: {},
|
|
60
|
+
/** Sessions rattachées à un utilisateur authentifié. */
|
|
61
|
+
authenticated: { authenticated: true },
|
|
62
|
+
/** Sessions anonymes (aucun utilisateur rattaché). */
|
|
63
|
+
anonymous: { authenticated: false }
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Ce que l'endpoint de COMPTEURS accepte de filtrer — {@link SESSION_FILTERS}
|
|
67
|
+
* **moins** le champ que ses facettes décomposent (`authenticated`).
|
|
68
|
+
*
|
|
69
|
+
* Le demander ici rendrait une réponse qui se contredit : le total suivrait le
|
|
70
|
+
* filtre pendant que chaque facette l'écraserait par le sien (« 5 sessions au
|
|
71
|
+
* total, dont 40 anonymes »). `user` reste : il découpe une AUTRE dimension, et
|
|
72
|
+
* « combien de sessions pour alice, dont combien d'anonymes ? » est une question
|
|
73
|
+
* cohérente — qui rend d'ailleurs l'ensemble vide, la réponse honnête.
|
|
74
|
+
*
|
|
75
|
+
* Frère de `USER_STATS_FILTERS` / `TOKEN_STATS_FILTERS` / `WEBHOOK_STATS_FILTERS`.
|
|
76
|
+
* Les sessions n'en avaient pas : `authenticated` n'était exposé nulle part, si
|
|
77
|
+
* bien que le trou était fermé par accident plutôt que par décision. Ouvrir le
|
|
78
|
+
* filtre sur la liste — pour que les cartes deviennent cliquables — l'aurait
|
|
79
|
+
* rouvert du même geste.
|
|
80
|
+
*/
|
|
81
|
+
const SESSION_STATS_FILTERS = { user: "string" };
|
|
82
|
+
//#endregion
|
|
83
|
+
export { SESSION_FACETS, SESSION_FILTERS, SESSION_STATS_FILTERS };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { renameOrderFields } from "nodefony";
|
|
2
|
+
//#region nodefony/src/session/storage/sessionSort.ts
|
|
3
|
+
/**
|
|
4
|
+
* **Le vocabulaire de tri des sessions**, en noms PUBLICS — ceux qu'un client
|
|
5
|
+
* écrit dans l'URL (`?order=updatedAt:DESC`), jamais des noms de colonne.
|
|
6
|
+
*
|
|
7
|
+
* Il vit ici, chez le propriétaire du contrat (`@nodefony/http`), et non dans
|
|
8
|
+
* chaque backend : c'est ce qui garantit qu'une console offre le même tri que
|
|
9
|
+
* l'application tourne sur mémoire, SQLite, PostgreSQL ou Mongo. Un store qui
|
|
10
|
+
* nomme ses colonnes autrement (SQL stocke l'identifiant en `session_id`)
|
|
11
|
+
* **traduit chez lui** — cf {@link SESSION_COLUMN_ALIASES}.
|
|
12
|
+
*
|
|
13
|
+
* - `updatedAt` — dernière activité (l'axe naturel d'une console de sessions).
|
|
14
|
+
* - `createdAt` — ouverture de la session (« qui s'est connecté en premier »).
|
|
15
|
+
* - `user` — porteur, pour regrouper les sessions d'un même compte à l'œil.
|
|
16
|
+
* - `id` — identifiant de session, utile surtout en départage.
|
|
17
|
+
*
|
|
18
|
+
* Ce que la liste n'inclut PAS, et pourquoi : `ip` et `ua` ne sont **pas des
|
|
19
|
+
* champs** mais des entrées du sac de métadonnées (`metaBag`, sérialisé en
|
|
20
|
+
* JSON). Aucun backend ne peut les ordonner sans matérialiser la collection —
|
|
21
|
+
* la console les affiche donc en colonnes non triables, au lieu d'offrir un
|
|
22
|
+
* tri qui serait refusé (SQL) ou coûteux (mémoire).
|
|
23
|
+
*/
|
|
24
|
+
const SESSION_SORTABLE_FIELDS = [
|
|
25
|
+
"updatedAt",
|
|
26
|
+
"createdAt",
|
|
27
|
+
"user",
|
|
28
|
+
"id"
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Ordre contractuel appliqué quand le client n'en demande aucun : activité la
|
|
32
|
+
* plus récente d'abord, départagée par identifiant pour rester **déterministe**
|
|
33
|
+
* à horodatage égal (sans quoi une pagination peut sauter ou répéter une ligne
|
|
34
|
+
* entre deux pages).
|
|
35
|
+
*/
|
|
36
|
+
const SESSION_DEFAULT_ORDER = [["updatedAt", "DESC"], ["id", "ASC"]];
|
|
37
|
+
/**
|
|
38
|
+
* Table d'alias des backends dont le schéma nomme l'identifiant de session
|
|
39
|
+
* `session_id` (SQL comme Mongo) — à passer à `renameOrderFields` (core).
|
|
40
|
+
*
|
|
41
|
+
* C'est une **donnée** du schéma, pas du code : la règle « réécrire les noms »
|
|
42
|
+
* vit au core en un exemplaire, et chaque backend n'apporte que sa table. Sans
|
|
43
|
+
* cette traduction, `?order=id:ASC` partirait vers une colonne `id` inexistante
|
|
44
|
+
* — l'erreur ne se verrait qu'à l'exécution, sur le backend concerné seulement.
|
|
45
|
+
*/
|
|
46
|
+
const SESSION_COLUMN_ALIASES = { id: "session_id" };
|
|
47
|
+
/**
|
|
48
|
+
* Ordre par défaut des backends dont le schéma nomme l'identifiant
|
|
49
|
+
* `session_id` — {@link SESSION_DEFAULT_ORDER} déjà traduit.
|
|
50
|
+
*/
|
|
51
|
+
const SESSION_DEFAULT_ORDER_SQL = renameOrderFields(SESSION_DEFAULT_ORDER, SESSION_COLUMN_ALIASES);
|
|
52
|
+
//#endregion
|
|
53
|
+
export { SESSION_COLUMN_ALIASES, SESSION_DEFAULT_ORDER, SESSION_DEFAULT_ORDER_SQL, SESSION_SORTABLE_FIELDS };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Kernel, Module } from "nodefony";
|
|
2
|
+
import type { IHttpConfig, IHttpConfigInput } from "./nodefony/interfaces/IHttpConfig.js";
|
|
3
|
+
import { Profiler } from "./nodefony/src/profiler/Profiler.js";
|
|
4
|
+
import HttpKernel from "./nodefony/service/http-kernel.js";
|
|
5
|
+
import SessionsService from "./nodefony/service/sessions/sessions-service.js";
|
|
6
|
+
import Context from "./nodefony/src/context/Context.js";
|
|
7
|
+
import Session from "./nodefony/src/session/session.js";
|
|
8
|
+
import HttpError from "./nodefony/src/errors/httpError.js";
|
|
9
|
+
import Response from "./nodefony/src/context/http/Response.js";
|
|
10
|
+
import Http2Response from "./nodefony/src/context/http2/Response.js";
|
|
11
|
+
import wsResponse from "./nodefony/src/context/websocket/Response.js";
|
|
12
|
+
import Cookie from "./nodefony/src/cookies/cookie.js";
|
|
13
|
+
import DefaultErrorRenderer from "./nodefony/service/error-renderer.js";
|
|
14
|
+
import DefaultRequestLogger from "./nodefony/service/request-logger.js";
|
|
15
|
+
import JsonAuditLogger from "./nodefony/service/audit-logger.js";
|
|
16
|
+
import PrettyRequestLogger from "./nodefony/service/pretty-request-logger.js";
|
|
17
|
+
import HttpContext from "./nodefony/src/context/http/HttpContext.js";
|
|
18
|
+
import WebsocketContext from "./nodefony/src/context/websocket/WebsocketContext.js";
|
|
19
|
+
import HttpRequest from "./nodefony/src/context/http/Request.js";
|
|
20
|
+
import Http2Request from "./nodefony/src/context/http2/Request.js";
|
|
21
|
+
declare module "nodefony" {
|
|
22
|
+
interface NodefonyModuleConfig {
|
|
23
|
+
"@nodefony/http": IHttpConfigInput;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
declare class Http extends Module<IHttpConfig> {
|
|
27
|
+
constructor(kernel: Kernel);
|
|
28
|
+
/**
|
|
29
|
+
* Expose le JSON Schema de la config http (dérivé du schéma Zod, flags `meta()`
|
|
30
|
+
* inclus) au data plane admin → Studio rend la config en réglages documentés
|
|
31
|
+
* (type, défaut, état, valeur effective) au lieu d'un dump brut. Override du
|
|
32
|
+
* seam {@link Module.configSchema}.
|
|
33
|
+
*/
|
|
34
|
+
configSchema(): unknown;
|
|
35
|
+
/**
|
|
36
|
+
* Phase `onRegister` : valide la config (défauts + override `module-http` +
|
|
37
|
+
* défauts kernel) via `defineHttpConfig`, puis la ré-assigne à `this.options`
|
|
38
|
+
* AVANT l'instanciation des `@services` (phase `onBoot`). Plante propre avec
|
|
39
|
+
* messages clairs si la config est invalide (convention Zod figée 2026-05-28).
|
|
40
|
+
*
|
|
41
|
+
* Config NON gelée : les services mutent `module.options` (upload `uploadDir`,
|
|
42
|
+
* certificats `serialNumber`) — cf `defineHttpConfig`.
|
|
43
|
+
*/
|
|
44
|
+
onKernelRegister(): Promise<this>;
|
|
45
|
+
/**
|
|
46
|
+
* Phase `onBoot` : s'enregistre comme producteur admin (`/nodefony/http/api/*`)
|
|
47
|
+
* auprès du broker, AVANT que framework ne monte le data plane à `onReady`.
|
|
48
|
+
*
|
|
49
|
+
* Importe seulement `IAdminRegistry` (core) — jamais `@nodefony/framework`
|
|
50
|
+
* (dépendance circulaire). Le broker est résolu du container partagé.
|
|
51
|
+
*/
|
|
52
|
+
onKernelBoot(): Promise<this>;
|
|
53
|
+
onKernelReady(): Promise<this>;
|
|
54
|
+
}
|
|
55
|
+
export default Http;
|
|
56
|
+
export { defineHttpConfig, httpConfigJsonSchema, } from "./nodefony/config/defineModuleConfig.js";
|
|
57
|
+
export { httpConfigSchema, type HttpConfig, type HttpConfigInput, } from "./nodefony/config/config.js";
|
|
58
|
+
export type { IHttpConfig, IHttpConfigInput, } from "./nodefony/interfaces/IHttpConfig.js";
|
|
59
|
+
export { decideSend, readBackpressureOptions, type WsBackpressurePolicy, type WsSendDecision, type IWsBackpressureOptions, type IBackpressureSocket, type IBackpressureTarget, } from "./nodefony/src/context/websocket/wsBackpressure.js";
|
|
60
|
+
export { compileDomainPattern, compileDomainPatterns, compileTrustedHosts, isDomainAllowed, } from "./nodefony/src/context/domainMatcher.js";
|
|
61
|
+
export type { DomainPattern, TrustedHostsConfig, } from "./nodefony/src/context/domainMatcher.js";
|
|
62
|
+
export { MemoryRateLimitStore } from "./nodefony/src/rateLimit/MemoryRateLimitStore.js";
|
|
63
|
+
export type { IRateLimitStore, IRateLimitOptions, RateLimitVerdict, } from "./nodefony/src/rateLimit/IRateLimitStore.js";
|
|
64
|
+
export { Context, Session, SessionsService, HttpError, HttpKernel, Response, Http2Response, Response as HttpResponse, wsResponse, wsResponse as WebsocketResponse, Cookie, HttpContext, WebsocketContext, HttpRequest, Http2Request, DefaultErrorRenderer, DefaultRequestLogger, JsonAuditLogger, PrettyRequestLogger, Profiler, };
|
|
65
|
+
export { schemaMismatchOf, type SchemaMismatchConfidence, } from "./nodefony/service/error-renderer.js";
|
|
66
|
+
export type { ProfileEntry, ProfileSummary, ProfilePhase, ProfileQuery, ProfileSecurity, } from "./nodefony/src/profiler/Profiler.js";
|
|
67
|
+
export { FrameProfile } from "./nodefony/src/profiler/FrameProfile.js";
|
|
68
|
+
export type { FrameProfileInit, ProfiledArea, ProfiledResolver, } from "./nodefony/src/profiler/FrameProfile.js";
|
|
69
|
+
export { resolveUiDelivery, PrebuiltUi, } from "./nodefony/src/assets/prebuiltUi.js";
|
|
70
|
+
export type { UiDeliveryMode, UiDeliveryResolved, IUiDeliveryResolution, IUiDeliveryOptions, IPrebuiltUiOptions, } from "./nodefony/src/assets/prebuiltUi.js";
|
|
71
|
+
export type { IContext, IHttpContext, IWebsocketContext, ServerType, SchemeType, WebSocketStateType, CookiesMap, ISecurityTrace, SecurityOutcome, } from "./nodefony/interfaces/IContext.js";
|
|
72
|
+
export type { ICookie, ICookieOptions, IWsCookie, SameSiteType, PriorityType, } from "./nodefony/interfaces/ICookie.js";
|
|
73
|
+
export type { ISession, ISessionStorage, ISerializedSession, ISessionSummary, ISessionRecord, ISessionListFilter, ISessionListQuery, SessionIntent, SessionStatusType, SessionStrategyType, FlashBagType, MetaBagType, } from "./nodefony/interfaces/ISession.js";
|
|
74
|
+
export { SESSION_SORTABLE_FIELDS, SESSION_DEFAULT_ORDER, SESSION_DEFAULT_ORDER_SQL, SESSION_COLUMN_ALIASES, } from "./nodefony/src/session/storage/sessionSort.js";
|
|
75
|
+
export type { IHttpRequest, IHttp2Request, IWsRequest, HTTPMethodType, } from "./nodefony/interfaces/IRequest.js";
|
|
76
|
+
export type { IHttpResponse, IWebsocketResponse, } from "./nodefony/interfaces/IResponse.js";
|
|
77
|
+
export type { IHttpKernel } from "./nodefony/interfaces/IHttpKernel.js";
|
|
78
|
+
export type { IUploadedFile, IUploadService, IParsedUploadFile, IUploadOptions, } from "./nodefony/interfaces/IUpload.js";
|
|
79
|
+
export type { IErrorRenderer, IErrorHttpResult, IErrorWebsocketResult, } from "./nodefony/interfaces/IErrorRenderer.js";
|
|
80
|
+
export type { IRequestLogger, IRequestLogEntry, } from "./nodefony/interfaces/IRequestLogger.js";
|
|
81
|
+
export type { AuditLogEntry, AuditErrorEntry, JsonAuditLoggerOptions, } from "./nodefony/service/audit-logger.js";
|
|
82
|
+
export type { ContextType, httpRequest, httpResponse, ProtocolType, } from "./nodefony/service/http-kernel.js";
|
|
83
|
+
export type { contextRequest, contextResponse, HTTPMethod, WebSocketState, Cookies, } from "./nodefony/src/context/Context.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CliKernel, Command } from "nodefony";
|
|
2
|
+
/**
|
|
3
|
+
* Commande CLI `assets:publish` — assemble TOUS les assets statiques servables
|
|
4
|
+
* (publics de module montés sous `/<module>/` + bundles `@nodefony/frontend`
|
|
5
|
+
* sous `/_assets/<name>/`) dans UN arbre `dist-assets/` miroir des préfixes
|
|
6
|
+
* d'URL, plus un `manifest.json`.
|
|
7
|
+
*
|
|
8
|
+
* Provider-agnostic — Nodefony ASSEMBLE, l'orchestrateur PUBLIE (cloud-native) :
|
|
9
|
+
* `aws s3 sync dist-assets s3://bucket`, `rsync`, upload CI… Pas de dépendance
|
|
10
|
+
* cloud embarquée dans le framework. Combine avec `frontend.assetBaseUrl` pour
|
|
11
|
+
* que les URLs émises pointent le CDN qui sert cet arbre.
|
|
12
|
+
*/
|
|
13
|
+
declare class AssetsPublish extends Command {
|
|
14
|
+
constructor(cli: CliKernel);
|
|
15
|
+
generate(opts: {
|
|
16
|
+
out?: string;
|
|
17
|
+
clean?: boolean;
|
|
18
|
+
json?: boolean;
|
|
19
|
+
}): Promise<this>;
|
|
20
|
+
/** Sources = mounts natifs (`server-static`) + bundles `@nodefony/frontend`. */
|
|
21
|
+
private collectSources;
|
|
22
|
+
}
|
|
23
|
+
export default AssetsPublish;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CliKernel, Command } from "nodefony";
|
|
2
|
+
/**
|
|
3
|
+
* Commande CLI `certificates` — (re)génère et inspecte le certificat TLS de
|
|
4
|
+
* DÉVELOPPEMENT. La génération reste un confort de dev : en production, fournir
|
|
5
|
+
* un vrai certificat (`certificates.strategy: "explicit"`).
|
|
6
|
+
*
|
|
7
|
+
* Réutilise le service `certificates` du module `@nodefony/http` (source unique)
|
|
8
|
+
* → la commande, le boot auto et un futur endpoint Studio appellent le même code.
|
|
9
|
+
*/
|
|
10
|
+
declare class Certificates extends Command {
|
|
11
|
+
constructor(cli: CliKernel);
|
|
12
|
+
generate(opts: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}): Promise<this>;
|
|
16
|
+
}
|
|
17
|
+
export default Certificates;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CliKernel, Command } from "nodefony";
|
|
2
|
+
/**
|
|
3
|
+
* Commande CLI `proxy:generate <nginx|haproxy>` — génère une configuration
|
|
4
|
+
* reverse-proxy DÉRIVÉE de l'introspection Nodefony (domaines de confiance,
|
|
5
|
+
* dossiers statiques servis, ports). Évite d'écrire la conf à la main et de la
|
|
6
|
+
* laisser diverger ; résout le « trou statiques multi-modules » côté nginx.
|
|
7
|
+
*/
|
|
8
|
+
declare class ProxyGenerate extends Command {
|
|
9
|
+
constructor(cli: CliKernel);
|
|
10
|
+
generate(target: string, opts: {
|
|
11
|
+
out?: string;
|
|
12
|
+
backend?: string;
|
|
13
|
+
listen?: string;
|
|
14
|
+
reencrypt?: boolean;
|
|
15
|
+
}): Promise<this>;
|
|
16
|
+
/** Construit le modèle d'introspection depuis le kernel + le service statique. */
|
|
17
|
+
private buildIntrospection;
|
|
18
|
+
}
|
|
19
|
+
export default ProxyGenerate;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const httpConfigSchema: z.ZodObject<{
|
|
3
|
+
headerServer: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
4
|
+
trustProxy: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
5
|
+
trustedHosts: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
6
|
+
securityHeaders: z.ZodDefault<z.ZodObject<{
|
|
7
|
+
contentTypeOptions: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
8
|
+
frameOptions: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
9
|
+
strictTransportSecurity: z.ZodDefault<z.ZodNullable<z.ZodObject<{
|
|
10
|
+
maxAge: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
includeSubDomains: z.ZodDefault<z.ZodBoolean>;
|
|
12
|
+
preload: z.ZodDefault<z.ZodBoolean>;
|
|
13
|
+
}, z.core.$strict>>>;
|
|
14
|
+
}, z.core.$strict>>;
|
|
15
|
+
maxBodySize: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
upload: z.ZodDefault<z.ZodObject<{
|
|
17
|
+
uploadDir: z.ZodDefault<z.ZodString>;
|
|
18
|
+
maxFileSize: z.ZodDefault<z.ZodNumber>;
|
|
19
|
+
maxTotalFileSize: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
maxFiles: z.ZodDefault<z.ZodNumber>;
|
|
21
|
+
maxFields: z.ZodDefault<z.ZodNumber>;
|
|
22
|
+
maxFieldsSize: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
hashAlgorithm: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodEnum<{
|
|
24
|
+
md5: "md5";
|
|
25
|
+
sha1: "sha1";
|
|
26
|
+
sha256: "sha256";
|
|
27
|
+
}>]>>;
|
|
28
|
+
encoding: z.ZodDefault<z.ZodString>;
|
|
29
|
+
}, z.core.$strict>>;
|
|
30
|
+
queryString: z.ZodDefault<z.ZodObject<{
|
|
31
|
+
parameterLimit: z.ZodDefault<z.ZodNumber>;
|
|
32
|
+
delimiter: z.ZodDefault<z.ZodString>;
|
|
33
|
+
ignoreQueryPrefix: z.ZodDefault<z.ZodBoolean>;
|
|
34
|
+
}, z.core.$loose>>;
|
|
35
|
+
http: z.ZodDefault<z.ZodObject<{
|
|
36
|
+
maxHeadersCount: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
keepAliveTimeout: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
requestTimeout: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
responseTimeout: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
shutdownTimeout: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
headers: z.ZodDefault<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
43
|
+
}, z.core.$loose>>;
|
|
44
|
+
https: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
maxHeadersCount: z.ZodDefault<z.ZodNumber>;
|
|
46
|
+
keepAliveTimeout: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
48
|
+
requestTimeout: z.ZodDefault<z.ZodNumber>;
|
|
49
|
+
responseTimeout: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
shutdownTimeout: z.ZodDefault<z.ZodNumber>;
|
|
51
|
+
headers: z.ZodDefault<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
52
|
+
rejectUnauthorized: z.ZodDefault<z.ZodBoolean>;
|
|
53
|
+
}, z.core.$loose>>;
|
|
54
|
+
http2: z.ZodDefault<z.ZodObject<{
|
|
55
|
+
maxConcurrentStreams: z.ZodDefault<z.ZodNumber>;
|
|
56
|
+
maxSessionMemory: z.ZodDefault<z.ZodNumber>;
|
|
57
|
+
}, z.core.$loose>>;
|
|
58
|
+
http3: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
|
|
59
|
+
certificates: z.ZodDefault<z.ZodObject<{
|
|
60
|
+
strategy: z.ZodDefault<z.ZodEnum<{
|
|
61
|
+
auto: "auto";
|
|
62
|
+
explicit: "explicit";
|
|
63
|
+
mkcert: "mkcert";
|
|
64
|
+
selfsigned: "selfsigned";
|
|
65
|
+
}>>;
|
|
66
|
+
ca: z.ZodDefault<z.ZodString>;
|
|
67
|
+
key: z.ZodDefault<z.ZodString>;
|
|
68
|
+
cert: z.ZodDefault<z.ZodString>;
|
|
69
|
+
privateKeyMode: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
san: z.ZodDefault<z.ZodObject<{
|
|
71
|
+
dns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
72
|
+
ip: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
73
|
+
}, z.core.$strict>>;
|
|
74
|
+
dev: z.ZodDefault<z.ZodObject<{
|
|
75
|
+
useMkcert: z.ZodDefault<z.ZodBoolean>;
|
|
76
|
+
}, z.core.$strict>>;
|
|
77
|
+
openssl: z.ZodDefault<z.ZodObject<{
|
|
78
|
+
size: z.ZodDefault<z.ZodNumber>;
|
|
79
|
+
hash: z.ZodDefault<z.ZodEnum<{
|
|
80
|
+
sha256: "sha256";
|
|
81
|
+
sha384: "sha384";
|
|
82
|
+
sha512: "sha512";
|
|
83
|
+
}>>;
|
|
84
|
+
validityDays: z.ZodDefault<z.ZodNumber>;
|
|
85
|
+
backdateMinutes: z.ZodDefault<z.ZodNumber>;
|
|
86
|
+
attrs: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
87
|
+
name: z.ZodOptional<z.ZodString>;
|
|
88
|
+
value: z.ZodOptional<z.ZodString>;
|
|
89
|
+
shortName: z.ZodOptional<z.ZodString>;
|
|
90
|
+
}, z.core.$loose>>>;
|
|
91
|
+
}, z.core.$strict>>;
|
|
92
|
+
}, z.core.$strict>>;
|
|
93
|
+
websocket: z.ZodDefault<z.ZodObject<{
|
|
94
|
+
keepaliveInterval: z.ZodDefault<z.ZodNumber>;
|
|
95
|
+
keepaliveGracePeriod: z.ZodDefault<z.ZodNumber>;
|
|
96
|
+
closeTimeout: z.ZodDefault<z.ZodNumber>;
|
|
97
|
+
maxPayload: z.ZodDefault<z.ZodNumber>;
|
|
98
|
+
allowedOrigins: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
99
|
+
perMessageDeflate: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
100
|
+
serverNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
|
|
101
|
+
clientNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
serverMaxWindowBits: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
clientMaxWindowBits: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
threshold: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
concurrencyLimit: z.ZodOptional<z.ZodNumber>;
|
|
106
|
+
}, z.core.$loose>]>>;
|
|
107
|
+
skipUTF8Validation: z.ZodDefault<z.ZodBoolean>;
|
|
108
|
+
autoPong: z.ZodDefault<z.ZodBoolean>;
|
|
109
|
+
allowSynchronousEvents: z.ZodDefault<z.ZodBoolean>;
|
|
110
|
+
maxBackpressure: z.ZodDefault<z.ZodNumber>;
|
|
111
|
+
backpressureCloseAfterDrops: z.ZodDefault<z.ZodNumber>;
|
|
112
|
+
backpressurePolicy: z.ZodDefault<z.ZodEnum<{
|
|
113
|
+
close: "close";
|
|
114
|
+
drop: "drop";
|
|
115
|
+
}>>;
|
|
116
|
+
}, z.core.$loose>>;
|
|
117
|
+
websocketSecure: z.ZodDefault<z.ZodObject<{
|
|
118
|
+
keepaliveInterval: z.ZodDefault<z.ZodNumber>;
|
|
119
|
+
keepaliveGracePeriod: z.ZodDefault<z.ZodNumber>;
|
|
120
|
+
closeTimeout: z.ZodDefault<z.ZodNumber>;
|
|
121
|
+
maxPayload: z.ZodDefault<z.ZodNumber>;
|
|
122
|
+
allowedOrigins: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
123
|
+
perMessageDeflate: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
124
|
+
serverNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
|
|
125
|
+
clientNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
|
|
126
|
+
serverMaxWindowBits: z.ZodOptional<z.ZodNumber>;
|
|
127
|
+
clientMaxWindowBits: z.ZodOptional<z.ZodNumber>;
|
|
128
|
+
threshold: z.ZodOptional<z.ZodNumber>;
|
|
129
|
+
concurrencyLimit: z.ZodOptional<z.ZodNumber>;
|
|
130
|
+
}, z.core.$loose>]>>;
|
|
131
|
+
skipUTF8Validation: z.ZodDefault<z.ZodBoolean>;
|
|
132
|
+
autoPong: z.ZodDefault<z.ZodBoolean>;
|
|
133
|
+
allowSynchronousEvents: z.ZodDefault<z.ZodBoolean>;
|
|
134
|
+
maxBackpressure: z.ZodDefault<z.ZodNumber>;
|
|
135
|
+
backpressureCloseAfterDrops: z.ZodDefault<z.ZodNumber>;
|
|
136
|
+
backpressurePolicy: z.ZodDefault<z.ZodEnum<{
|
|
137
|
+
close: "close";
|
|
138
|
+
drop: "drop";
|
|
139
|
+
}>>;
|
|
140
|
+
}, z.core.$loose>>;
|
|
141
|
+
statics: z.ZodDefault<z.ZodObject<{
|
|
142
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
143
|
+
defaultOptions: z.ZodDefault<z.ZodObject<{
|
|
144
|
+
cacheControl: z.ZodOptional<z.ZodBoolean>;
|
|
145
|
+
maxAge: z.ZodOptional<z.ZodNumber>;
|
|
146
|
+
}, z.core.$loose>>;
|
|
147
|
+
web: z.ZodDefault<z.ZodObject<{
|
|
148
|
+
path: z.ZodString;
|
|
149
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
150
|
+
cacheControl: z.ZodOptional<z.ZodBoolean>;
|
|
151
|
+
maxAge: z.ZodOptional<z.ZodNumber>;
|
|
152
|
+
}, z.core.$loose>>;
|
|
153
|
+
}, z.core.$loose>>;
|
|
154
|
+
}, z.core.$loose>>;
|
|
155
|
+
session: z.ZodDefault<z.ZodObject<{
|
|
156
|
+
strictMode: z.ZodDefault<z.ZodBoolean>;
|
|
157
|
+
name: z.ZodDefault<z.ZodString>;
|
|
158
|
+
store: z.ZodDefault<z.ZodString>;
|
|
159
|
+
gcIntervalS: z.ZodDefault<z.ZodNumber>;
|
|
160
|
+
gcJitter: z.ZodDefault<z.ZodBoolean>;
|
|
161
|
+
idleTimeoutS: z.ZodDefault<z.ZodNumber>;
|
|
162
|
+
absoluteTimeoutS: z.ZodDefault<z.ZodNumber>;
|
|
163
|
+
refererCheck: z.ZodDefault<z.ZodBoolean>;
|
|
164
|
+
cookie: z.ZodDefault<z.ZodObject<{
|
|
165
|
+
maxAge: z.ZodDefault<z.ZodNumber>;
|
|
166
|
+
httpOnly: z.ZodDefault<z.ZodBoolean>;
|
|
167
|
+
secure: z.ZodDefault<z.ZodBoolean>;
|
|
168
|
+
signed: z.ZodDefault<z.ZodBoolean>;
|
|
169
|
+
hostPrefix: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
170
|
+
}, z.core.$strict>>;
|
|
171
|
+
}, z.core.$strict>>;
|
|
172
|
+
rateLimit: z.ZodDefault<z.ZodObject<{
|
|
173
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
174
|
+
windowS: z.ZodDefault<z.ZodNumber>;
|
|
175
|
+
max: z.ZodDefault<z.ZodNumber>;
|
|
176
|
+
maxTracked: z.ZodDefault<z.ZodNumber>;
|
|
177
|
+
gcIntervalS: z.ZodDefault<z.ZodNumber>;
|
|
178
|
+
gcJitter: z.ZodDefault<z.ZodBoolean>;
|
|
179
|
+
}, z.core.$strict>>;
|
|
180
|
+
health: z.ZodDefault<z.ZodObject<{
|
|
181
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
182
|
+
livenessPath: z.ZodDefault<z.ZodString>;
|
|
183
|
+
readinessPath: z.ZodDefault<z.ZodString>;
|
|
184
|
+
shutdownDelay: z.ZodDefault<z.ZodNumber>;
|
|
185
|
+
}, z.core.$loose>>;
|
|
186
|
+
wsMaxConnectionsPerIp: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
187
|
+
}, z.core.$strict>;
|
|
188
|
+
/** Type de sortie (config normalisée + défauts appliqués). */
|
|
189
|
+
export type HttpConfig = z.infer<typeof httpConfigSchema>;
|
|
190
|
+
/** Type d'entrée (toutes sections omissibles — défauts du schéma). */
|
|
191
|
+
export type HttpConfigInput = z.input<typeof httpConfigSchema>;
|
|
192
|
+
/**
|
|
193
|
+
* Défauts du module, matérialisés depuis le schéma (source unique). Toujours
|
|
194
|
+
* valides par construction ; passés au `super(..., config)` du Module class.
|
|
195
|
+
*/
|
|
196
|
+
declare const config: HttpConfig;
|
|
197
|
+
export default config;
|