@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
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { GGContextKey } from "@grest-ts/context";
|
|
2
|
+
import { IsAny, IsString, SERVER_ERROR } from "@grest-ts/schema";
|
|
3
|
+
import { GGWireContextKey } from "./GGWireContextKey.js";
|
|
4
|
+
/**
|
|
5
|
+
* Per-request set of context-key names the current route is permitted to write a cookie
|
|
6
|
+
* for (declared via GGRpc.*(...).updatesCookie(key)). Populated by the server route
|
|
7
|
+
* handler; read by setCookie() to reject undeclared cookie writes.
|
|
8
|
+
*/
|
|
9
|
+
export const GG_COOKIE_WRITES = new GGContextKey("cookie:writes", IsAny);
|
|
10
|
+
/**
|
|
11
|
+
* Per-request Set-Cookie writes scheduled via setCookie()/clearCookie(), keyed by the
|
|
12
|
+
* context key's name. Flushed onto the response by the matching cookie() binding.
|
|
13
|
+
*/
|
|
14
|
+
const GG_COOKIE_PENDING = new GGContextKey("cookie:pending", IsAny);
|
|
15
|
+
const SAFE_DEFAULTS = {
|
|
16
|
+
httpOnly: true,
|
|
17
|
+
secure: true,
|
|
18
|
+
sameSite: "lax",
|
|
19
|
+
path: "/"
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A cookie that IS its own context key.
|
|
23
|
+
*
|
|
24
|
+
* // ambient — the named cookie's value lands in the wire and persists, no implementation needed.
|
|
25
|
+
* const SESSION_WIRE = new GGCookie("session_id")
|
|
26
|
+
*
|
|
27
|
+
* Reads ONLY the named cookie — never a header — from the inbound Cookie header into the wire.
|
|
28
|
+
* For HTTP that is the request Cookie; for WebSocket the real upgrade Cookie (the runtime fills
|
|
29
|
+
* inbound.cookie from there, never from the spoofable in-band message). The cookie name is the
|
|
30
|
+
* first constructor argument (case-sensitive — unlike a header it is not lowercased). To write
|
|
31
|
+
* the cookie, call GGCookie.setCookie(key, …) from a route that declared .updatesCookie(key);
|
|
32
|
+
* this wire flushes it as Set-Cookie (HTTP only — a WebSocket has no response to set a cookie on).
|
|
33
|
+
*/
|
|
34
|
+
export class GGCookie extends GGWireContextKey {
|
|
35
|
+
cookieParams;
|
|
36
|
+
constructor(name) {
|
|
37
|
+
const WIRE_SCHEMA = IsString.orUndefined;
|
|
38
|
+
super(name, WIRE_SCHEMA);
|
|
39
|
+
_assertCookieSafe("name", this.name);
|
|
40
|
+
this.cookieParams = { [this.name]: WIRE_SCHEMA };
|
|
41
|
+
}
|
|
42
|
+
parse(inbound) {
|
|
43
|
+
const value = _readCookie(inbound.cookie, this.name);
|
|
44
|
+
if (value !== undefined)
|
|
45
|
+
this.set(value);
|
|
46
|
+
}
|
|
47
|
+
respond(res) {
|
|
48
|
+
const pending = GG_COOKIE_PENDING.get()?.get(this.name);
|
|
49
|
+
if (pending === undefined)
|
|
50
|
+
return;
|
|
51
|
+
const line = _serializeSetCookie(this.name, pending.value, pending.options);
|
|
52
|
+
const existing = res.headers["set-cookie"];
|
|
53
|
+
const arr = existing === undefined ? [] : Array.isArray(existing) ? existing : [existing];
|
|
54
|
+
arr.push(line);
|
|
55
|
+
res.headers["set-cookie"] = arr;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Schedule a Set-Cookie on the response (HTTP only). The value never touches key.get() —
|
|
59
|
+
* inbound reads stay set-once. The route must declare .updatesCookie(key); an undeclared
|
|
60
|
+
* call is invalid usage and throws SERVER_ERROR. The matching cookie() binding serializes
|
|
61
|
+
* the pending write with these options (HttpOnly/Secure/SameSite/Path/Domain/Max-Age).
|
|
62
|
+
*/
|
|
63
|
+
static setCookie(key, value, options) {
|
|
64
|
+
if (options) {
|
|
65
|
+
if (options.maxAgeSec !== undefined && !Number.isFinite(options.maxAgeSec)) {
|
|
66
|
+
throw new Error(`setCookie("${key.name}"): maxAgeSec must be a finite number, got ${options.maxAgeSec}.`);
|
|
67
|
+
}
|
|
68
|
+
if (options.path !== undefined)
|
|
69
|
+
_assertCookieSafe("path", options.path);
|
|
70
|
+
if (options.domain !== undefined)
|
|
71
|
+
_assertCookieSafe("domain", options.domain);
|
|
72
|
+
}
|
|
73
|
+
if (!GG_COOKIE_WRITES.get()?.has(key.name)) {
|
|
74
|
+
throw new SERVER_ERROR({ debugMessage: `setCookie("${key.name}") was called, but this route did not declare .updatesCookie(<key>). Only routes that declare it may set or clear the cookie.` });
|
|
75
|
+
}
|
|
76
|
+
let pending = GG_COOKIE_PENDING.get();
|
|
77
|
+
if (pending === undefined) {
|
|
78
|
+
pending = new Map();
|
|
79
|
+
GG_COOKIE_PENDING.set(pending);
|
|
80
|
+
}
|
|
81
|
+
pending.set(key.name, { value, options });
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Clear the cookie — schedules a Set-Cookie with Max-Age=0. Pass path/domain to match a
|
|
85
|
+
* scoped cookie (deletion only works when path+domain match what was set). Equivalent to
|
|
86
|
+
* setCookie(key, undefined, options), but reads clearer at logout-style call sites.
|
|
87
|
+
*/
|
|
88
|
+
static clearCookie(key, options) {
|
|
89
|
+
this.setCookie(key, undefined, options);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Reject anything that could break out of the Set-Cookie line / inject attributes.
|
|
93
|
+
function _assertCookieSafe(label, value) {
|
|
94
|
+
if (/[\x00-\x1f;]/.test(value)) {
|
|
95
|
+
throw new Error(`Cookie ${label} contains illegal characters (control chars or ';'): ${JSON.stringify(value)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Read a single named cookie out of a raw `Cookie` header value. A malformed
|
|
100
|
+
* percent-encoding (e.g. "sid=%") must not crash — fall back to the raw value.
|
|
101
|
+
*/
|
|
102
|
+
function _readCookie(rawCookieHeader, name) {
|
|
103
|
+
if (typeof rawCookieHeader !== "string")
|
|
104
|
+
return undefined;
|
|
105
|
+
for (const part of rawCookieHeader.split(";")) {
|
|
106
|
+
const eq = part.indexOf("=");
|
|
107
|
+
if (eq === -1)
|
|
108
|
+
continue;
|
|
109
|
+
if (part.slice(0, eq).trim() === name) {
|
|
110
|
+
const rawValue = part.slice(eq + 1).trim();
|
|
111
|
+
try {
|
|
112
|
+
return decodeURIComponent(rawValue);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return rawValue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
function _serializeSetCookie(name, value, options) {
|
|
122
|
+
const o = { ...SAFE_DEFAULTS, ...options };
|
|
123
|
+
const secure = o.sameSite === "none" ? true : o.secure;
|
|
124
|
+
const sameSite = `${o.sameSite.charAt(0).toUpperCase()}${o.sameSite.slice(1)}`;
|
|
125
|
+
const attrs = `; Path=${o.path}${o.domain ? `; Domain=${o.domain}` : ""}; SameSite=${sameSite}${secure ? "; Secure" : ""}${o.httpOnly ? "; HttpOnly" : ""}`;
|
|
126
|
+
return value
|
|
127
|
+
? `${name}=${encodeURIComponent(value)}${o.maxAgeSec !== undefined ? `; Max-Age=${Math.trunc(o.maxAgeSec)}` : ""}${attrs}`
|
|
128
|
+
: `${name}=; Max-Age=0${attrs}`;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=GGCookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGCookie.js","sourceRoot":"","sources":["../../../src/schema/GGCookie.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type GGInbound, type GGOutbound } from "@grest-ts/context";
|
|
2
|
+
import { type GGSchema } from "@grest-ts/schema";
|
|
3
|
+
import { GGWireContextKey } from "./GGWireContextKey";
|
|
4
|
+
/**
|
|
5
|
+
* A request header that IS its own context key.
|
|
6
|
+
*
|
|
7
|
+
* // verified: requires .define() server-side; raw credential is ephemeral.
|
|
8
|
+
* const USER_TOKEN_WIRE = new GGHeader("authorization", {scheme: "bearer"})
|
|
9
|
+
*
|
|
10
|
+
* // ambient: parsed value lands in the wire and persists, no implementation needed.
|
|
11
|
+
* const CLIENT_VERSION_WIRE = new GGHeader("x-client-version")
|
|
12
|
+
*/
|
|
13
|
+
export declare class GGHeader extends GGWireContextKey {
|
|
14
|
+
readonly headers: Record<string, GGSchema<string | undefined>>;
|
|
15
|
+
private readonly scheme?;
|
|
16
|
+
private readonly wireName;
|
|
17
|
+
constructor(name: string, options?: {
|
|
18
|
+
scheme?: "bearer";
|
|
19
|
+
});
|
|
20
|
+
parse(inbound: GGInbound): void;
|
|
21
|
+
update(outbound: GGOutbound): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=GGHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGHeader.d.ts","sourceRoot":"","sources":["../../../src/schema/GGHeader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,SAAS,EAAE,KAAK,UAAU,EAAC,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAC,KAAK,QAAQ,EAAW,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAKnD;;;;;;;;GAQG;AACH,qBAAa,QAAS,SAAQ,gBAAgB;IAE1C,SAAgB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IACrE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,QAAQ,CAAA;KAAE;IAQlD,KAAK,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAW/B,MAAM,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;CAM5C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { IsString } from "@grest-ts/schema";
|
|
2
|
+
import { GGWireContextKey } from "./GGWireContextKey.js";
|
|
3
|
+
const BEARER = "Bearer ";
|
|
4
|
+
/**
|
|
5
|
+
* A request header that IS its own context key.
|
|
6
|
+
*
|
|
7
|
+
* // verified: requires .define() server-side; raw credential is ephemeral.
|
|
8
|
+
* const USER_TOKEN_WIRE = new GGHeader("authorization", {scheme: "bearer"})
|
|
9
|
+
*
|
|
10
|
+
* // ambient: parsed value lands in the wire and persists, no implementation needed.
|
|
11
|
+
* const CLIENT_VERSION_WIRE = new GGHeader("x-client-version")
|
|
12
|
+
*/
|
|
13
|
+
export class GGHeader extends GGWireContextKey {
|
|
14
|
+
headers;
|
|
15
|
+
scheme;
|
|
16
|
+
wireName;
|
|
17
|
+
constructor(name, options) {
|
|
18
|
+
const WIRE_SCHEMA = IsString.orUndefined;
|
|
19
|
+
super(name, WIRE_SCHEMA);
|
|
20
|
+
this.scheme = options?.scheme;
|
|
21
|
+
this.wireName = name.toLowerCase();
|
|
22
|
+
this.headers = { [this.wireName]: WIRE_SCHEMA };
|
|
23
|
+
}
|
|
24
|
+
parse(inbound) {
|
|
25
|
+
const raw = inbound.headers[this.wireName];
|
|
26
|
+
if (raw === undefined) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const value = this.scheme === "bearer" && raw.startsWith(BEARER) ? raw.slice(BEARER.length) : raw;
|
|
30
|
+
if (value !== undefined) {
|
|
31
|
+
this.set(value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
update(outbound) {
|
|
35
|
+
const value = this.get();
|
|
36
|
+
if (value !== undefined) {
|
|
37
|
+
outbound.headers[this.wireName] = (this.scheme === "bearer" ? `${BEARER}${value}` : value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=GGHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGHeader.js","sourceRoot":"","sources":["../../../src/schema/GGHeader.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAEnD,MAAM,MAAM,GAAG,SAAS,CAAA;AAGxB;;;;;;;;GAQG;AACH,MAAM,OAAO,QAAS,SAAQ,gBAAgB;IAE1B,OAAO,CAA8C;IACpD,MAAM,CAAW;IACjB,QAAQ,CAAQ;IAEjC,YAAY,IAAY,EAAE,OAA+B;QACrD,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QACxC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAA;QAC7B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAClC,IAAI,CAAC,OAAO,GAAG,EAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAC,CAAA;IACjD,CAAC;IAEM,KAAK,CAAC,OAAkB;QAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO,SAAS,CAAA;QACpB,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACjG,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,QAAoB;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QAC9F,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
2
|
+
import { GGPermission } from "@grest-ts/schema";
|
|
3
|
+
export declare class GGHttpPermissionsChecker {
|
|
4
|
+
private readonly middlewaresWithPermissions;
|
|
5
|
+
constructor(apiMiddlewares: readonly GGTransportMiddleware[]);
|
|
6
|
+
assert(schema: string, method: string, required: GGPermission): Promise<ReadonlyArray<ReadonlyArray<string>>>;
|
|
7
|
+
assertGrants(schema: string, method: string, granted: undefined | ReadonlyArray<ReadonlyArray<string>>, required: GGPermission): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=GGHttpPermissionsChecker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGHttpPermissionsChecker.d.ts","sourceRoot":"","sources":["../../../src/schema/GGHttpPermissionsChecker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAY,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAE9E,qBAAa,wBAAwB;IAEjC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAyB;gBAExD,cAAc,EAAE,SAAS,qBAAqB,EAAE;IAS/C,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IASnH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI;CAQ/I"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GGWireContextKey } from "./GGWireContextKey.js";
|
|
2
|
+
import { FORBIDDEN, GGPermissionChecker } from "@grest-ts/schema";
|
|
3
|
+
export class GGHttpPermissionsChecker {
|
|
4
|
+
middlewaresWithPermissions = [];
|
|
5
|
+
constructor(apiMiddlewares) {
|
|
6
|
+
for (const mw of apiMiddlewares) {
|
|
7
|
+
if (mw instanceof GGWireContextKey && mw.hasPermissions()) {
|
|
8
|
+
this.middlewaresWithPermissions.push(mw);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
Object.freeze(this.middlewaresWithPermissions);
|
|
12
|
+
}
|
|
13
|
+
async assert(schema, method, required) {
|
|
14
|
+
const scopes = [];
|
|
15
|
+
for (let i = 0; i < this.middlewaresWithPermissions.length; i++) {
|
|
16
|
+
scopes.push(await this.middlewaresWithPermissions[i].getGrantedPermissions());
|
|
17
|
+
}
|
|
18
|
+
this.assertGrants(schema, method, scopes, required);
|
|
19
|
+
return Object.freeze(scopes);
|
|
20
|
+
}
|
|
21
|
+
assertGrants(schema, method, granted, required) {
|
|
22
|
+
if (!GGPermissionChecker.satisfies(required, granted)) {
|
|
23
|
+
throw new FORBIDDEN({
|
|
24
|
+
debugMessage: `${schema + (method ? "." + method : "")} requires ${GGPermissionChecker.describePermission(required)} — caller scopes did not satisfy`
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=GGHttpPermissionsChecker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGHttpPermissionsChecker.js","sourceRoot":"","sources":["../../../src/schema/GGHttpPermissionsChecker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAC,SAAS,EAAgB,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAE9E,MAAM,OAAO,wBAAwB;IAEhB,0BAA0B,GAAuB,EAAE,CAAA;IAEpE,YAAY,cAAgD;QACxD,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;YAC9B,IAAI,EAAE,YAAY,gBAAgB,IAAI,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC;gBACxD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;IAClD,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc,EAAE,QAAsB;QACtE,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9D,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAA;QACjF,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;QACnD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAwB,CAAA;IACvD,CAAC;IAEM,YAAY,CAAC,MAAc,EAAE,MAAc,EAAE,OAAyD,EAAE,QAAsB;QACjI,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,SAAS,CAAC;gBAChB,YAAY,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,mBAAmB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,kCAAkC;aACxJ,CAAC,CAAA;QACN,CAAC;IACL,CAAC;CAEJ"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { ERROR, ERROR_JSON, GGContractApiDefinition, GGContractClass, GGContractMethod, GGSchema, GGSchemaDescription, OK } from "@grest-ts/schema";
|
|
2
2
|
import type { HttpMethod } from "@grest-ts/common";
|
|
3
3
|
import type http from "http";
|
|
4
|
-
import type {
|
|
4
|
+
import type { GGContextKey, GGTransportMiddleware } from "@grest-ts/context";
|
|
5
5
|
import type { OpenAPIV3_1 } from "openapi-types";
|
|
6
6
|
export declare class GGHttpSchema<TContract extends GGContractApiDefinition, TContext> {
|
|
7
7
|
readonly name: string;
|
|
8
8
|
readonly pathPrefix: string;
|
|
9
|
-
readonly apiMiddlewares: readonly
|
|
9
|
+
readonly apiMiddlewares: readonly GGTransportMiddleware[];
|
|
10
10
|
readonly codec: Record<keyof TContract, GGHttpCodec>;
|
|
11
11
|
readonly contract: GGContractClass<TContract> | null;
|
|
12
|
-
constructor(pathPrefix: string, contract: GGContractClass<TContract>, wireCodec: Record<keyof TContract, GGHttpCodec>, middlewares?: readonly
|
|
12
|
+
constructor(pathPrefix: string, contract: GGContractClass<TContract>, wireCodec: Record<keyof TContract, GGHttpCodec>, middlewares?: readonly GGTransportMiddleware[]);
|
|
13
13
|
}
|
|
14
14
|
export interface ClientHttpRouteToRpcTransformClientConfig {
|
|
15
15
|
pathPrefix: string;
|
|
16
16
|
contract: GGContractMethod;
|
|
17
|
-
middlewares: readonly
|
|
17
|
+
middlewares: readonly GGTransportMiddleware[];
|
|
18
18
|
}
|
|
19
19
|
export interface ClientHttpRouteToRpcTransformClientCodec {
|
|
20
20
|
createRequest: (data: unknown) => GGHttpFetchRequest | Promise<GGHttpFetchRequest>;
|
|
@@ -28,11 +28,12 @@ export interface GGHttpFetchRequest {
|
|
|
28
28
|
}
|
|
29
29
|
export interface ClientHttpRouteToRpcTransformServerConfig {
|
|
30
30
|
contract: GGContractMethod;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/** Schema bindings + server middlewares, already merged into one ordered server pipeline. */
|
|
32
|
+
middlewares: readonly GGTransportMiddleware[];
|
|
33
33
|
}
|
|
34
34
|
export interface ClientHttpRouteToRpcTransformServerCodec {
|
|
35
|
-
|
|
35
|
+
readRequest: (req: http.IncomingMessage) => Promise<unknown>;
|
|
36
|
+
validateInput: (rawInput: unknown) => unknown;
|
|
36
37
|
sendResponse: (res: http.ServerResponse, rpcResult: ERROR<string, unknown> | OK<unknown>) => Promise<void>;
|
|
37
38
|
}
|
|
38
39
|
/**
|
|
@@ -73,6 +74,12 @@ export interface GGHttpCodec {
|
|
|
73
74
|
* Use {} if the codec sets no custom response headers.
|
|
74
75
|
*/
|
|
75
76
|
readonly responseHeaders: Record<string, GGSchema<string | undefined>>;
|
|
77
|
+
/**
|
|
78
|
+
* Cookie context keys this route is permitted to modify (set/clear), declared via
|
|
79
|
+
* GGRpc.*(...).updatesCookie(key). A handler that changes a cookie its route did not
|
|
80
|
+
* declare is a SERVER_ERROR. Reading a cookie needs no declaration.
|
|
81
|
+
*/
|
|
82
|
+
readonly updatesCookies?: readonly GGContextKey<string | undefined>[];
|
|
76
83
|
createForClient(config: ClientHttpRouteToRpcTransformClientConfig): ClientHttpRouteToRpcTransformClientCodec;
|
|
77
84
|
createForServer(config: ClientHttpRouteToRpcTransformServerConfig): ClientHttpRouteToRpcTransformServerCodec;
|
|
78
85
|
/**
|
|
@@ -85,49 +92,4 @@ export interface GGHttpCodec {
|
|
|
85
92
|
*/
|
|
86
93
|
toOpenApiOperation?(config: GGHttpCodecOpenApiConfig): Partial<OpenAPIV3_1.OperationObject>;
|
|
87
94
|
}
|
|
88
|
-
export interface GGHttpTransportMiddleware {
|
|
89
|
-
/**
|
|
90
|
-
* Request headers this middleware reads or writes, mapped to their value schemas.
|
|
91
|
-
* Keys are header names; values describe the header value format for validation and docs.
|
|
92
|
-
* Used for CORS Access-Control-Allow-Headers and OpenAPI parameter docs.
|
|
93
|
-
* Use {} if the middleware touches no custom request headers.
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* headers: {
|
|
97
|
-
* "authorization": IsString.nonEmpty.docs({title: "Bearer token", example: "Bearer ..."}),
|
|
98
|
-
* "accept-language": IsLocale.orUndefined
|
|
99
|
-
* }
|
|
100
|
-
*/
|
|
101
|
-
readonly headers: Record<string, GGSchema<string | undefined>>;
|
|
102
|
-
/**
|
|
103
|
-
* Response headers this middleware sets, mapped to their value schemas.
|
|
104
|
-
* Keys are header names; values describe the header value format for validation and docs.
|
|
105
|
-
* Used for CORS Access-Control-Expose-Headers and OpenAPI response header docs.
|
|
106
|
-
* Use {} if the middleware sets no custom response headers.
|
|
107
|
-
*/
|
|
108
|
-
readonly responseHeaders: Record<string, GGSchema<string | undefined>>;
|
|
109
|
-
/**
|
|
110
|
-
* Client-side: modify outgoing request (add headers, etc.)
|
|
111
|
-
*/
|
|
112
|
-
updateRequest?(req: GGHttpRequest): void;
|
|
113
|
-
/**
|
|
114
|
-
* Server-side: parse incoming request (extract context from headers, etc.)
|
|
115
|
-
*/
|
|
116
|
-
parseRequest?(req: GGHttpRequest): void;
|
|
117
|
-
/**
|
|
118
|
-
* Server-side: modify outgoing response
|
|
119
|
-
*/
|
|
120
|
-
updateResponse?(res: GGHttpResponse): void;
|
|
121
|
-
/**
|
|
122
|
-
* Client-side: parse incoming response
|
|
123
|
-
*/
|
|
124
|
-
parseResponse?(res: GGHttpResponse): void;
|
|
125
|
-
}
|
|
126
|
-
export interface GGHttpRequest {
|
|
127
|
-
headers?: Record<string, string | string[]>;
|
|
128
|
-
queryArgs?: Record<string, string | string[]>;
|
|
129
|
-
}
|
|
130
|
-
export interface GGHttpResponse {
|
|
131
|
-
headers: Record<string, string | string[]>;
|
|
132
|
-
}
|
|
133
95
|
//# sourceMappingURL=GGHttpSchema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GGHttpSchema.d.ts","sourceRoot":"","sources":["../../../src/schema/GGHttpSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,EAAE,EAAC,MAAM,kBAAkB,CAAC;AAClJ,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"GGHttpSchema.d.ts","sourceRoot":"","sources":["../../../src/schema/GGHttpSchema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GGHttpSchema.js","sourceRoot":"","sources":["../../../src/schema/GGHttpSchema.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,YAAY;IAEL,IAAI,CAAQ;IACZ,UAAU,CAAQ;IAClB,cAAc,
|
|
1
|
+
{"version":3,"file":"GGHttpSchema.js","sourceRoot":"","sources":["../../../src/schema/GGHttpSchema.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,YAAY;IAEL,IAAI,CAAQ;IACZ,UAAU,CAAQ;IAClB,cAAc,CAAkC;IAChD,KAAK,CAAsC;IAC3C,QAAQ,GAAsC,IAAI,CAAA;IAElE,YACI,UAAkB,EAClB,QAAoC,EACpC,SAA+C,EAC/C,cAAgD,EAAE;QAElD,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAA;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,cAAc,GAAG,WAAW,CAAA;QACjC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC;CACJ"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { GGContextKey, type GGTransportMiddleware } from "@grest-ts/context";
|
|
2
|
+
/** Outbound freshness gate for a smart wire. The outbound value is always the wire's own context value. */
|
|
3
|
+
export interface GGWireClientHandler {
|
|
4
|
+
/** Async — true when the wire value is stale and recover() should run before the next outbound read. */
|
|
5
|
+
isStale?: () => boolean;
|
|
6
|
+
/** Async — refresh the credential into the wire (via key.set); run by the synchronizer's waitFor before the outbound read. */
|
|
7
|
+
recover?: () => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Base for credential wires (GGHeader, GGCookie). A wire IS a GGContextKey and a transport
|
|
11
|
+
* middleware at once. Verified vs ambient is decided by whether `.define()` was called:
|
|
12
|
+
* - verified (`.define()`d): the wire holds the raw inbound credential, which is verified
|
|
13
|
+
* during process(), then clear()d before the handler runs — handlers read the durable key
|
|
14
|
+
* minted by the handler, never the credential.
|
|
15
|
+
* - ambient (never `.define()`d): the parsed value lands in the wire and persists through the
|
|
16
|
+
* handler (read via WIRE.get()); no process, no clear, no implementation needed.
|
|
17
|
+
*
|
|
18
|
+
* The server/inbound half (define/create/process/permissions) is attached node-side via
|
|
19
|
+
* ./GGWireContextKey.node — the browser bundle never pulls @grest-ts/locator.
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class GGWireContextKey extends GGContextKey<string | undefined> implements GGTransportMiddleware {
|
|
22
|
+
private _clientHandler?;
|
|
23
|
+
/**
|
|
24
|
+
* Attach the outbound freshness gate. Freeze-once. The outbound value is always the wire's
|
|
25
|
+
* context value; this only registers an isStale/recover gate that refreshes it before the read.
|
|
26
|
+
* GGAuthSession calls it internally on the wires it holds.
|
|
27
|
+
*/
|
|
28
|
+
defineClient(handler: GGWireClientHandler): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=GGWireContextKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWireContextKey.d.ts","sourceRoot":"","sources":["../../../src/schema/GGWireContextKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,KAAK,qBAAqB,EAAC,MAAM,mBAAmB,CAAA;AAG1E,2GAA2G;AAC3G,MAAM,WAAW,mBAAmB;IAChC,wGAAwG;IACxG,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;IACvB,8HAA8H;IAC9H,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAChC;AAED;;;;;;;;;;;GAWG;AACH,8BAAsB,gBAAiB,SAAQ,YAAY,CAAC,MAAM,GAAG,SAAS,CAAE,YAAW,qBAAqB;IAE5G,OAAO,CAAC,cAAc,CAAC,CAAqB;IAE5C;;;;OAIG;IACI,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;CAa1D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { GGContextKey } from "@grest-ts/context";
|
|
2
|
+
import { GGContextKeySynchronizer } from "../client/GGContextKeySynchronizer.js";
|
|
3
|
+
/**
|
|
4
|
+
* Base for credential wires (GGHeader, GGCookie). A wire IS a GGContextKey and a transport
|
|
5
|
+
* middleware at once. Verified vs ambient is decided by whether `.define()` was called:
|
|
6
|
+
* - verified (`.define()`d): the wire holds the raw inbound credential, which is verified
|
|
7
|
+
* during process(), then clear()d before the handler runs — handlers read the durable key
|
|
8
|
+
* minted by the handler, never the credential.
|
|
9
|
+
* - ambient (never `.define()`d): the parsed value lands in the wire and persists through the
|
|
10
|
+
* handler (read via WIRE.get()); no process, no clear, no implementation needed.
|
|
11
|
+
*
|
|
12
|
+
* The server/inbound half (define/create/process/permissions) is attached node-side via
|
|
13
|
+
* ./GGWireContextKey.node — the browser bundle never pulls @grest-ts/locator.
|
|
14
|
+
*/
|
|
15
|
+
export class GGWireContextKey extends GGContextKey {
|
|
16
|
+
_clientHandler;
|
|
17
|
+
/**
|
|
18
|
+
* Attach the outbound freshness gate. Freeze-once. The outbound value is always the wire's
|
|
19
|
+
* context value; this only registers an isStale/recover gate that refreshes it before the read.
|
|
20
|
+
* GGAuthSession calls it internally on the wires it holds.
|
|
21
|
+
*/
|
|
22
|
+
defineClient(handler) {
|
|
23
|
+
if (this._clientHandler) {
|
|
24
|
+
throw new Error(`Wire "${this.name}" already has .defineClient() — it can only be defined once.`);
|
|
25
|
+
}
|
|
26
|
+
this._clientHandler = handler;
|
|
27
|
+
if (handler.isStale || handler.recover) {
|
|
28
|
+
GGContextKeySynchronizer.provide(this, {
|
|
29
|
+
isStale: handler.isStale ?? (() => false),
|
|
30
|
+
recover: handler.recover ?? (async () => {
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=GGWireContextKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWireContextKey.js","sourceRoot":"","sources":["../../../src/schema/GGWireContextKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAA6B,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAC,wBAAwB,EAAC,MAAM,oCAAoC,CAAA;AAU3E;;;;;;;;;;;GAWG;AACH,MAAM,OAAgB,gBAAiB,SAAQ,YAAgC;IAEnE,cAAc,CAAsB;IAE5C;;;;OAIG;IACI,YAAY,CAAC,OAA4B;QAC5C,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,8DAA8D,CAAC,CAAA;QACrG,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAA;QAC7B,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,wBAAwB,CAAC,OAAO,CAAC,IAAI,EAAE;gBACnC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;gBACzC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE;gBACxC,CAAC,CAAC;aACL,CAAC,CAAA;QACN,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { GGWireContextKey } from "./GGWireContextKey";
|
|
2
|
+
export interface GGWireServerHandler {
|
|
3
|
+
/** Verify the raw credential and mint the durable principal. Throws to reject the request. */
|
|
4
|
+
process: () => Promise<void>;
|
|
5
|
+
/** The caller's grants from this wire — read off the durable principal minted in process(). */
|
|
6
|
+
permissions?: () => Promise<readonly string[]>;
|
|
7
|
+
}
|
|
8
|
+
/** True once .define() has run on this wire — distinguishes verified wires from ambient ones. */
|
|
9
|
+
export declare function wireIsDefined(wire: GGWireContextKey): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Binds the verification handler's deps into one runtime's locator scope. Returned by
|
|
12
|
+
* `.define()`; `.create(deps)` runs once per scope (a fresh worker / restart gets its own).
|
|
13
|
+
*/
|
|
14
|
+
export declare class GGWireHandlerRegistration<Deps> {
|
|
15
|
+
private readonly wire;
|
|
16
|
+
private readonly factory;
|
|
17
|
+
constructor(wire: GGWireContextKey, factory: (deps: Deps) => GGWireServerHandler);
|
|
18
|
+
create(deps: Deps): void;
|
|
19
|
+
}
|
|
20
|
+
declare module "./GGWireContextKey" {
|
|
21
|
+
interface GGWireContextKey {
|
|
22
|
+
/** Attach the server-side verification handler. Process-global, frozen once — a second call throws. */
|
|
23
|
+
define<Deps>(factory: (deps: Deps) => GGWireServerHandler): GGWireHandlerRegistration<Deps>;
|
|
24
|
+
/** @internal server pipeline hook — verify the credential and mint the durable principal. */
|
|
25
|
+
process(): Promise<void>;
|
|
26
|
+
/** @internal If wire is handling permissions **/
|
|
27
|
+
hasPermissions(): boolean;
|
|
28
|
+
/** @internal permission-gate hook — the caller's grants from this wire. */
|
|
29
|
+
getGrantedPermissions(): Promise<readonly string[]>;
|
|
30
|
+
/** @internal startup validation — true once .create() has run on the current runtime scope. */
|
|
31
|
+
hasHandler(): boolean;
|
|
32
|
+
/** Drop the ephemeral raw credential after process(); ambient wires keep their value. */
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=GGWireContextKey.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWireContextKey.node.d.ts","sourceRoot":"","sources":["../../../src/schema/GGWireContextKey.node.ts"],"names":[],"mappings":"AAMA,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAEnD,MAAM,WAAW,mBAAmB;IAChC,8FAA8F;IAC9F,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;CACjD;AAUD,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE7D;AAmBD;;;GAGG;AACH,qBAAa,yBAAyB,CAAC,IAAI;IAEnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,mBAAmB;IAI1D,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;CAOlC;AAED,OAAO,QAAQ,oBAAoB,CAAC;IAChC,UAAU,gBAAgB;QACtB,uGAAuG;QACvG,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,mBAAmB,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAA;QAE3F,6FAA6F;QAC7F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;QAExB,iDAAiD;QACjD,cAAc,IAAI,OAAO,CAAC;QAE1B,2EAA2E;QAC3E,qBAAqB,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;QAEnD,+FAA+F;QAC/F,UAAU,IAAI,OAAO,CAAA;QAErB,yFAAyF;QACzF,KAAK,IAAI,IAAI,CAAA;KAChB;CACJ"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server/inbound half of the wire model: define/create the verification handler, run it during
|
|
3
|
+
* the request pipeline (process), and expose the caller's grants to the permission gate
|
|
4
|
+
* (permissions). Node-only — keeps @grest-ts/locator out of the browser bundle.
|
|
5
|
+
*/
|
|
6
|
+
import { GGLocator, GGLocatorKey } from "@grest-ts/locator";
|
|
7
|
+
import { GGWireContextKey } from "./GGWireContextKey.js";
|
|
8
|
+
const HANDLER_KEYS = new WeakMap();
|
|
9
|
+
const FACTORIES = new WeakMap();
|
|
10
|
+
// Locator keys resolve by their string name, so the handler key must be unique per wire
|
|
11
|
+
// instance — two wires over the same name (e.g. a public ambient cookie and a gated one
|
|
12
|
+
// over the same cookie name) must not share a handler.
|
|
13
|
+
let nextWireHandlerId = 0;
|
|
14
|
+
/** True once .define() has run on this wire — distinguishes verified wires from ambient ones. */
|
|
15
|
+
export function wireIsDefined(wire) {
|
|
16
|
+
return FACTORIES.has(wire);
|
|
17
|
+
}
|
|
18
|
+
function handlerKeyFor(wire) {
|
|
19
|
+
let key = HANDLER_KEYS.get(wire);
|
|
20
|
+
if (!key) {
|
|
21
|
+
key = new GGLocatorKey(`wire:${wire.name}:${nextWireHandlerId++}`);
|
|
22
|
+
HANDLER_KEYS.set(wire, key);
|
|
23
|
+
}
|
|
24
|
+
return key;
|
|
25
|
+
}
|
|
26
|
+
function resolveHandler(wire) {
|
|
27
|
+
const handler = handlerKeyFor(wire).tryGet();
|
|
28
|
+
if (!handler) {
|
|
29
|
+
throw new Error(`Wire "${wire.name}" is used but not implemented — call ${wire.name}.define(...).create(deps) in compose().`);
|
|
30
|
+
}
|
|
31
|
+
return handler;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Binds the verification handler's deps into one runtime's locator scope. Returned by
|
|
35
|
+
* `.define()`; `.create(deps)` runs once per scope (a fresh worker / restart gets its own).
|
|
36
|
+
*/
|
|
37
|
+
export class GGWireHandlerRegistration {
|
|
38
|
+
wire;
|
|
39
|
+
factory;
|
|
40
|
+
constructor(wire, factory) {
|
|
41
|
+
this.wire = wire;
|
|
42
|
+
this.factory = factory;
|
|
43
|
+
}
|
|
44
|
+
create(deps) {
|
|
45
|
+
const key = handlerKeyFor(this.wire);
|
|
46
|
+
if (GGLocator.getScope().has(key)) {
|
|
47
|
+
throw new Error(`Wire "${this.wire.name}" was already created in this runtime scope — .create() runs once per runtime.`);
|
|
48
|
+
}
|
|
49
|
+
GGLocator.getScope().set(key, this.factory(deps));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
GGWireContextKey.prototype.define = function (factory) {
|
|
53
|
+
if (FACTORIES.has(this)) {
|
|
54
|
+
throw new Error(`Wire "${this.name}" already has .define() — it can only be defined once.`);
|
|
55
|
+
}
|
|
56
|
+
FACTORIES.set(this, factory);
|
|
57
|
+
return new GGWireHandlerRegistration(this, factory);
|
|
58
|
+
};
|
|
59
|
+
GGWireContextKey.prototype.process = async function () {
|
|
60
|
+
if (!this.hasHandler())
|
|
61
|
+
return;
|
|
62
|
+
await resolveHandler(this).process();
|
|
63
|
+
};
|
|
64
|
+
GGWireContextKey.prototype.hasPermissions = function () {
|
|
65
|
+
if (!this.hasHandler())
|
|
66
|
+
return false;
|
|
67
|
+
const handler = resolveHandler(this);
|
|
68
|
+
return !!handler.permissions;
|
|
69
|
+
};
|
|
70
|
+
GGWireContextKey.prototype.getGrantedPermissions = async function () {
|
|
71
|
+
if (!this.hasHandler())
|
|
72
|
+
return [];
|
|
73
|
+
const handler = resolveHandler(this);
|
|
74
|
+
return handler.permissions ? await handler.permissions() : [];
|
|
75
|
+
};
|
|
76
|
+
GGWireContextKey.prototype.hasHandler = function () {
|
|
77
|
+
return handlerKeyFor(this).has();
|
|
78
|
+
};
|
|
79
|
+
GGWireContextKey.prototype.clear = function () {
|
|
80
|
+
if (this.hasHandler() && this.has())
|
|
81
|
+
this.delete();
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=GGWireContextKey.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWireContextKey.node.js","sourceRoot":"","sources":["../../../src/schema/GGWireContextKey.node.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAC,SAAS,EAAE,YAAY,EAAC,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AASnD,MAAM,YAAY,GAAG,IAAI,OAAO,EAAuD,CAAA;AACvF,MAAM,SAAS,GAAG,IAAI,OAAO,EAA6B,CAAA;AAE1D,wFAAwF;AACxF,wFAAwF;AACxF,uDAAuD;AACvD,IAAI,iBAAiB,GAAG,CAAC,CAAA;AAEzB,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,IAAsB;IAChD,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC;AAED,SAAS,aAAa,CAAC,IAAsB;IACzC,IAAI,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,GAAG,GAAG,IAAI,YAAY,CAAsB,QAAQ,IAAI,CAAC,IAAI,IAAI,iBAAiB,EAAE,EAAE,CAAC,CAAA;QACvF,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC/B,CAAC;IACD,OAAO,GAAG,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAsB;IAC1C,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAA;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,wCAAwC,IAAI,CAAC,IAAI,yCAAyC,CAAC,CAAA;IACjI,CAAC;IACD,OAAO,OAAO,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IAEb;IACA;IAFrB,YACqB,IAAsB,EACtB,OAA4C;QAD5C,SAAI,GAAJ,IAAI,CAAkB;QACtB,YAAO,GAAP,OAAO,CAAqC;IAEjE,CAAC;IAEM,MAAM,CAAC,IAAU;QACpB,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,gFAAgF,CAAC,CAAA;QAC5H,CAAC;QACD,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,CAAC;CACJ;AAwBD,gBAAgB,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU,OAAO;IACjD,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,wDAAwD,CAAC,CAAA;IAC/F,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC5B,OAAO,IAAI,yBAAyB,CAAC,IAAI,EAAE,OAAc,CAAC,CAAA;AAC9D,CAAC,CAAA;AAED,gBAAgB,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK;IACtC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;QAAE,OAAM;IAC9B,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAA;AACxC,CAAC,CAAA;AAED,gBAAgB,CAAC,SAAS,CAAC,cAAc,GAAG;IACxC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;QAAE,OAAO,KAAK,CAAA;IACpC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;IACpC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAA;AAChC,CAAC,CAAA;AAED,gBAAgB,CAAC,SAAS,CAAC,qBAAqB,GAAG,KAAK;IACpD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;IACpC,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACjE,CAAC,CAAA;AAED,gBAAgB,CAAC,SAAS,CAAC,UAAU,GAAG;IACpC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAA;AACpC,CAAC,CAAA;AAED,gBAAgB,CAAC,SAAS,CAAC,KAAK,GAAG;IAC/B,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE;QAAE,IAAI,CAAC,MAAM,EAAE,CAAA;AACtD,CAAC,CAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { GGHttpCodec, GGHttpSchema } from "./GGHttpSchema";
|
|
2
|
-
import { GGHttpTransportMiddleware } from "./GGHttpSchema";
|
|
3
2
|
import { GGContractApiDefinition, GGContractClass } from "@grest-ts/schema";
|
|
4
|
-
import {
|
|
3
|
+
import type { GGTransportMiddleware } from "@grest-ts/context";
|
|
5
4
|
/**
|
|
6
5
|
* Create an HTTP API schema builder from a contract.
|
|
7
6
|
*
|
|
@@ -33,8 +32,7 @@ declare class GGHttpSchemaBuilder<TContract extends GGContractApiDefinition, TCo
|
|
|
33
32
|
private _middlewares;
|
|
34
33
|
constructor(contract: GGContractClass<TContract>);
|
|
35
34
|
pathPrefix(prefix: string): this;
|
|
36
|
-
use<M extends
|
|
37
|
-
useHeader<Input>(contextKey: GGContextKey<Input>): GGHttpSchemaBuilder<TContract, TContext | Input>;
|
|
35
|
+
use<M extends GGTransportMiddleware>(middleware: M): GGHttpSchemaBuilder<TContract, TContext | M>;
|
|
38
36
|
routes(mapping: {
|
|
39
37
|
[K in keyof TContract]: GGHttpCodec;
|
|
40
38
|
}): GGHttpSchema<TContract, TContext>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpSchema.d.ts","sourceRoot":"","sources":["../../../src/schema/httpSchema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"httpSchema.d.ts","sourceRoot":"","sources":["../../../src/schema/httpSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAC,uBAAuB,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CAAC,SAAS,SAAS,uBAAuB,EAChE,QAAQ,EAAE,eAAe,CAAC,SAAS,CAAC,GACrC,mBAAmB,CAAC,SAAS,CAAC,CAEhC;AAED,cAAM,mBAAmB,CAAC,SAAS,SAAS,uBAAuB,EAAE,QAAQ,GAAG,SAAS;IAErF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,YAAY,CAA8B;gBAEtC,QAAQ,EAAE,eAAe,CAAC,SAAS,CAAC;IAIhD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKhC,GAAG,CAAC,CAAC,SAAS,qBAAqB,EAAE,UAAU,EAAE,CAAC,GAAG,mBAAmB,CAAC,SAAS,EAAE,QAAQ,GAAG,CAAC,CAAC;IAKjG,MAAM,CAAC,OAAO,EAAE;SAAG,CAAC,IAAI,MAAM,SAAS,GAAG,WAAW;KAAE,GAAG,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC;CAG9F"}
|