@inkbox/sdk 0.2.16 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +10 -1
  2. package/dist/_http.d.ts +24 -5
  3. package/dist/_http.d.ts.map +1 -1
  4. package/dist/_http.js +21 -11
  5. package/dist/_http.js.map +1 -1
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/inkbox.d.ts +4 -0
  11. package/dist/inkbox.d.ts.map +1 -1
  12. package/dist/inkbox.js +5 -0
  13. package/dist/inkbox.js.map +1 -1
  14. package/dist/tunnels/_validation.d.ts +7 -0
  15. package/dist/tunnels/_validation.d.ts.map +1 -0
  16. package/dist/tunnels/_validation.js +27 -0
  17. package/dist/tunnels/_validation.js.map +1 -0
  18. package/dist/tunnels/client/_bridge.d.ts +35 -0
  19. package/dist/tunnels/client/_bridge.d.ts.map +1 -0
  20. package/dist/tunnels/client/_bridge.js +52 -0
  21. package/dist/tunnels/client/_bridge.js.map +1 -0
  22. package/dist/tunnels/client/_callable_streaming.d.ts +25 -0
  23. package/dist/tunnels/client/_callable_streaming.d.ts.map +1 -0
  24. package/dist/tunnels/client/_callable_streaming.js +158 -0
  25. package/dist/tunnels/client/_callable_streaming.js.map +1 -0
  26. package/dist/tunnels/client/_cert.d.ts +45 -0
  27. package/dist/tunnels/client/_cert.d.ts.map +1 -0
  28. package/dist/tunnels/client/_cert.js +193 -0
  29. package/dist/tunnels/client/_cert.js.map +1 -0
  30. package/dist/tunnels/client/_dispatch.d.ts +109 -0
  31. package/dist/tunnels/client/_dispatch.d.ts.map +1 -0
  32. package/dist/tunnels/client/_dispatch.js +314 -0
  33. package/dist/tunnels/client/_dispatch.js.map +1 -0
  34. package/dist/tunnels/client/_envelope.d.ts +55 -0
  35. package/dist/tunnels/client/_envelope.d.ts.map +1 -0
  36. package/dist/tunnels/client/_envelope.js +97 -0
  37. package/dist/tunnels/client/_envelope.js.map +1 -0
  38. package/dist/tunnels/client/_h1_server.d.ts +37 -0
  39. package/dist/tunnels/client/_h1_server.d.ts.map +1 -0
  40. package/dist/tunnels/client/_h1_server.js +433 -0
  41. package/dist/tunnels/client/_h1_server.js.map +1 -0
  42. package/dist/tunnels/client/_h2_transcode.d.ts +43 -0
  43. package/dist/tunnels/client/_h2_transcode.d.ts.map +1 -0
  44. package/dist/tunnels/client/_h2_transcode.js +488 -0
  45. package/dist/tunnels/client/_h2_transcode.js.map +1 -0
  46. package/dist/tunnels/client/_handler.d.ts +62 -0
  47. package/dist/tunnels/client/_handler.d.ts.map +1 -0
  48. package/dist/tunnels/client/_handler.js +121 -0
  49. package/dist/tunnels/client/_handler.js.map +1 -0
  50. package/dist/tunnels/client/_listener.d.ts +64 -0
  51. package/dist/tunnels/client/_listener.d.ts.map +1 -0
  52. package/dist/tunnels/client/_listener.js +113 -0
  53. package/dist/tunnels/client/_listener.js.map +1 -0
  54. package/dist/tunnels/client/_protocol.d.ts +67 -0
  55. package/dist/tunnels/client/_protocol.d.ts.map +1 -0
  56. package/dist/tunnels/client/_protocol.js +86 -0
  57. package/dist/tunnels/client/_protocol.js.map +1 -0
  58. package/dist/tunnels/client/_runtime.d.ts +143 -0
  59. package/dist/tunnels/client/_runtime.d.ts.map +1 -0
  60. package/dist/tunnels/client/_runtime.js +1679 -0
  61. package/dist/tunnels/client/_runtime.js.map +1 -0
  62. package/dist/tunnels/client/_state.d.ts +45 -0
  63. package/dist/tunnels/client/_state.d.ts.map +1 -0
  64. package/dist/tunnels/client/_state.js +165 -0
  65. package/dist/tunnels/client/_state.js.map +1 -0
  66. package/dist/tunnels/client/_tls.d.ts +50 -0
  67. package/dist/tunnels/client/_tls.d.ts.map +1 -0
  68. package/dist/tunnels/client/_tls.js +139 -0
  69. package/dist/tunnels/client/_tls.js.map +1 -0
  70. package/dist/tunnels/client/_upstream_tls.d.ts +25 -0
  71. package/dist/tunnels/client/_upstream_tls.d.ts.map +1 -0
  72. package/dist/tunnels/client/_upstream_tls.js +24 -0
  73. package/dist/tunnels/client/_upstream_tls.js.map +1 -0
  74. package/dist/tunnels/client/_url_forward.d.ts +92 -0
  75. package/dist/tunnels/client/_url_forward.d.ts.map +1 -0
  76. package/dist/tunnels/client/_url_forward.js +255 -0
  77. package/dist/tunnels/client/_url_forward.js.map +1 -0
  78. package/dist/tunnels/client/_validation.d.ts +27 -0
  79. package/dist/tunnels/client/_validation.d.ts.map +1 -0
  80. package/dist/tunnels/client/_validation.js +96 -0
  81. package/dist/tunnels/client/_validation.js.map +1 -0
  82. package/dist/tunnels/client/_ws.d.ts +149 -0
  83. package/dist/tunnels/client/_ws.d.ts.map +1 -0
  84. package/dist/tunnels/client/_ws.js +351 -0
  85. package/dist/tunnels/client/_ws.js.map +1 -0
  86. package/dist/tunnels/client/_ws_passthrough.d.ts +129 -0
  87. package/dist/tunnels/client/_ws_passthrough.d.ts.map +1 -0
  88. package/dist/tunnels/client/_ws_passthrough.js +432 -0
  89. package/dist/tunnels/client/_ws_passthrough.js.map +1 -0
  90. package/dist/tunnels/client/_ws_url_bridge.d.ts +71 -0
  91. package/dist/tunnels/client/_ws_url_bridge.d.ts.map +1 -0
  92. package/dist/tunnels/client/_ws_url_bridge.js +474 -0
  93. package/dist/tunnels/client/_ws_url_bridge.js.map +1 -0
  94. package/dist/tunnels/client/_ws_url_edge_bridge.d.ts +26 -0
  95. package/dist/tunnels/client/_ws_url_edge_bridge.d.ts.map +1 -0
  96. package/dist/tunnels/client/_ws_url_edge_bridge.js +256 -0
  97. package/dist/tunnels/client/_ws_url_edge_bridge.js.map +1 -0
  98. package/dist/tunnels/client/_wsframe.d.ts +142 -0
  99. package/dist/tunnels/client/_wsframe.d.ts.map +1 -0
  100. package/dist/tunnels/client/_wsframe.js +282 -0
  101. package/dist/tunnels/client/_wsframe.js.map +1 -0
  102. package/dist/tunnels/client/index.d.ts +101 -0
  103. package/dist/tunnels/client/index.d.ts.map +1 -0
  104. package/dist/tunnels/client/index.js +242 -0
  105. package/dist/tunnels/client/index.js.map +1 -0
  106. package/dist/tunnels/exceptions.d.ts +31 -0
  107. package/dist/tunnels/exceptions.d.ts.map +1 -0
  108. package/dist/tunnels/exceptions.js +68 -0
  109. package/dist/tunnels/exceptions.js.map +1 -0
  110. package/dist/tunnels/resources/tunnels.d.ts +73 -0
  111. package/dist/tunnels/resources/tunnels.d.ts.map +1 -0
  112. package/dist/tunnels/resources/tunnels.js +173 -0
  113. package/dist/tunnels/resources/tunnels.js.map +1 -0
  114. package/dist/tunnels/types.d.ts +99 -0
  115. package/dist/tunnels/types.d.ts.map +1 -0
  116. package/dist/tunnels/types.js +76 -0
  117. package/dist/tunnels/types.js.map +1 -0
  118. package/package.json +14 -5
  119. package/protocol/tunnel_protocol_constants.json +65 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * inkbox-tunnels/client/_handler.ts
3
+ *
4
+ * In-process Fetch-API HTTP handler. The user supplies a
5
+ * `(req: Request, ctx: InkboxRequestContext) => Response | Promise<Response>`
6
+ * function; the runtime synthesizes a `Request` from the envelope,
7
+ * invokes the handler, reads the response with the same per-chunk size
8
+ * cap as the URL-forward path, and returns a discriminated union the
9
+ * runtime maps onto fixed on-wire response shapes.
10
+ *
11
+ * Mirrors Python `_asgi.py` semantics at the wire level. The TS-side
12
+ * shape is Web standards (Fetch API) instead of ASGI 3.0.
13
+ */
14
+ import { HOP_BY_HOP_RESPONSE } from "./_protocol.js";
15
+ /**
16
+ * Synthesize a `Request` from the envelope, invoke the handler, read
17
+ * back the response under the size cap.
18
+ */
19
+ export async function dispatchHttpInProcess(opts) {
20
+ const { envelope, handler, publicHost, maxResponseBytes, signal } = opts;
21
+ const url = `https://${publicHost}${envelope.path}`;
22
+ const reqHeaders = new Headers();
23
+ reqHeaders.set("host", publicHost);
24
+ reqHeaders.set("x-forwarded-host", publicHost);
25
+ reqHeaders.set("x-forwarded-proto", "https");
26
+ if (envelope.forwardedForIp !== null) {
27
+ reqHeaders.set("x-forwarded-for", envelope.forwardedForIp);
28
+ reqHeaders.set("forwarded", `for=${envelope.forwardedForIp}`);
29
+ }
30
+ for (const [k, v] of envelope.forwardedHeaders) {
31
+ const kl = k.toLowerCase();
32
+ if (kl === "host" ||
33
+ kl === "x-forwarded-host" ||
34
+ kl === "x-forwarded-proto" ||
35
+ kl === "x-forwarded-for" ||
36
+ kl === "forwarded") {
37
+ continue;
38
+ }
39
+ reqHeaders.append(k, v);
40
+ }
41
+ const reqInit = {
42
+ method: envelope.method,
43
+ headers: reqHeaders,
44
+ body: envelope.method === "GET" || envelope.method === "HEAD"
45
+ ? undefined
46
+ : envelope.body.length > 0
47
+ ? new Uint8Array(envelope.body)
48
+ : undefined,
49
+ signal,
50
+ // Discourage the user from issuing duplex calls when not needed.
51
+ };
52
+ let request;
53
+ try {
54
+ request = new Request(url, reqInit);
55
+ }
56
+ catch {
57
+ return {
58
+ kind: "handler-error",
59
+ status: 502,
60
+ inkboxReason: "handler-error",
61
+ };
62
+ }
63
+ const ctx = {
64
+ signal,
65
+ forwardedForIp: envelope.forwardedForIp,
66
+ sniHost: envelope.sniHost,
67
+ envelope: envelope,
68
+ };
69
+ let response;
70
+ try {
71
+ response = await handler(request, ctx);
72
+ }
73
+ catch {
74
+ return { kind: "handler-error", status: 502, inkboxReason: "handler-error" };
75
+ }
76
+ const headers = [];
77
+ response.headers.forEach((value, key) => {
78
+ if (HOP_BY_HOP_RESPONSE.has(key.toLowerCase()))
79
+ return;
80
+ headers.push([key, value]);
81
+ });
82
+ const reader = response.body?.getReader();
83
+ if (!reader) {
84
+ return {
85
+ kind: "ok",
86
+ status: response.status,
87
+ headers,
88
+ body: Buffer.alloc(0),
89
+ };
90
+ }
91
+ const chunks = [];
92
+ let total = 0;
93
+ try {
94
+ while (true) {
95
+ const { value, done } = await reader.read();
96
+ if (done)
97
+ break;
98
+ const chunk = Buffer.from(value);
99
+ if (total + chunk.length > maxResponseBytes) {
100
+ await reader.cancel().catch(() => undefined);
101
+ return {
102
+ kind: "too-large",
103
+ status: 502,
104
+ inkboxReason: "response-too-large",
105
+ };
106
+ }
107
+ chunks.push(chunk);
108
+ total += chunk.length;
109
+ }
110
+ }
111
+ catch {
112
+ return { kind: "handler-error", status: 502, inkboxReason: "handler-error" };
113
+ }
114
+ return {
115
+ kind: "ok",
116
+ status: response.status,
117
+ headers,
118
+ body: chunks.length === 0 ? Buffer.alloc(0) : Buffer.concat(chunks, total),
119
+ };
120
+ }
121
+ //# sourceMappingURL=_handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_handler.js","sourceRoot":"","sources":["../../../src/tunnels/client/_handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * inkbox-tunnels/client/_listener.ts
3
+ *
4
+ * Public TunnelListener interface and implementation. Drives the
5
+ * {@link TunnelRuntime} to completion; surfaces fatal runtime errors
6
+ * via `wait()`.
7
+ */
8
+ import type { Tunnel } from "../types.js";
9
+ import type { TunnelRuntime } from "./_runtime.js";
10
+ export type TunnelStatusCallback = (status: "connecting" | "connected" | "reconnecting" | "closed") => void;
11
+ /**
12
+ * Options that affect how the listener behaves around process signals.
13
+ *
14
+ * The default mode is `undefined`: the listener installs SIGINT/SIGTERM
15
+ * handlers iff the parent process has none at construction time. Hosts
16
+ * that own their shutdown code should set `installSignalHandlers: false`
17
+ * and call `await listener.aclose()` from their own handler.
18
+ */
19
+ export interface TunnelListenerOpts {
20
+ installSignalHandlers?: boolean;
21
+ }
22
+ /**
23
+ * A live tunnel.
24
+ *
25
+ * Returned by `connect(...)`. Use `await listener.wait()` to block
26
+ * until shutdown, or call `await listener.close()` to drive a clean
27
+ * teardown.
28
+ */
29
+ export interface TunnelListener {
30
+ /** `https://{public_host}`. */
31
+ readonly publicUrl: string;
32
+ /** Snapshot of the resource record taken at bootstrap. Not refreshed. */
33
+ readonly tunnel: Tunnel;
34
+ /** Block until shutdown. Resolves on clean close; throws on fatal. */
35
+ wait(): Promise<void>;
36
+ /** Drive a graceful shutdown. Idempotent. */
37
+ close(): Promise<void>;
38
+ /** Async-friendly alias for `close()`. */
39
+ aclose(): Promise<void>;
40
+ /** Run the runtime to completion. */
41
+ serveForever(): Promise<void>;
42
+ }
43
+ export declare class TunnelListenerImpl implements TunnelListener {
44
+ readonly publicUrl: string;
45
+ readonly tunnel: Tunnel;
46
+ private readonly runtime;
47
+ private servePromise;
48
+ private closed;
49
+ private capturedError;
50
+ private installedSigintHandler;
51
+ private installedSigtermHandler;
52
+ private willExitOnSignal;
53
+ constructor(opts: {
54
+ publicHost: string;
55
+ tunnel: Tunnel;
56
+ runtime: TunnelRuntime;
57
+ listenerOpts?: TunnelListenerOpts;
58
+ });
59
+ serveForever(): Promise<void>;
60
+ wait(): Promise<void>;
61
+ close(): Promise<void>;
62
+ aclose(): Promise<void>;
63
+ }
64
+ //# sourceMappingURL=_listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_listener.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/_listener.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,oBAAoB,GAAG,CACjC,MAAM,EAAE,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,KAC3D,IAAI,CAAC;AAEV;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,0CAA0C;IAC1C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,qCAAqC;IACrC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,sBAAsB,CAA6B;IAC3D,OAAO,CAAC,uBAAuB,CAA6B;IAC5D,OAAO,CAAC,gBAAgB,CAAS;gBAErB,IAAI,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,aAAa,CAAC;QACvB,YAAY,CAAC,EAAE,kBAAkB,CAAC;KACnC;IAkDK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAY7B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB9B"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * inkbox-tunnels/client/_listener.ts
3
+ *
4
+ * Public TunnelListener interface and implementation. Drives the
5
+ * {@link TunnelRuntime} to completion; surfaces fatal runtime errors
6
+ * via `wait()`.
7
+ */
8
+ export class TunnelListenerImpl {
9
+ publicUrl;
10
+ tunnel;
11
+ runtime;
12
+ servePromise = null;
13
+ closed = false;
14
+ capturedError = null;
15
+ installedSigintHandler = null;
16
+ installedSigtermHandler = null;
17
+ willExitOnSignal = false;
18
+ constructor(opts) {
19
+ this.publicUrl = `https://${opts.publicHost}`;
20
+ this.tunnel = opts.tunnel;
21
+ this.runtime = opts.runtime;
22
+ const listenerOpts = opts.listenerOpts ?? {};
23
+ const explicit = listenerOpts.installSignalHandlers;
24
+ let shouldInstall;
25
+ if (explicit === true) {
26
+ const hadHandlers = process.listenerCount("SIGTERM") > 0 ||
27
+ process.listenerCount("SIGINT") > 0;
28
+ if (hadHandlers) {
29
+ // eslint-disable-next-line no-console
30
+ console.warn("TunnelListener: installSignalHandlers=true requested but " +
31
+ "pre-existing SIGTERM/SIGINT handlers are present. The SDK " +
32
+ "handler attaches alongside; both run on signal.");
33
+ }
34
+ shouldInstall = true;
35
+ this.willExitOnSignal = true;
36
+ }
37
+ else if (explicit === false) {
38
+ shouldInstall = false;
39
+ }
40
+ else {
41
+ // Default: install iff none exist at construction time.
42
+ shouldInstall =
43
+ process.listenerCount("SIGTERM") === 0 &&
44
+ process.listenerCount("SIGINT") === 0;
45
+ this.willExitOnSignal = shouldInstall;
46
+ }
47
+ if (shouldInstall) {
48
+ const handler = () => {
49
+ void (async () => {
50
+ try {
51
+ await this.aclose();
52
+ }
53
+ finally {
54
+ if (this.willExitOnSignal) {
55
+ process.exit(0);
56
+ }
57
+ }
58
+ })();
59
+ };
60
+ this.installedSigtermHandler = handler;
61
+ this.installedSigintHandler = handler;
62
+ process.on("SIGTERM", handler);
63
+ process.on("SIGINT", handler);
64
+ }
65
+ }
66
+ async serveForever() {
67
+ if (this.servePromise !== null)
68
+ return this.servePromise;
69
+ this.servePromise = (async () => {
70
+ try {
71
+ await this.runtime.serveForever();
72
+ }
73
+ catch (err) {
74
+ this.capturedError = err;
75
+ }
76
+ })();
77
+ return this.servePromise;
78
+ }
79
+ async wait() {
80
+ await this.serveForever();
81
+ if (this.capturedError !== null) {
82
+ const err = this.capturedError;
83
+ this.capturedError = null;
84
+ throw err;
85
+ }
86
+ }
87
+ async close() {
88
+ return this.aclose();
89
+ }
90
+ async aclose() {
91
+ if (this.closed)
92
+ return;
93
+ this.closed = true;
94
+ await this.runtime.aclose();
95
+ if (this.installedSigtermHandler !== null) {
96
+ process.off("SIGTERM", this.installedSigtermHandler);
97
+ this.installedSigtermHandler = null;
98
+ }
99
+ if (this.installedSigintHandler !== null) {
100
+ process.off("SIGINT", this.installedSigintHandler);
101
+ this.installedSigintHandler = null;
102
+ }
103
+ if (this.servePromise !== null) {
104
+ try {
105
+ await this.servePromise;
106
+ }
107
+ catch {
108
+ /* swallow — captured in capturedError if relevant */
109
+ }
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=_listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_listener.js","sourceRoot":"","sources":["../../../src/tunnels/client/_listener.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * inkbox-tunnels/client/_protocol.ts
3
+ *
4
+ * Single source of truth for the wire protocol in the TS SDK. Mirrors
5
+ * the server-side definitions in `servers/src/data_models/tunnel.py`.
6
+ *
7
+ * The companion manifest at
8
+ * `sdk/typescript/protocol/tunnel_protocol_constants.json` is the
9
+ * cross-SDK forcing function; the contract test in
10
+ * `tests/tunnels/protocol_contract.test.ts` asserts the constants here
11
+ * match it byte-for-byte. When the protocol changes, update both files
12
+ * in lockstep.
13
+ */
14
+ export declare const INKBOX_NAMESPACE_PREFIX: "inkbox-";
15
+ export declare const INKBOX_FORWARDED_HEADER_PREFIX: "inkbox-h-";
16
+ /**
17
+ * The closed set of inkbox-defined meta headers exchanged on the
18
+ * `/_system/intake` and `/_system/response/{id}` streams.
19
+ */
20
+ export declare const TunnelMetaHeader: {
21
+ readonly REQUEST_ID: "inkbox-request-id";
22
+ readonly METHOD: "inkbox-method";
23
+ readonly PATH: "inkbox-path";
24
+ readonly ROUTE_KIND: "inkbox-route-kind";
25
+ readonly STATUS: "inkbox-status";
26
+ readonly WS_ID: "inkbox-ws-id";
27
+ readonly TCP_ID: "inkbox-tcp-id";
28
+ readonly SNI_HOST: "inkbox-sni-host";
29
+ readonly BODY_URI: "inkbox-body-uri";
30
+ readonly FORWARDED_FOR: "inkbox-forwarded-for";
31
+ readonly REASON: "inkbox-reason";
32
+ };
33
+ export type TunnelMetaHeader = (typeof TunnelMetaHeader)[keyof typeof TunnelMetaHeader];
34
+ /** Values for the `inkbox-route-kind` meta header. */
35
+ export declare const TunnelRouteKind: {
36
+ readonly WEBHOOK: "webhook";
37
+ readonly WS_UPGRADE: "ws-upgrade";
38
+ readonly TCP_STREAM: "tcp-stream";
39
+ };
40
+ export type TunnelRouteKind = (typeof TunnelRouteKind)[keyof typeof TunnelRouteKind];
41
+ /** ALPN-style subprotocols negotiated on extended-CONNECT bridge streams. */
42
+ export declare const TunnelSubprotocol: {
43
+ readonly WS: "inkbox-tunnel-ws";
44
+ readonly TCP: "inkbox-tunnel-tcp";
45
+ };
46
+ export type TunnelSubprotocol = (typeof TunnelSubprotocol)[keyof typeof TunnelSubprotocol];
47
+ /** Control-plane HTTP/2 paths exposed by the tunnel server. */
48
+ export declare const ControlPaths: {
49
+ readonly HELLO: "/_system/hello";
50
+ readonly INTAKE: "/_system/intake";
51
+ readonly RESPONSE_PREFIX: "/_system/response/";
52
+ readonly WS_PREFIX: "/_system/ws/";
53
+ readonly TCP_PREFIX: "/_system/tcp/";
54
+ };
55
+ /** SDK-side request headers used on every control-plane stream. */
56
+ export declare const ControlHeaders: {
57
+ readonly TUNNEL_ID: "x-tunnel-id";
58
+ readonly TUNNEL_SECRET: "x-tunnel-secret";
59
+ readonly OWNER_TOKEN: "x-owner-token";
60
+ readonly POOL_SLOT: "x-pool-slot";
61
+ readonly POOL_SIZE: "x-pool-size";
62
+ };
63
+ /** Hop-by-hop request headers stripped before forwarding upstream. */
64
+ export declare const HOP_BY_HOP_REQUEST: ReadonlySet<string>;
65
+ /** Hop-by-hop response headers stripped before forwarding back. */
66
+ export declare const HOP_BY_HOP_RESPONSE: ReadonlySet<string>;
67
+ //# sourceMappingURL=_protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_protocol.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/_protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,uBAAuB,EAAG,SAAkB,CAAC;AAC1D,eAAO,MAAM,8BAA8B,EAAG,WAAoB,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CAYnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAE3D,sDAAsD;AACtD,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AACX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE7D,+DAA+D;AAC/D,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX,mEAAmE;AACnE,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AAEX,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAajD,CAAC;AAEH,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CASlD,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * inkbox-tunnels/client/_protocol.ts
3
+ *
4
+ * Single source of truth for the wire protocol in the TS SDK. Mirrors
5
+ * the server-side definitions in `servers/src/data_models/tunnel.py`.
6
+ *
7
+ * The companion manifest at
8
+ * `sdk/typescript/protocol/tunnel_protocol_constants.json` is the
9
+ * cross-SDK forcing function; the contract test in
10
+ * `tests/tunnels/protocol_contract.test.ts` asserts the constants here
11
+ * match it byte-for-byte. When the protocol changes, update both files
12
+ * in lockstep.
13
+ */
14
+ export const INKBOX_NAMESPACE_PREFIX = "inkbox-";
15
+ export const INKBOX_FORWARDED_HEADER_PREFIX = "inkbox-h-";
16
+ /**
17
+ * The closed set of inkbox-defined meta headers exchanged on the
18
+ * `/_system/intake` and `/_system/response/{id}` streams.
19
+ */
20
+ export const TunnelMetaHeader = {
21
+ REQUEST_ID: "inkbox-request-id",
22
+ METHOD: "inkbox-method",
23
+ PATH: "inkbox-path",
24
+ ROUTE_KIND: "inkbox-route-kind",
25
+ STATUS: "inkbox-status",
26
+ WS_ID: "inkbox-ws-id",
27
+ TCP_ID: "inkbox-tcp-id",
28
+ SNI_HOST: "inkbox-sni-host",
29
+ BODY_URI: "inkbox-body-uri",
30
+ FORWARDED_FOR: "inkbox-forwarded-for",
31
+ REASON: "inkbox-reason",
32
+ };
33
+ /** Values for the `inkbox-route-kind` meta header. */
34
+ export const TunnelRouteKind = {
35
+ WEBHOOK: "webhook",
36
+ WS_UPGRADE: "ws-upgrade",
37
+ TCP_STREAM: "tcp-stream",
38
+ };
39
+ /** ALPN-style subprotocols negotiated on extended-CONNECT bridge streams. */
40
+ export const TunnelSubprotocol = {
41
+ WS: "inkbox-tunnel-ws",
42
+ TCP: "inkbox-tunnel-tcp",
43
+ };
44
+ /** Control-plane HTTP/2 paths exposed by the tunnel server. */
45
+ export const ControlPaths = {
46
+ HELLO: "/_system/hello",
47
+ INTAKE: "/_system/intake",
48
+ RESPONSE_PREFIX: "/_system/response/",
49
+ WS_PREFIX: "/_system/ws/",
50
+ TCP_PREFIX: "/_system/tcp/",
51
+ };
52
+ /** SDK-side request headers used on every control-plane stream. */
53
+ export const ControlHeaders = {
54
+ TUNNEL_ID: "x-tunnel-id",
55
+ TUNNEL_SECRET: "x-tunnel-secret",
56
+ OWNER_TOKEN: "x-owner-token",
57
+ POOL_SLOT: "x-pool-slot",
58
+ POOL_SIZE: "x-pool-size",
59
+ };
60
+ /** Hop-by-hop request headers stripped before forwarding upstream. */
61
+ export const HOP_BY_HOP_REQUEST = new Set([
62
+ "host",
63
+ "connection",
64
+ "upgrade",
65
+ "keep-alive",
66
+ "te",
67
+ "trailer",
68
+ "transfer-encoding",
69
+ "proxy-authenticate",
70
+ "proxy-authorization",
71
+ "sec-websocket-key",
72
+ "sec-websocket-version",
73
+ "sec-websocket-extensions",
74
+ ]);
75
+ /** Hop-by-hop response headers stripped before forwarding back. */
76
+ export const HOP_BY_HOP_RESPONSE = new Set([
77
+ "connection",
78
+ "keep-alive",
79
+ "transfer-encoding",
80
+ "upgrade",
81
+ "proxy-authenticate",
82
+ "proxy-authorization",
83
+ "te",
84
+ "trailer",
85
+ ]);
86
+ //# sourceMappingURL=_protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_protocol.js","sourceRoot":"","sources":["../../../src/tunnels/client/_protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,SAAkB,CAAC;AAC1D,MAAM,CAAC,MAAM,8BAA8B,GAAG,WAAoB,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU,EAAE,mBAAmB;IAC/B,MAAM,EAAE,eAAe;IACvB,IAAI,EAAE,aAAa;IACnB,UAAU,EAAE,mBAAmB;IAC/B,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,cAAc;IACrB,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,QAAQ,EAAE,iBAAiB;IAC3B,aAAa,EAAE,sBAAsB;IACrC,MAAM,EAAE,eAAe;CACf,CAAC;AAIX,sDAAsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;CAChB,CAAC;AAIX,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,EAAE,EAAE,kBAAkB;IACtB,GAAG,EAAE,mBAAmB;CAChB,CAAC;AAIX,+DAA+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,iBAAiB;IACzB,eAAe,EAAE,oBAAoB;IACrC,SAAS,EAAE,cAAc;IACzB,UAAU,EAAE,eAAe;CACnB,CAAC;AAEX,mEAAmE;AACnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS,EAAE,aAAa;IACxB,aAAa,EAAE,iBAAiB;IAChC,WAAW,EAAE,eAAe;IAC5B,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CAChB,CAAC;AAEX,sEAAsE;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,MAAM;IACN,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,IAAI;IACJ,SAAS;IACT,mBAAmB;IACnB,oBAAoB;IACpB,qBAAqB;IACrB,mBAAmB;IACnB,uBAAuB;IACvB,0BAA0B;CAC3B,CAAC,CAAC;AAEH,mEAAmE;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,YAAY;IACZ,YAAY;IACZ,mBAAmB;IACnB,SAAS;IACT,oBAAoB;IACpB,qBAAqB;IACrB,IAAI;IACJ,SAAS;CACV,CAAC,CAAC"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * inkbox-tunnels/client/_runtime.ts
3
+ *
4
+ * The h2 data-plane runtime (Node-only). Maintains one persistent
5
+ * HTTP/2 connection to `https://{zone}/_system/connect`, parks N
6
+ * intake streams, dispatches envelopes (HTTP / WS upgrade / passthrough
7
+ * TCP-stream), and manages flow control + reconnect.
8
+ *
9
+ * Mirrors Python `_runtime.py` at the wire level. The TS-side API
10
+ * shape diverges where Python exposed ASGI 3.0 — we expose Web
11
+ * standards (Fetch API, `InkboxWebSocket`) instead. The on-wire
12
+ * behavior is identical.
13
+ *
14
+ * Flow-control caveat: Node's high-level h2 server auto-credits, so
15
+ * the `awaitWindow` / `markWindowBlocked` / per-stream send-window
16
+ * gate paths are unit-tested only and not exercised through a real h2
17
+ * stack against a real flow-control sequence.
18
+ */
19
+ import * as http2 from "node:http2";
20
+ import type { ClientHttp2Session } from "node:http2";
21
+ import { type InkboxHandler } from "./_handler.js";
22
+ import type { TlsTerminator } from "./_tls.js";
23
+ import { type InkboxWsHandler } from "./_ws.js";
24
+ export declare const PING_INTERVAL_MS = 20000;
25
+ /**
26
+ * Force-reconnect window if a PING goes unacked. Long enough to absorb
27
+ * a slow path's RTT (multi-hop NLB, congested link), short enough that
28
+ * a dead TCP doesn't strand the runtime past the next intake.
29
+ */
30
+ export declare const PING_ACK_TIMEOUT_MS = 10000;
31
+ export declare const BACKOFF_CAP_SEC = 30;
32
+ export declare const BACKOFF_JITTER = 0.25;
33
+ export declare const DEFAULT_INBOUND_BODY_BYTES: number;
34
+ export declare const DEFAULT_OUTBOUND_BODY_BYTES: number;
35
+ export declare class TunnelAuthError extends Error {
36
+ constructor(message: string);
37
+ }
38
+ export type StatusCallback = (status: "connecting" | "connected" | "reconnecting" | "closed") => void;
39
+ /**
40
+ * What this runtime forwards to. URL is required; `httpHandler` and
41
+ * `wsHandler` activate the in-process callable paths.
42
+ */
43
+ export interface DispatchConfig {
44
+ /** Set if the runtime forwards HTTP envelopes to a local URL. */
45
+ forwardTo?: string;
46
+ /** Set if the runtime invokes an in-process Fetch-API handler. */
47
+ httpHandler?: InkboxHandler;
48
+ /** Set if the runtime drives WS-upgrade envelopes through an in-process handler. */
49
+ wsHandler?: InkboxWsHandler;
50
+ }
51
+ export interface TunnelRuntimeOpts {
52
+ tunnelId: string;
53
+ secret: string;
54
+ zone: string;
55
+ publicHost: string;
56
+ poolSize: number | null;
57
+ dispatch: DispatchConfig;
58
+ /**
59
+ * Set when the tunnel is in passthrough TLS mode. The runtime drives
60
+ * the in-process TLS state machine for inbound bridge data and
61
+ * forwards plaintext to `dispatch.forwardTo`.
62
+ */
63
+ tlsTerminator?: TlsTerminator;
64
+ maxInboundBodyBytes?: number;
65
+ maxResponseBytes?: number;
66
+ allowRemoteForwarding?: boolean;
67
+ /** Verify the upstream's TLS cert when `forwardTo` is https://. Default true. */
68
+ forwardToVerifyTls?: boolean;
69
+ /** Extra CA bundle (PEM) to trust for the upstream TLS connection. */
70
+ forwardToCaBundle?: Buffer | string;
71
+ onStatus?: StatusCallback;
72
+ /** Internal injection point for tests; default is `Math.random`. */
73
+ rng?: () => number;
74
+ /** Internal injection point for tests; default is `node:http2` connect. */
75
+ http2Connect?: (authority: string, options: http2.ClientSessionOptions | http2.SecureClientSessionOptions) => ClientHttp2Session;
76
+ }
77
+ /**
78
+ * The data-plane runtime. Construct with the bootstrap-derived
79
+ * tunnelId/secret/zone/publicHost; call `serveForever()` to drive it,
80
+ * `aclose()` to shut down.
81
+ */
82
+ export declare class TunnelRuntime {
83
+ private readonly tunnelId;
84
+ private readonly secret;
85
+ private readonly zone;
86
+ private readonly publicHost;
87
+ private readonly poolSize;
88
+ private readonly dispatch;
89
+ private readonly maxInbound;
90
+ private readonly maxOutbound;
91
+ private readonly tlsTerminator;
92
+ private readonly forwardToVerifyTls;
93
+ private readonly forwardToCaBundle;
94
+ private readonly onStatus?;
95
+ private readonly rng;
96
+ private readonly http2Connect;
97
+ private session;
98
+ private ownerToken;
99
+ private serverPoolSize;
100
+ private intakeIdleSeconds;
101
+ private responseDeadlineSeconds;
102
+ private stop;
103
+ private readonly streams;
104
+ private readonly bridgeStreamIds;
105
+ private readonly tasks;
106
+ private passthroughDispatch;
107
+ private readonly undiciAgentCache;
108
+ private pingHandle;
109
+ private pingAbort;
110
+ private shutdownAbort;
111
+ constructor(opts: TunnelRuntimeOpts);
112
+ /**
113
+ * Drive the runtime forever. Reconnects with jittered exponential
114
+ * backoff; rejects only on permanent auth failure (rotate the
115
+ * secret) or after `aclose()`.
116
+ */
117
+ serveForever(): Promise<void>;
118
+ /** Graceful shutdown. Signals all loops to exit; closes the h2 session. */
119
+ aclose(): Promise<void>;
120
+ private runOnce;
121
+ private openConnection;
122
+ private waitForSessionClose;
123
+ private sendHello;
124
+ private openStream;
125
+ private wake;
126
+ private nextEvent;
127
+ private awaitResponse;
128
+ private intakeLoop;
129
+ private parkOneIntake;
130
+ private startPingLoop;
131
+ private stopPingLoop;
132
+ private dispatchEnvelope;
133
+ private dispatchHttp;
134
+ private materializeBody;
135
+ private dispatchWsUpgrade;
136
+ private dispatchWsUpgradeToUrl;
137
+ private openWsBridge;
138
+ private dispatchTcpStream;
139
+ private writeBridgeFrame;
140
+ private postResponse;
141
+ private notifyStatus;
142
+ }
143
+ //# sourceMappingURL=_runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_runtime.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/_runtime.ts"],"names":[],"mappings":"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"}