@grest-ts/http 0.0.47 → 0.0.49
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/README.md +321 -128
- package/dist/src/_dedupCheck.js +1 -1
- package/dist/src/client/GGContextKeySynchronizer.d.ts +11 -0
- package/dist/src/client/GGContextKeySynchronizer.d.ts.map +1 -0
- package/dist/src/client/GGContextKeySynchronizer.js +26 -0
- package/dist/src/client/GGContextKeySynchronizer.js.map +1 -0
- package/dist/src/client/GGHttpSchema.createClient.d.ts +8 -0
- package/dist/src/client/GGHttpSchema.createClient.d.ts.map +1 -1
- package/dist/src/client/GGHttpSchema.createClient.js +2 -1
- package/dist/src/client/GGHttpSchema.createClient.js.map +1 -1
- package/dist/src/index-browser.d.ts +4 -0
- package/dist/src/index-browser.d.ts.map +1 -1
- package/dist/src/index-browser.js +4 -0
- package/dist/src/index-browser.js.map +1 -1
- package/dist/src/index-node.d.ts +9 -1
- package/dist/src/index-node.d.ts.map +1 -1
- package/dist/src/index-node.js +17 -5
- package/dist/src/index-node.js.map +1 -1
- package/dist/src/rpc/GGHttpRouteRPC.d.ts +4 -0
- package/dist/src/rpc/GGHttpRouteRPC.d.ts.map +1 -1
- package/dist/src/rpc/GGHttpRouteRPC.js +6 -0
- package/dist/src/rpc/GGHttpRouteRPC.js.map +1 -1
- package/dist/src/rpc/RpcRequest/GGRpcRequestBuilder.d.ts +4 -3
- package/dist/src/rpc/RpcRequest/GGRpcRequestBuilder.d.ts.map +1 -1
- package/dist/src/rpc/RpcRequest/GGRpcRequestBuilder.js +9 -2
- package/dist/src/rpc/RpcRequest/GGRpcRequestBuilder.js.map +1 -1
- package/dist/src/rpc/RpcRequest/GGRpcRequestParser.d.ts +3 -3
- package/dist/src/rpc/RpcRequest/GGRpcRequestParser.d.ts.map +1 -1
- package/dist/src/rpc/RpcRequest/GGRpcRequestParser.js +13 -16
- package/dist/src/rpc/RpcRequest/GGRpcRequestParser.js.map +1 -1
- package/dist/src/rpc/RpcResponse/GGRpcResponseBuilder.d.ts +1 -0
- package/dist/src/rpc/RpcResponse/GGRpcResponseBuilder.d.ts.map +1 -1
- package/dist/src/rpc/RpcResponse/GGRpcResponseBuilder.js +4 -0
- package/dist/src/rpc/RpcResponse/GGRpcResponseBuilder.js.map +1 -1
- package/dist/src/schema/GGCookie.d.ts +50 -0
- package/dist/src/schema/GGCookie.d.ts.map +1 -0
- package/dist/src/schema/GGCookie.js +130 -0
- package/dist/src/schema/GGCookie.js.map +1 -0
- package/dist/src/schema/GGHeader.d.ts +23 -0
- package/dist/src/schema/GGHeader.d.ts.map +1 -0
- package/dist/src/schema/GGHeader.js +41 -0
- package/dist/src/schema/GGHeader.js.map +1 -0
- package/dist/src/schema/GGHttpPermissionsChecker.d.ts +9 -0
- package/dist/src/schema/GGHttpPermissionsChecker.d.ts.map +1 -0
- package/dist/src/schema/GGHttpPermissionsChecker.js +29 -0
- package/dist/src/schema/GGHttpPermissionsChecker.js.map +1 -0
- package/dist/src/schema/GGHttpSchema.d.ts +14 -52
- package/dist/src/schema/GGHttpSchema.d.ts.map +1 -1
- package/dist/src/schema/GGHttpSchema.js.map +1 -1
- package/dist/src/schema/GGWireContextKey.d.ts +30 -0
- package/dist/src/schema/GGWireContextKey.d.ts.map +1 -0
- package/dist/src/schema/GGWireContextKey.js +36 -0
- package/dist/src/schema/GGWireContextKey.js.map +1 -0
- package/dist/src/schema/GGWireContextKey.node.d.ts +36 -0
- package/dist/src/schema/GGWireContextKey.node.d.ts.map +1 -0
- package/dist/src/schema/GGWireContextKey.node.js +83 -0
- package/dist/src/schema/GGWireContextKey.node.js.map +1 -0
- package/dist/src/schema/httpSchema.d.ts +2 -4
- package/dist/src/schema/httpSchema.d.ts.map +1 -1
- package/dist/src/schema/httpSchema.js +0 -48
- package/dist/src/schema/httpSchema.js.map +1 -1
- package/dist/src/server/GGHttp.d.ts +2 -26
- package/dist/src/server/GGHttp.d.ts.map +1 -1
- package/dist/src/server/GGHttp.js +0 -15
- package/dist/src/server/GGHttp.js.map +1 -1
- package/dist/src/server/GGHttpSchema.startServer.d.ts +2 -11
- package/dist/src/server/GGHttpSchema.startServer.d.ts.map +1 -1
- package/dist/src/server/GGHttpSchema.startServer.js +14 -28
- package/dist/src/server/GGHttpSchema.startServer.js.map +1 -1
- package/dist/src/server/GGHttpServer.d.ts +45 -14
- package/dist/src/server/GGHttpServer.d.ts.map +1 -1
- package/dist/src/server/GGHttpServer.js +61 -87
- package/dist/src/server/GGHttpServer.js.map +1 -1
- package/dist/src/server/applyRequestMiddleware.d.ts +11 -0
- package/dist/src/server/applyRequestMiddleware.d.ts.map +1 -0
- package/dist/src/server/applyRequestMiddleware.js +38 -0
- package/dist/src/server/applyRequestMiddleware.js.map +1 -0
- package/dist/src/server/applyResponseMiddleware.d.ts +12 -0
- package/dist/src/server/applyResponseMiddleware.d.ts.map +1 -0
- package/dist/src/server/applyResponseMiddleware.js +25 -0
- package/dist/src/server/applyResponseMiddleware.js.map +1 -0
- package/dist/src/server/checkers/checkPermissionsAtStart.d.ts +39 -0
- package/dist/src/server/checkers/checkPermissionsAtStart.d.ts.map +1 -0
- package/dist/src/server/checkers/checkPermissionsAtStart.js +82 -0
- package/dist/src/server/checkers/checkPermissionsAtStart.js.map +1 -0
- package/dist/src/server/checkers/checkWireConflicts.d.ts +18 -0
- package/dist/src/server/checkers/checkWireConflicts.d.ts.map +1 -0
- package/dist/src/server/checkers/checkWireConflicts.js +43 -0
- package/dist/src/server/checkers/checkWireConflicts.js.map +1 -0
- package/dist/src/server/checkers/checkWiresImplemented.d.ts +11 -0
- package/dist/src/server/checkers/checkWiresImplemented.d.ts.map +1 -0
- package/dist/src/server/checkers/checkWiresImplemented.js +27 -0
- package/dist/src/server/checkers/checkWiresImplemented.js.map +1 -0
- package/dist/src/tsconfig.json +2 -1
- package/dist/tsconfig.publish.tsbuildinfo +1 -1
- package/package.json +14 -11
- package/src/_dedupCheck.ts +1 -1
- package/src/client/GGContextKeySynchronizer.test.ts +106 -0
- package/src/client/GGContextKeySynchronizer.ts +42 -0
- package/src/client/GGHttpSchema.createClient.ts +10 -1
- package/src/index-browser.ts +4 -0
- package/src/index-node.ts +18 -5
- package/src/rpc/GGHttpRouteRPC.ts +8 -0
- package/src/rpc/RpcRequest/GGRpcRequestBuilder.ts +11 -4
- package/src/rpc/RpcRequest/GGRpcRequestParser.ts +16 -17
- package/src/rpc/RpcResponse/GGRpcResponseBuilder.ts +5 -0
- package/src/schema/GGCookie.ts +151 -0
- package/src/schema/GGHeader.ts +48 -0
- package/src/schema/GGHttpPermissionsChecker.test.ts +125 -0
- package/src/schema/GGHttpPermissionsChecker.ts +35 -0
- package/src/schema/GGHttpSchema.ts +15 -63
- package/src/schema/GGWireContextKey.node.ts +119 -0
- package/src/schema/GGWireContextKey.ts +46 -0
- package/src/schema/httpSchema.ts +4 -57
- package/src/server/GGHttp.ts +3 -34
- package/src/server/GGHttpSchema.startServer.ts +16 -38
- package/src/server/GGHttpServer.ts +90 -97
- package/src/server/applyRequestMiddleware.ts +40 -0
- package/src/server/applyResponseMiddleware.ts +27 -0
- package/src/server/checkers/checkPermissionsAtStart.ts +112 -0
- package/src/server/checkers/checkWireConflicts.ts +65 -0
- package/src/server/checkers/checkWiresImplemented.ts +42 -0
- package/src/tsconfig.json +2 -1
- package/dist/src/server/GG_PERMISSIONS.d.ts +0 -15
- package/dist/src/server/GG_PERMISSIONS.d.ts.map +0 -1
- package/dist/src/server/GG_PERMISSIONS.js +0 -15
- package/dist/src/server/GG_PERMISSIONS.js.map +0 -1
- package/src/server/GG_PERMISSIONS.ts +0 -15
|
@@ -5,13 +5,17 @@ import { GGLocator, GGLocatorServiceType } from "@grest-ts/locator";
|
|
|
5
5
|
import { GG_HTTP_SERVER } from "./GG_HTTP_SERVER.js";
|
|
6
6
|
import { GGLog } from "@grest-ts/logger";
|
|
7
7
|
import findMyWay from "find-my-way";
|
|
8
|
-
import {
|
|
8
|
+
import { checkWiresImplemented } from "./checkers/checkWiresImplemented.js";
|
|
9
|
+
import { checkPermissionsAtStart } from "./checkers/checkPermissionsAtStart.js";
|
|
10
|
+
import { checkWireConflicts } from "./checkers/checkWireConflicts.js";
|
|
11
|
+
import "../schema/GGWireContextKey.node.js";
|
|
9
12
|
export class GGHttpServer {
|
|
10
13
|
_port;
|
|
11
14
|
teardownPromise;
|
|
12
15
|
scope;
|
|
13
16
|
runtimeName;
|
|
14
17
|
configuredPort;
|
|
18
|
+
cors;
|
|
15
19
|
_onStart = [];
|
|
16
20
|
_onTeardown = [];
|
|
17
21
|
/**
|
|
@@ -19,14 +23,9 @@ export class GGHttpServer {
|
|
|
19
23
|
* Framework-internal — only setupRoutes() (in GGHttpSchema.startServer.ts) should push here.
|
|
20
24
|
*/
|
|
21
25
|
_registeredSchemas = [];
|
|
22
|
-
|
|
23
|
-
* All GGHttpSchema instances registered on this server, in registration order.
|
|
24
|
-
* Available from the moment compose() begins; frozen (no further push allowed) once start() is called.
|
|
25
|
-
*/
|
|
26
|
-
get registeredSchemas() {
|
|
27
|
-
return this._registeredSchemas;
|
|
28
|
-
}
|
|
26
|
+
_registeredWebSocketSchemas = [];
|
|
29
27
|
httpServer;
|
|
28
|
+
_routeOwners = new Map();
|
|
30
29
|
activeRequests = 0;
|
|
31
30
|
router = findMyWay();
|
|
32
31
|
static DEFAULT_CORS_HEADERS = ['Content-Type'];
|
|
@@ -38,6 +37,7 @@ export class GGHttpServer {
|
|
|
38
37
|
this.runtimeName = GGLocator.getScope().serviceName;
|
|
39
38
|
this.scope = GGLocator.getScope();
|
|
40
39
|
this.configuredPort = config?.port ?? (process.env.PORT ? Number(process.env.PORT) : 0);
|
|
40
|
+
this.cors = config?.cors;
|
|
41
41
|
GGLocator.getScope().setWithLifecycle(config?.key ?? GG_HTTP_SERVER, this, {
|
|
42
42
|
type: GGLocatorServiceType.HTTP,
|
|
43
43
|
start: this.start.bind(this),
|
|
@@ -51,14 +51,9 @@ export class GGHttpServer {
|
|
|
51
51
|
}
|
|
52
52
|
this.activeRequests++;
|
|
53
53
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
res.setHeader(
|
|
57
|
-
res.setHeader('Access-Control-Allow-Headers', this._corsHeadersCache);
|
|
58
|
-
if (this._corsExposeHeadersCache) {
|
|
59
|
-
res.setHeader('Access-Control-Expose-Headers', this._corsExposeHeadersCache);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
54
|
+
const cors = corsResponseHeaders(req.headers.origin, this.cors, this._corsHeadersCache, this._corsExposeHeadersCache);
|
|
55
|
+
for (const name in cors)
|
|
56
|
+
res.setHeader(name, cors[name]);
|
|
62
57
|
if (req.method === 'OPTIONS') {
|
|
63
58
|
res.writeHead(204);
|
|
64
59
|
res.end();
|
|
@@ -133,90 +128,39 @@ export class GGHttpServer {
|
|
|
133
128
|
_registerSchema(schema) {
|
|
134
129
|
this._registeredSchemas.push(schema);
|
|
135
130
|
}
|
|
136
|
-
_registeredWebSocketSchemas = [];
|
|
137
131
|
/**
|
|
138
|
-
* All
|
|
139
|
-
*
|
|
132
|
+
* All GGHttpSchema instances registered on this server, in registration order.
|
|
133
|
+
* Available from the moment compose() begins; frozen (no further push allowed) once start() is called.
|
|
140
134
|
*/
|
|
141
|
-
get
|
|
142
|
-
return this.
|
|
135
|
+
get registeredSchemas() {
|
|
136
|
+
return this._registeredSchemas;
|
|
143
137
|
}
|
|
144
138
|
/** @internal Called by GGWebSocketSchema.startServer(). Do not call directly. */
|
|
145
139
|
_registerWebSocketSchema(schema) {
|
|
146
140
|
this._registeredWebSocketSchemas.push(schema);
|
|
147
141
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
142
|
+
/**
|
|
143
|
+
* All GGWebSocketSchema instances registered on this server, in registration order.
|
|
144
|
+
* Populated automatically by GGWebSocketSchema.startServer() / .register().
|
|
145
|
+
*/
|
|
146
|
+
get registeredWebSocketSchemas() {
|
|
147
|
+
return this._registeredWebSocketSchemas;
|
|
152
148
|
}
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
surfaces.push({
|
|
160
|
-
label: `${schema.name}.${name}`,
|
|
161
|
-
permission: methods[name].permission,
|
|
162
|
-
resolverWired,
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
for (const ws of this._registeredWebSocketSchemas) {
|
|
167
|
-
const resolverWired = this._schemasWithResolver.has(ws);
|
|
168
|
-
const methods = ws.contract.clientToServer.methods;
|
|
169
|
-
for (const name of Object.keys(methods)) {
|
|
170
|
-
surfaces.push({
|
|
171
|
-
label: `${ws.name}.${name}`,
|
|
172
|
-
permission: methods[name].permission,
|
|
173
|
-
resolverWired,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
if (ws.connectPermission !== undefined) {
|
|
177
|
-
surfaces.push({
|
|
178
|
-
label: `${ws.name} (connectPermission)`,
|
|
179
|
-
permission: ws.connectPermission,
|
|
180
|
-
resolverWired,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
let strict = false;
|
|
185
|
-
const undeclared = [];
|
|
186
|
-
const orphaned = [];
|
|
187
|
-
for (const s of surfaces) {
|
|
188
|
-
if (s.permission !== undefined || s.resolverWired)
|
|
189
|
-
strict = true;
|
|
190
|
-
if (s.permission === undefined)
|
|
191
|
-
undeclared.push(s);
|
|
192
|
-
else if (s.permission !== GG_NO_PERMISSIONS && !s.resolverWired)
|
|
193
|
-
orphaned.push(s);
|
|
194
|
-
}
|
|
195
|
-
if (!strict)
|
|
196
|
-
return;
|
|
197
|
-
if (undeclared.length > 0) {
|
|
198
|
-
const lines = undeclared.map(s => ` ${s.label}`).join("\n");
|
|
199
|
-
throw new Error(`GGHttpServer: permission strict mode is active on this server ` +
|
|
200
|
-
`(at least one route declares a permission or has .usePermissions(...) wired), ` +
|
|
201
|
-
`but the following routes have no \`permission\` declared:\n\n` +
|
|
202
|
-
lines +
|
|
203
|
-
`\n\nFix: declare \`permission\` on every route — use \`GG_NO_PERMISSIONS\` for intentionally public ones.`);
|
|
204
|
-
}
|
|
205
|
-
if (orphaned.length > 0) {
|
|
206
|
-
const lines = orphaned.map(s => ` ${s.label} requires ${describePermission(s.permission)}`).join("\n");
|
|
207
|
-
throw new Error(`GGHttpServer: these routes declare non-public permissions but their schema was ` +
|
|
208
|
-
`registered without a scope resolver:\n\n` +
|
|
209
|
-
lines +
|
|
210
|
-
`\n\nFix: call \`.usePermissions(yourResolver)\` on the GGHttp chain (or pass ` +
|
|
211
|
-
`\`permissionResolver\` to the WS schema config) before registering these routes.`);
|
|
149
|
+
registerRoute(method, path, handler, owner) {
|
|
150
|
+
const route = `${method} ${path}`;
|
|
151
|
+
const existing = this._routeOwners.get(route);
|
|
152
|
+
if (existing !== undefined) {
|
|
153
|
+
throw new Error(`GGHttpServer: route ${route} is declared by both ${existing} and ${owner ?? "another route"}. ` +
|
|
154
|
+
`Give each route a distinct path (change a pathPrefix or route path).`);
|
|
212
155
|
}
|
|
213
|
-
|
|
214
|
-
registerRoute(method, path, handler) {
|
|
156
|
+
this._routeOwners.set(route, owner ?? path);
|
|
215
157
|
this.router.on(method, path, handler);
|
|
216
158
|
}
|
|
217
159
|
async start() {
|
|
218
160
|
Object.freeze(this._registeredSchemas);
|
|
219
|
-
this.
|
|
161
|
+
checkWireConflicts(this.registeredSchemas, this.registeredWebSocketSchemas);
|
|
162
|
+
checkWiresImplemented(this.registeredSchemas, this.registeredWebSocketSchemas);
|
|
163
|
+
checkPermissionsAtStart(this.registeredSchemas, this.registeredWebSocketSchemas);
|
|
220
164
|
this._port = await new Promise((resolve) => {
|
|
221
165
|
this.httpServer.listen(this.configuredPort, '0.0.0.0', () => {
|
|
222
166
|
const port = this.httpServer.address().port;
|
|
@@ -253,4 +197,34 @@ export class GGHttpServer {
|
|
|
253
197
|
return this;
|
|
254
198
|
}
|
|
255
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Computes CORS response headers for a request Origin. Pure (no req/res) so it is
|
|
202
|
+
* unit-testable. Default (no config) = permissive `*`, no credentials. With config =
|
|
203
|
+
* allowlisted: only a matching Origin is echoed (never `*`), `credentials` adds
|
|
204
|
+
* Allow-Credentials, and Vary: Origin is always set so caches key on the origin.
|
|
205
|
+
*/
|
|
206
|
+
export function corsResponseHeaders(origin, cors, allowHeaders, exposeHeaders) {
|
|
207
|
+
if (!origin)
|
|
208
|
+
return {};
|
|
209
|
+
const headers = {};
|
|
210
|
+
if (cors) {
|
|
211
|
+
// Never reflect the literal "null" origin (sandboxed iframe / file:// / opaque
|
|
212
|
+
// origins) with credentials — the classic null-origin credential-leak footgun.
|
|
213
|
+
const allowed = origin !== "null" && (Array.isArray(cors.origins) ? cors.origins.includes(origin) : cors.origins(origin));
|
|
214
|
+
headers['Vary'] = 'Origin';
|
|
215
|
+
if (!allowed)
|
|
216
|
+
return headers;
|
|
217
|
+
headers['Access-Control-Allow-Origin'] = origin;
|
|
218
|
+
if (cors.credentials)
|
|
219
|
+
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
headers['Access-Control-Allow-Origin'] = '*';
|
|
223
|
+
}
|
|
224
|
+
headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
|
|
225
|
+
headers['Access-Control-Allow-Headers'] = allowHeaders;
|
|
226
|
+
if (exposeHeaders)
|
|
227
|
+
headers['Access-Control-Expose-Headers'] = exposeHeaders;
|
|
228
|
+
return headers;
|
|
229
|
+
}
|
|
256
230
|
//# sourceMappingURL=GGHttpServer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GGHttpServer.js","sourceRoot":"","sources":["../../../src/server/GGHttpServer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAa,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAC,SAAS,EAAgC,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAC;AACvC,OAAO,SAAuB,MAAM,aAAa,CAAC;AAElD,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"GGHttpServer.js","sourceRoot":"","sources":["../../../src/server/GGHttpServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type http from "http";
|
|
2
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
3
|
+
/**
|
|
4
|
+
* Normalizes a Node request + parsed query into a GGInbound and runs the server-side
|
|
5
|
+
* pipeline: every parse() (populating context keys) before any process() (async
|
|
6
|
+
* validation), so a middleware can validate against a key an earlier one parsed.
|
|
7
|
+
* The cookie is taken only from the real request header — never from anywhere a
|
|
8
|
+
* client could forge — preserving the anti-spoof guarantee on every transport.
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyRequestMiddleware(req: http.IncomingMessage, queryArgs: Record<string, string | string[]>, middlewares: readonly GGTransportMiddleware[]): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=applyRequestMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyRequestMiddleware.d.ts","sourceRoot":"","sources":["../../../src/server/applyRequestMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAY,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAExE;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CACxC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC5C,WAAW,EAAE,SAAS,qBAAqB,EAAE,GAC9C,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a Node request + parsed query into a GGInbound and runs the server-side
|
|
3
|
+
* pipeline: every parse() (populating context keys) before any process() (async
|
|
4
|
+
* validation), so a middleware can validate against a key an earlier one parsed.
|
|
5
|
+
* The cookie is taken only from the real request header — never from anywhere a
|
|
6
|
+
* client could forge — preserving the anti-spoof guarantee on every transport.
|
|
7
|
+
*/
|
|
8
|
+
export async function applyRequestMiddleware(req, queryArgs, middlewares) {
|
|
9
|
+
if (middlewares.length === 0)
|
|
10
|
+
return;
|
|
11
|
+
const inbound = {
|
|
12
|
+
headers: flatten(req.headers),
|
|
13
|
+
cookie: typeof req.headers.cookie === "string" ? req.headers.cookie : undefined,
|
|
14
|
+
query: flatten(queryArgs)
|
|
15
|
+
};
|
|
16
|
+
for (const mw of middlewares)
|
|
17
|
+
mw.parse?.(inbound);
|
|
18
|
+
// finally: a rejecting process() (e.g. anonymous → NOT_AUTHORIZED) must still drop every
|
|
19
|
+
// ephemeral credential — including those an earlier wire already parsed — so no raw token
|
|
20
|
+
// outlives the failed request in context.
|
|
21
|
+
try {
|
|
22
|
+
for (const mw of middlewares)
|
|
23
|
+
await mw.process?.();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
for (const mw of middlewares)
|
|
27
|
+
mw.clear?.();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function flatten(src) {
|
|
31
|
+
const out = {};
|
|
32
|
+
for (const key in src) {
|
|
33
|
+
const value = src[key];
|
|
34
|
+
out[key] = Array.isArray(value) ? value[0] : value;
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=applyRequestMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyRequestMiddleware.js","sourceRoot":"","sources":["../../../src/server/applyRequestMiddleware.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CACxC,GAAyB,EACzB,SAA4C,EAC5C,WAA6C;IAE7C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACrC,MAAM,OAAO,GAAc;QACvB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAC7B,MAAM,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC/E,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC;KAC5B,CAAC;IACF,KAAK,MAAM,EAAE,IAAI,WAAW;QAAE,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC;IAClD,yFAAyF;IACzF,0FAA0F;IAC1F,0CAA0C;IAC1C,IAAI,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,WAAW;YAAE,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;IACvD,CAAC;YAAS,CAAC;QACP,KAAK,MAAM,EAAE,IAAI,WAAW;YAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;IAC/C,CAAC;AACL,CAAC;AAED,SAAS,OAAO,CAAC,GAAkD;IAC/D,MAAM,GAAG,GAAuC,EAAE,CAAC;IACnD,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type http from "http";
|
|
2
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
3
|
+
/**
|
|
4
|
+
* Runs the transport chain's server-side response hook and writes the collected
|
|
5
|
+
* headers onto the Node response. Applied via setHeader (not writeHead) so a
|
|
6
|
+
* string[] value emits one header line per element — the only way to send
|
|
7
|
+
* multiple Set-Cookie headers — and so the codec's later writeHead(Content-*)
|
|
8
|
+
* merges rather than clobbers. Must run inside the request GGContext so a
|
|
9
|
+
* middleware can read per-request staged state.
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyResponseMiddleware(res: http.ServerResponse, middlewares: readonly GGTransportMiddleware[] | undefined): void;
|
|
12
|
+
//# sourceMappingURL=applyResponseMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyResponseMiddleware.d.ts","sourceRoot":"","sources":["../../../src/server/applyResponseMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAa,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACnC,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,WAAW,EAAE,SAAS,qBAAqB,EAAE,GAAG,SAAS,GAC1D,IAAI,CAYN"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs the transport chain's server-side response hook and writes the collected
|
|
3
|
+
* headers onto the Node response. Applied via setHeader (not writeHead) so a
|
|
4
|
+
* string[] value emits one header line per element — the only way to send
|
|
5
|
+
* multiple Set-Cookie headers — and so the codec's later writeHead(Content-*)
|
|
6
|
+
* merges rather than clobbers. Must run inside the request GGContext so a
|
|
7
|
+
* middleware can read per-request staged state.
|
|
8
|
+
*/
|
|
9
|
+
export function applyResponseMiddleware(res, middlewares) {
|
|
10
|
+
if (!middlewares?.length || res.headersSent)
|
|
11
|
+
return;
|
|
12
|
+
let response;
|
|
13
|
+
for (const mw of middlewares) {
|
|
14
|
+
if (!mw.respond)
|
|
15
|
+
continue;
|
|
16
|
+
response ??= { headers: {} };
|
|
17
|
+
mw.respond(response);
|
|
18
|
+
}
|
|
19
|
+
if (!response)
|
|
20
|
+
return;
|
|
21
|
+
for (const name in response.headers) {
|
|
22
|
+
res.setHeader(name, response.headers[name]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=applyResponseMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyResponseMiddleware.js","sourceRoot":"","sources":["../../../src/server/applyResponseMiddleware.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACnC,GAAwB,EACxB,WAAyD;IAEzD,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,GAAG,CAAC,WAAW;QAAE,OAAO;IACpD,IAAI,QAAgC,CAAC;IACrC,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC,OAAO;YAAE,SAAS;QAC1B,QAAQ,KAAK,EAAC,OAAO,EAAE,EAAE,EAAC,CAAC;QAC3B,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QAClC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run at GGHttpServer.start() over the frozen schema graph. Three permission-coherence checks:
|
|
3
|
+
*
|
|
4
|
+
* - strict-mode coverage: once any route declares a permission, every route on the server must
|
|
5
|
+
* declare one (use GG_NO_PERMISSIONS for intentionally public routes).
|
|
6
|
+
* - unsatisfiable route: a route requiring a non-public permission on a schema with no
|
|
7
|
+
* permission-resolving wire (a .define()d wire whose handler exposes permissions()) can never
|
|
8
|
+
* pass the gate — its pooled grants are always empty, so it is permanently FORBIDDEN.
|
|
9
|
+
* - dead serverToClient permission: the gate has no caller identity for server-pushed messages,
|
|
10
|
+
* so a non-public permission on a WS serverToClient method is silently ignored.
|
|
11
|
+
*
|
|
12
|
+
* Scopes come only from the schema's wires; there is no resolver wiring.
|
|
13
|
+
*/
|
|
14
|
+
import { GGContractMethod, GGPermission } from "@grest-ts/schema";
|
|
15
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
16
|
+
import "../../schema/GGWireContextKey.node";
|
|
17
|
+
interface HttpSchemaLike {
|
|
18
|
+
name: string;
|
|
19
|
+
apiMiddlewares: readonly GGTransportMiddleware[];
|
|
20
|
+
contract?: {
|
|
21
|
+
methods: Record<string, GGContractMethod>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
interface WebSocketSchemaLike {
|
|
25
|
+
name: string;
|
|
26
|
+
middlewares: readonly GGTransportMiddleware[];
|
|
27
|
+
contract: {
|
|
28
|
+
clientToServer: {
|
|
29
|
+
methods: Record<string, GGContractMethod>;
|
|
30
|
+
};
|
|
31
|
+
serverToClient: {
|
|
32
|
+
methods: Record<string, GGContractMethod>;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
connectPermission?: GGPermission;
|
|
36
|
+
}
|
|
37
|
+
export declare function checkPermissionsAtStart(httpSchemas: readonly HttpSchemaLike[], webSocketSchemas: readonly WebSocketSchemaLike[]): void;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=checkPermissionsAtStart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkPermissionsAtStart.d.ts","sourceRoot":"","sources":["../../../../src/server/checkers/checkPermissionsAtStart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAoB,gBAAgB,EAAE,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAClF,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAA;AAE5D,OAAO,oCAAoC,CAAA;AAE3C,UAAU,cAAc;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,SAAS,qBAAqB,EAAE,CAAA;IAChD,QAAQ,CAAC,EAAE;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;KAAC,CAAA;CACzD;AAED,UAAU,mBAAmB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,SAAS,qBAAqB,EAAE,CAAA;IAC7C,QAAQ,EAAE;QACN,cAAc,EAAE;YAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;SAAC,CAAA;QAC3D,cAAc,EAAE;YAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;SAAC,CAAA;KAC9D,CAAA;IACD,iBAAiB,CAAC,EAAE,YAAY,CAAA;CACnC;AAUD,wBAAgB,uBAAuB,CACnC,WAAW,EAAE,SAAS,cAAc,EAAE,EACtC,gBAAgB,EAAE,SAAS,mBAAmB,EAAE,GACjD,IAAI,CAkEN"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run at GGHttpServer.start() over the frozen schema graph. Three permission-coherence checks:
|
|
3
|
+
*
|
|
4
|
+
* - strict-mode coverage: once any route declares a permission, every route on the server must
|
|
5
|
+
* declare one (use GG_NO_PERMISSIONS for intentionally public routes).
|
|
6
|
+
* - unsatisfiable route: a route requiring a non-public permission on a schema with no
|
|
7
|
+
* permission-resolving wire (a .define()d wire whose handler exposes permissions()) can never
|
|
8
|
+
* pass the gate — its pooled grants are always empty, so it is permanently FORBIDDEN.
|
|
9
|
+
* - dead serverToClient permission: the gate has no caller identity for server-pushed messages,
|
|
10
|
+
* so a non-public permission on a WS serverToClient method is silently ignored.
|
|
11
|
+
*
|
|
12
|
+
* Scopes come only from the schema's wires; there is no resolver wiring.
|
|
13
|
+
*/
|
|
14
|
+
import { GG_NO_PERMISSIONS } from "@grest-ts/schema";
|
|
15
|
+
import { GGWireContextKey } from "../../schema/GGWireContextKey.js";
|
|
16
|
+
import "../../schema/GGWireContextKey.node.js";
|
|
17
|
+
function isNonPublic(permission) {
|
|
18
|
+
return permission !== undefined && permission !== GG_NO_PERMISSIONS;
|
|
19
|
+
}
|
|
20
|
+
function hasPermissionWire(wires) {
|
|
21
|
+
return wires.some(mw => mw instanceof GGWireContextKey && mw.hasPermissions());
|
|
22
|
+
}
|
|
23
|
+
export function checkPermissionsAtStart(httpSchemas, webSocketSchemas) {
|
|
24
|
+
const surfaces = [];
|
|
25
|
+
const deadServerToClient = [];
|
|
26
|
+
for (const schema of httpSchemas) {
|
|
27
|
+
const hasWire = hasPermissionWire(schema.apiMiddlewares);
|
|
28
|
+
const methods = schema.contract?.methods ?? {};
|
|
29
|
+
for (const name of Object.keys(methods)) {
|
|
30
|
+
surfaces.push({ label: `${schema.name}.${name}`, permission: methods[name].permission, hasWire });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const ws of webSocketSchemas) {
|
|
34
|
+
const hasWire = hasPermissionWire(ws.middlewares);
|
|
35
|
+
const methods = ws.contract.clientToServer.methods;
|
|
36
|
+
for (const name of Object.keys(methods)) {
|
|
37
|
+
surfaces.push({ label: `${ws.name}.${name}`, permission: methods[name].permission, hasWire });
|
|
38
|
+
}
|
|
39
|
+
if (ws.connectPermission !== undefined) {
|
|
40
|
+
surfaces.push({ label: `${ws.name} (connectPermission)`, permission: ws.connectPermission, hasWire });
|
|
41
|
+
}
|
|
42
|
+
const pushed = ws.contract.serverToClient.methods;
|
|
43
|
+
for (const name of Object.keys(pushed)) {
|
|
44
|
+
if (isNonPublic(pushed[name].permission))
|
|
45
|
+
deadServerToClient.push(` ${ws.name}.${name}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (deadServerToClient.length > 0) {
|
|
49
|
+
throw new Error(`GGHttpServer: these WebSocket serverToClient methods declare a non-public permission, ` +
|
|
50
|
+
`but server-pushed messages have no caller to gate — the permission is silently ignored:\n\n` +
|
|
51
|
+
deadServerToClient.join("\n") +
|
|
52
|
+
`\n\nFix: set \`permission: GG_NO_PERMISSIONS\` on serverToClient methods.`);
|
|
53
|
+
}
|
|
54
|
+
const unsatisfiable = surfaces.filter(s => isNonPublic(s.permission) && !s.hasWire);
|
|
55
|
+
if (unsatisfiable.length > 0) {
|
|
56
|
+
const lines = unsatisfiable.map(s => ` ${s.label}`).join("\n");
|
|
57
|
+
throw new Error(`GGHttpServer: these routes require a permission but their schema .use()s no wire that ` +
|
|
58
|
+
`resolves permissions — they can never pass the gate (permanently FORBIDDEN):\n\n` +
|
|
59
|
+
lines +
|
|
60
|
+
`\n\nFix: .use() an auth wire whose handler exposes permissions(), or set the route to ` +
|
|
61
|
+
`\`GG_NO_PERMISSIONS\` if it is meant to be public.`);
|
|
62
|
+
}
|
|
63
|
+
let strict = false;
|
|
64
|
+
const undeclared = [];
|
|
65
|
+
for (const s of surfaces) {
|
|
66
|
+
if (s.permission !== undefined)
|
|
67
|
+
strict = true;
|
|
68
|
+
if (s.permission === undefined)
|
|
69
|
+
undeclared.push(s);
|
|
70
|
+
}
|
|
71
|
+
if (!strict)
|
|
72
|
+
return;
|
|
73
|
+
if (undeclared.length > 0) {
|
|
74
|
+
const lines = undeclared.map(s => ` ${s.label}`).join("\n");
|
|
75
|
+
throw new Error(`GGHttpServer: permission strict mode is active on this server ` +
|
|
76
|
+
`(at least one route declares a permission), ` +
|
|
77
|
+
`but the following routes have no \`permission\` declared:\n\n` +
|
|
78
|
+
lines +
|
|
79
|
+
`\n\nFix: declare \`permission\` on every route — use \`GG_NO_PERMISSIONS\` for intentionally public ones.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=checkPermissionsAtStart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkPermissionsAtStart.js","sourceRoot":"","sources":["../../../../src/server/checkers/checkPermissionsAtStart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAC,iBAAiB,EAAiC,MAAM,kBAAkB,CAAA;AAElF,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAA;AAC9D,OAAO,oCAAoC,CAAA;AAkB3C,SAAS,WAAW,CAAC,UAAoC;IACrD,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,iBAAiB,CAAA;AACvE,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAuC;IAC9D,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,gBAAgB,IAAI,EAAE,CAAC,cAAc,EAAE,CAAC,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,uBAAuB,CACnC,WAAsC,EACtC,gBAAgD;IAGhD,MAAM,QAAQ,GAAc,EAAE,CAAA;IAC9B,MAAM,kBAAkB,GAAa,EAAE,CAAA;IAEvC,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;QACxD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAA;QAC9C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAC,CAAC,CAAA;QACnG,CAAC;IACL,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,gBAAgB,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,iBAAiB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;QACjD,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAA;QAClD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAC,CAAC,CAAA;QAC/F,CAAC;QACD,IAAI,EAAE,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,sBAAsB,EAAE,UAAU,EAAE,EAAE,CAAC,iBAAiB,EAAE,OAAO,EAAC,CAAC,CAAA;QACvG,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAA;QACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC;gBAAE,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAA;QAC7F,CAAC;IACL,CAAC;IAED,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACX,wFAAwF;YACxF,6FAA6F;YAC7F,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,2EAA2E,CAC9E,CAAA;IACL,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACnF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/D,MAAM,IAAI,KAAK,CACX,wFAAwF;YACxF,kFAAkF;YAClF,KAAK;YACL,wFAAwF;YACxF,oDAAoD,CACvD,CAAA;IACL,CAAC;IAED,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,MAAM,UAAU,GAAc,EAAE,CAAA;IAChC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;YAAE,MAAM,GAAG,IAAI,CAAA;QAC7C,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtD,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,OAAM;IAEnB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5D,MAAM,IAAI,KAAK,CACX,gEAAgE;YAChE,8CAA8C;YAC9C,+DAA+D;YAC/D,KAAK;YACL,2GAA2G,CAC9G,CAAA;IACL,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run at GGHttpServer.start() over the frozen schema graph: the wires a single schema .use()s
|
|
3
|
+
* must not conflict with each other. Two conflicts are caught:
|
|
4
|
+
* - same context-key name → both wires resolve to one storage slot; parse() of one clobbers
|
|
5
|
+
* the value the other read.
|
|
6
|
+
* - same inbound header / cookie → both wires read (and a client writes) the same transport
|
|
7
|
+
* field; one silently overwrites the other in parse()/update().
|
|
8
|
+
* Both are per-schema: the same wire reused across different schemas is fine.
|
|
9
|
+
*/
|
|
10
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
11
|
+
export declare function checkWireConflicts(httpSchemas: readonly {
|
|
12
|
+
name: string;
|
|
13
|
+
apiMiddlewares: readonly GGTransportMiddleware[];
|
|
14
|
+
}[], webSocketSchemas: readonly {
|
|
15
|
+
name: string;
|
|
16
|
+
middlewares: readonly GGTransportMiddleware[];
|
|
17
|
+
}[]): void;
|
|
18
|
+
//# sourceMappingURL=checkWireConflicts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkWireConflicts.d.ts","sourceRoot":"","sources":["../../../../src/server/checkers/checkWireConflicts.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAA;AAe5D,wBAAgB,kBAAkB,CAC9B,WAAW,EAAE,SAAS;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,SAAS,qBAAqB,EAAE,CAAA;CAAC,EAAE,EACxF,gBAAgB,EAAE,SAAS;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,qBAAqB,EAAE,CAAA;CAAC,EAAE,GAC3F,IAAI,CAqCN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { GGWireContextKey } from "../../schema/GGWireContextKey.js";
|
|
2
|
+
function transportKeys(mw) {
|
|
3
|
+
return [
|
|
4
|
+
...Object.keys(mw.headers ?? {}).map(h => `header "${h.toLowerCase()}"`),
|
|
5
|
+
...Object.keys(mw.cookieParams ?? {}).map(c => `cookie "${c}"`),
|
|
6
|
+
];
|
|
7
|
+
}
|
|
8
|
+
export function checkWireConflicts(httpSchemas, webSocketSchemas) {
|
|
9
|
+
const schemas = [
|
|
10
|
+
...httpSchemas.map(s => ({ name: s.name, wires: s.apiMiddlewares })),
|
|
11
|
+
...webSocketSchemas.map(s => ({ name: s.name, wires: s.middlewares })),
|
|
12
|
+
];
|
|
13
|
+
const conflicts = [];
|
|
14
|
+
for (const schema of schemas) {
|
|
15
|
+
const names = new Map();
|
|
16
|
+
const fields = new Map();
|
|
17
|
+
for (const mw of schema.wires) {
|
|
18
|
+
if (mw instanceof GGWireContextKey) {
|
|
19
|
+
if (names.has(mw.name)) {
|
|
20
|
+
conflicts.push(` ${schema.name}: two wires share context-key name "${mw.name}"`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
names.set(mw.name, mw);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for (const field of transportKeys(mw)) {
|
|
27
|
+
if (fields.has(field)) {
|
|
28
|
+
conflicts.push(` ${schema.name}: two wires bind the same ${field}`);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
fields.set(field, mw);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (conflicts.length > 0) {
|
|
37
|
+
throw new Error(`GGHttpServer: conflicting wires .use()d on one schema:\n\n` +
|
|
38
|
+
conflicts.join("\n") +
|
|
39
|
+
`\n\nFix: a schema must not .use() two wires that share a context-key name or read the ` +
|
|
40
|
+
`same header/cookie — one silently clobbers the other.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=checkWireConflicts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkWireConflicts.js","sourceRoot":"","sources":["../../../../src/server/checkers/checkWireConflicts.ts"],"names":[],"mappings":"AAUA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAA;AAO9D,SAAS,aAAa,CAAC,EAAyB;IAC5C,OAAO;QACH,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC;QACxE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC;KAClE,CAAA;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAC9B,WAAwF,EACxF,gBAA0F;IAE1F,MAAM,OAAO,GAAiB;QAC1B,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,EAAC,CAAC,CAAC;QAClE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,WAAW,EAAC,CAAC,CAAC;KACvE,CAAA;IAED,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAA;QACjD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAA;QAEvD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,EAAE,YAAY,gBAAgB,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,SAAS,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,uCAAuC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAA;gBACrF,CAAC;qBAAM,CAAC;oBACJ,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;gBAC1B,CAAC;YACL,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC;gBACpC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACpB,SAAS,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,6BAA6B,KAAK,EAAE,CAAC,CAAA;gBACxE,CAAC;qBAAM,CAAC;oBACJ,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;gBACzB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACX,4DAA4D;YAC5D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YACpB,wFAAwF;YACxF,uDAAuD,CAC1D,CAAA;IACL,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface HttpSchemaLike {
|
|
2
|
+
name: string;
|
|
3
|
+
apiMiddlewares: readonly unknown[];
|
|
4
|
+
}
|
|
5
|
+
interface WebSocketSchemaLike {
|
|
6
|
+
name: string;
|
|
7
|
+
middlewares: readonly unknown[];
|
|
8
|
+
}
|
|
9
|
+
export declare function checkWiresImplemented(httpSchemas: readonly HttpSchemaLike[], webSocketSchemas: readonly WebSocketSchemaLike[]): void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=checkWiresImplemented.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkWiresImplemented.d.ts","sourceRoot":"","sources":["../../../../src/server/checkers/checkWiresImplemented.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,SAAS,OAAO,EAAE,CAAA;CACrC;AAED,UAAU,mBAAmB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,SAAS,OAAO,EAAE,CAAA;CAClC;AAED,wBAAgB,qBAAqB,CACjC,WAAW,EAAE,SAAS,cAAc,EAAE,EACtC,gBAAgB,EAAE,SAAS,mBAAmB,EAAE,GACjD,IAAI,CAqBN"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run at GGHttpServer.start() over the frozen schema graph: every wire a schema
|
|
3
|
+
* .use()s and that is .define()d must have a .create()d handler on this runtime.
|
|
4
|
+
*/
|
|
5
|
+
import { GGWireContextKey } from "../../schema/GGWireContextKey.js";
|
|
6
|
+
import { wireIsDefined } from "../../schema/GGWireContextKey.node.js";
|
|
7
|
+
export function checkWiresImplemented(httpSchemas, webSocketSchemas) {
|
|
8
|
+
const surfaces = [
|
|
9
|
+
...httpSchemas.map(s => ({ name: s.name, wires: s.apiMiddlewares })),
|
|
10
|
+
...webSocketSchemas.map(s => ({ name: s.name, wires: s.middlewares })),
|
|
11
|
+
];
|
|
12
|
+
const missing = [];
|
|
13
|
+
for (const surface of surfaces) {
|
|
14
|
+
for (const mw of surface.wires) {
|
|
15
|
+
if (mw instanceof GGWireContextKey && wireIsDefined(mw) && !mw.hasHandler()) {
|
|
16
|
+
missing.push(` ${surface.name} uses wire "${mw.name}"`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (missing.length > 0) {
|
|
21
|
+
throw new Error(`GGHttpServer: these schemas .use() a smart wire that was never implemented on this ` +
|
|
22
|
+
`runtime:\n\n` +
|
|
23
|
+
missing.join("\n") +
|
|
24
|
+
`\n\nFix: call \`${"<WIRE>"}.define(...).create(deps)\` in compose() before the server starts.`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=checkWiresImplemented.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkWiresImplemented.js","sourceRoot":"","sources":["../../../../src/server/checkers/checkWiresImplemented.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAC,aAAa,EAAC,MAAM,oCAAoC,CAAA;AAYhE,MAAM,UAAU,qBAAqB,CACjC,WAAsC,EACtC,gBAAgD;IAEhD,MAAM,QAAQ,GAAgD;QAC1D,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,EAAC,CAAC,CAAC;QAClE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,WAAW,EAAC,CAAC,CAAC;KACvE,CAAA;IACD,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,EAAE,YAAY,gBAAgB,IAAI,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC;gBAC1E,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,GAAG,CAAC,CAAA;YAC7D,CAAC;QACL,CAAC;IACL,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACX,qFAAqF;YACrF,cAAc;YACd,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAClB,mBAAmB,QAAQ,oEAAoE,CAClG,CAAA;IACL,CAAC;AACL,CAAC"}
|