@inkbox/sdk 0.2.15 → 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 (135) 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/agent_identity.d.ts +20 -0
  7. package/dist/agent_identity.d.ts.map +1 -1
  8. package/dist/agent_identity.js +17 -0
  9. package/dist/agent_identity.js.map +1 -1
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/inkbox.d.ts +4 -0
  15. package/dist/inkbox.d.ts.map +1 -1
  16. package/dist/inkbox.js +5 -0
  17. package/dist/inkbox.js.map +1 -1
  18. package/dist/phone/resources/calls.d.ts +8 -0
  19. package/dist/phone/resources/calls.d.ts.map +1 -1
  20. package/dist/phone/resources/calls.js +15 -1
  21. package/dist/phone/resources/calls.js.map +1 -1
  22. package/dist/phone/resources/texts.d.ts +26 -0
  23. package/dist/phone/resources/texts.d.ts.map +1 -1
  24. package/dist/phone/resources/texts.js +42 -2
  25. package/dist/phone/resources/texts.js.map +1 -1
  26. package/dist/phone/types.d.ts +18 -0
  27. package/dist/phone/types.d.ts.map +1 -1
  28. package/dist/phone/types.js +2 -0
  29. package/dist/phone/types.js.map +1 -1
  30. package/dist/tunnels/_validation.d.ts +7 -0
  31. package/dist/tunnels/_validation.d.ts.map +1 -0
  32. package/dist/tunnels/_validation.js +27 -0
  33. package/dist/tunnels/_validation.js.map +1 -0
  34. package/dist/tunnels/client/_bridge.d.ts +35 -0
  35. package/dist/tunnels/client/_bridge.d.ts.map +1 -0
  36. package/dist/tunnels/client/_bridge.js +52 -0
  37. package/dist/tunnels/client/_bridge.js.map +1 -0
  38. package/dist/tunnels/client/_callable_streaming.d.ts +25 -0
  39. package/dist/tunnels/client/_callable_streaming.d.ts.map +1 -0
  40. package/dist/tunnels/client/_callable_streaming.js +158 -0
  41. package/dist/tunnels/client/_callable_streaming.js.map +1 -0
  42. package/dist/tunnels/client/_cert.d.ts +45 -0
  43. package/dist/tunnels/client/_cert.d.ts.map +1 -0
  44. package/dist/tunnels/client/_cert.js +193 -0
  45. package/dist/tunnels/client/_cert.js.map +1 -0
  46. package/dist/tunnels/client/_dispatch.d.ts +109 -0
  47. package/dist/tunnels/client/_dispatch.d.ts.map +1 -0
  48. package/dist/tunnels/client/_dispatch.js +314 -0
  49. package/dist/tunnels/client/_dispatch.js.map +1 -0
  50. package/dist/tunnels/client/_envelope.d.ts +55 -0
  51. package/dist/tunnels/client/_envelope.d.ts.map +1 -0
  52. package/dist/tunnels/client/_envelope.js +97 -0
  53. package/dist/tunnels/client/_envelope.js.map +1 -0
  54. package/dist/tunnels/client/_h1_server.d.ts +37 -0
  55. package/dist/tunnels/client/_h1_server.d.ts.map +1 -0
  56. package/dist/tunnels/client/_h1_server.js +433 -0
  57. package/dist/tunnels/client/_h1_server.js.map +1 -0
  58. package/dist/tunnels/client/_h2_transcode.d.ts +43 -0
  59. package/dist/tunnels/client/_h2_transcode.d.ts.map +1 -0
  60. package/dist/tunnels/client/_h2_transcode.js +488 -0
  61. package/dist/tunnels/client/_h2_transcode.js.map +1 -0
  62. package/dist/tunnels/client/_handler.d.ts +62 -0
  63. package/dist/tunnels/client/_handler.d.ts.map +1 -0
  64. package/dist/tunnels/client/_handler.js +121 -0
  65. package/dist/tunnels/client/_handler.js.map +1 -0
  66. package/dist/tunnels/client/_listener.d.ts +64 -0
  67. package/dist/tunnels/client/_listener.d.ts.map +1 -0
  68. package/dist/tunnels/client/_listener.js +113 -0
  69. package/dist/tunnels/client/_listener.js.map +1 -0
  70. package/dist/tunnels/client/_protocol.d.ts +67 -0
  71. package/dist/tunnels/client/_protocol.d.ts.map +1 -0
  72. package/dist/tunnels/client/_protocol.js +86 -0
  73. package/dist/tunnels/client/_protocol.js.map +1 -0
  74. package/dist/tunnels/client/_runtime.d.ts +143 -0
  75. package/dist/tunnels/client/_runtime.d.ts.map +1 -0
  76. package/dist/tunnels/client/_runtime.js +1679 -0
  77. package/dist/tunnels/client/_runtime.js.map +1 -0
  78. package/dist/tunnels/client/_state.d.ts +45 -0
  79. package/dist/tunnels/client/_state.d.ts.map +1 -0
  80. package/dist/tunnels/client/_state.js +165 -0
  81. package/dist/tunnels/client/_state.js.map +1 -0
  82. package/dist/tunnels/client/_tls.d.ts +50 -0
  83. package/dist/tunnels/client/_tls.d.ts.map +1 -0
  84. package/dist/tunnels/client/_tls.js +139 -0
  85. package/dist/tunnels/client/_tls.js.map +1 -0
  86. package/dist/tunnels/client/_upstream_tls.d.ts +25 -0
  87. package/dist/tunnels/client/_upstream_tls.d.ts.map +1 -0
  88. package/dist/tunnels/client/_upstream_tls.js +24 -0
  89. package/dist/tunnels/client/_upstream_tls.js.map +1 -0
  90. package/dist/tunnels/client/_url_forward.d.ts +92 -0
  91. package/dist/tunnels/client/_url_forward.d.ts.map +1 -0
  92. package/dist/tunnels/client/_url_forward.js +255 -0
  93. package/dist/tunnels/client/_url_forward.js.map +1 -0
  94. package/dist/tunnels/client/_validation.d.ts +27 -0
  95. package/dist/tunnels/client/_validation.d.ts.map +1 -0
  96. package/dist/tunnels/client/_validation.js +96 -0
  97. package/dist/tunnels/client/_validation.js.map +1 -0
  98. package/dist/tunnels/client/_ws.d.ts +149 -0
  99. package/dist/tunnels/client/_ws.d.ts.map +1 -0
  100. package/dist/tunnels/client/_ws.js +351 -0
  101. package/dist/tunnels/client/_ws.js.map +1 -0
  102. package/dist/tunnels/client/_ws_passthrough.d.ts +129 -0
  103. package/dist/tunnels/client/_ws_passthrough.d.ts.map +1 -0
  104. package/dist/tunnels/client/_ws_passthrough.js +432 -0
  105. package/dist/tunnels/client/_ws_passthrough.js.map +1 -0
  106. package/dist/tunnels/client/_ws_url_bridge.d.ts +71 -0
  107. package/dist/tunnels/client/_ws_url_bridge.d.ts.map +1 -0
  108. package/dist/tunnels/client/_ws_url_bridge.js +474 -0
  109. package/dist/tunnels/client/_ws_url_bridge.js.map +1 -0
  110. package/dist/tunnels/client/_ws_url_edge_bridge.d.ts +26 -0
  111. package/dist/tunnels/client/_ws_url_edge_bridge.d.ts.map +1 -0
  112. package/dist/tunnels/client/_ws_url_edge_bridge.js +256 -0
  113. package/dist/tunnels/client/_ws_url_edge_bridge.js.map +1 -0
  114. package/dist/tunnels/client/_wsframe.d.ts +142 -0
  115. package/dist/tunnels/client/_wsframe.d.ts.map +1 -0
  116. package/dist/tunnels/client/_wsframe.js +282 -0
  117. package/dist/tunnels/client/_wsframe.js.map +1 -0
  118. package/dist/tunnels/client/index.d.ts +101 -0
  119. package/dist/tunnels/client/index.d.ts.map +1 -0
  120. package/dist/tunnels/client/index.js +242 -0
  121. package/dist/tunnels/client/index.js.map +1 -0
  122. package/dist/tunnels/exceptions.d.ts +31 -0
  123. package/dist/tunnels/exceptions.d.ts.map +1 -0
  124. package/dist/tunnels/exceptions.js +68 -0
  125. package/dist/tunnels/exceptions.js.map +1 -0
  126. package/dist/tunnels/resources/tunnels.d.ts +73 -0
  127. package/dist/tunnels/resources/tunnels.d.ts.map +1 -0
  128. package/dist/tunnels/resources/tunnels.js +173 -0
  129. package/dist/tunnels/resources/tunnels.js.map +1 -0
  130. package/dist/tunnels/types.d.ts +99 -0
  131. package/dist/tunnels/types.d.ts.map +1 -0
  132. package/dist/tunnels/types.js +76 -0
  133. package/dist/tunnels/types.js.map +1 -0
  134. package/package.json +14 -5
  135. package/protocol/tunnel_protocol_constants.json +65 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * inkbox-tunnels/client/_wsframe.ts
3
+ *
4
+ * RFC 6455 WebSocket frame codec, plus the length-prefixed JSON envelope
5
+ * format the WS-bridge stream carries.
6
+ *
7
+ * Pure / synchronous; no I/O. Used by both the WS upgrade bridge and
8
+ * the passthrough TCP bridge (which tunnels raw bytes inside WS BINARY
9
+ * frames on an extended-CONNECT stream).
10
+ *
11
+ * ## Statefulness — the decoder MUST accumulate across calls
12
+ *
13
+ * A single h2 DATA frame can carry zero, one, many, or partial WS
14
+ * frames; a single WS frame (with extended length) can span multiple
15
+ * DATA boundaries. Use {@link WsFrameDecoder.feed} which retains a
16
+ * carry buffer between calls. Do not implement
17
+ * one-frame-per-DATA-callback in callers.
18
+ *
19
+ * ## Partial-bytes-at-EOF policy (M3 T0 — matches Python)
20
+ *
21
+ * If the bridge stream ends ("end" or "reset" h2 event) while the carry
22
+ * buffer still contains a partial WS frame, the policy is:
23
+ * **drop the trailing bytes silently and close the WS session.**
24
+ * No RST_STREAM. No error surfaced to the user.
25
+ *
26
+ * Verified against Python `_runtime.py` (`_pump_ws`): on a stream-end /
27
+ * stream-reset event, `recv_done` is set and the loop exits, abandoning
28
+ * `wire_buf` and `env_buf` without any cleanup write. The TS port
29
+ * mirrors that exactly.
30
+ */
31
+ import { randomBytes } from "node:crypto";
32
+ export const WS_OPCODE_CONTINUATION = 0x0;
33
+ export const WS_OPCODE_TEXT = 0x1;
34
+ export const WS_OPCODE_BINARY = 0x2;
35
+ export const WS_OPCODE_CLOSE = 0x8;
36
+ export const WS_OPCODE_PING = 0x9;
37
+ export const WS_OPCODE_PONG = 0xa;
38
+ /**
39
+ * Stateful WS frame decoder. Hold one per bridge stream; call
40
+ * {@link feed} as h2 DATA chunks arrive.
41
+ */
42
+ export class WsFrameDecoder {
43
+ buf = Buffer.alloc(0);
44
+ /**
45
+ * Feed a chunk of wire bytes; return any newly-decodable frames.
46
+ * Trailing partial bytes stay in the carry buffer for the next call.
47
+ */
48
+ feed(chunk) {
49
+ if (chunk.length > 0) {
50
+ this.buf = this.buf.length === 0 ? chunk : Buffer.concat([this.buf, chunk]);
51
+ }
52
+ const frames = [];
53
+ let cursor = 0;
54
+ while (true) {
55
+ const remaining = this.buf.length - cursor;
56
+ if (remaining < 2)
57
+ break;
58
+ const b0 = this.buf[cursor];
59
+ const b1 = this.buf[cursor + 1];
60
+ const fin = (b0 & 0x80) !== 0;
61
+ const opcode = b0 & 0x0f;
62
+ const masked = (b1 & 0x80) !== 0;
63
+ let plen = b1 & 0x7f;
64
+ let offset = 2;
65
+ if (plen === 126) {
66
+ if (remaining < 4)
67
+ break;
68
+ plen = this.buf.readUInt16BE(cursor + 2);
69
+ offset = 4;
70
+ }
71
+ else if (plen === 127) {
72
+ if (remaining < 10)
73
+ break;
74
+ const high = this.buf.readUInt32BE(cursor + 2);
75
+ const low = this.buf.readUInt32BE(cursor + 6);
76
+ // JS-safe range: < 2^53. The bridge cap is well below that.
77
+ plen = high * 0x1_0000_0000 + low;
78
+ offset = 10;
79
+ }
80
+ let maskKey = null;
81
+ if (masked) {
82
+ if (remaining < offset + 4)
83
+ break;
84
+ maskKey = this.buf.subarray(cursor + offset, cursor + offset + 4);
85
+ offset += 4;
86
+ }
87
+ if (remaining < offset + plen)
88
+ break;
89
+ let payload = Buffer.from(this.buf.subarray(cursor + offset, cursor + offset + plen));
90
+ if (masked && maskKey) {
91
+ for (let i = 0; i < payload.length; i++) {
92
+ payload[i] = payload[i] ^ maskKey[i % 4];
93
+ }
94
+ }
95
+ frames.push({ opcode, payload, fin });
96
+ cursor += offset + plen;
97
+ }
98
+ if (cursor > 0) {
99
+ this.buf = cursor === this.buf.length
100
+ ? Buffer.alloc(0)
101
+ : Buffer.from(this.buf.subarray(cursor));
102
+ }
103
+ return frames;
104
+ }
105
+ /** True iff there are partial bytes still in the carry buffer. */
106
+ hasPartial() {
107
+ return this.buf.length > 0;
108
+ }
109
+ /** Bytes currently buffered (test-only inspection). */
110
+ partialBytes() {
111
+ return this.buf.length;
112
+ }
113
+ }
114
+ /**
115
+ * Encode a single WS frame. ``mask=true`` is required for
116
+ * client→server traffic per RFC 6455.
117
+ */
118
+ export function encodeWsFrame(opcode, payload, options = {}) {
119
+ const mask = options.mask !== false;
120
+ const fin = options.fin !== false;
121
+ const plen = payload.length;
122
+ let headerLen = 2;
123
+ if (plen >= 126 && plen < 65536)
124
+ headerLen = 4;
125
+ else if (plen >= 65536)
126
+ headerLen = 10;
127
+ if (mask)
128
+ headerLen += 4;
129
+ const out = Buffer.alloc(headerLen + plen);
130
+ out[0] = (fin ? 0x80 : 0x00) | (opcode & 0x0f);
131
+ const maskBit = mask ? 0x80 : 0x00;
132
+ let off = 2;
133
+ if (plen < 126) {
134
+ out[1] = maskBit | plen;
135
+ }
136
+ else if (plen < 65536) {
137
+ out[1] = maskBit | 126;
138
+ out.writeUInt16BE(plen, 2);
139
+ off = 4;
140
+ }
141
+ else {
142
+ out[1] = maskBit | 127;
143
+ const high = Math.floor(plen / 0x1_0000_0000);
144
+ const low = plen % 0x1_0000_0000;
145
+ out.writeUInt32BE(high, 2);
146
+ out.writeUInt32BE(low, 6);
147
+ off = 10;
148
+ }
149
+ if (mask) {
150
+ const maskKey = randomBytes(4);
151
+ maskKey.copy(out, off);
152
+ for (let i = 0; i < plen; i++) {
153
+ out[off + 4 + i] = payload[i] ^ maskKey[i % 4];
154
+ }
155
+ }
156
+ else {
157
+ payload.copy(out, off);
158
+ }
159
+ return out;
160
+ }
161
+ export function encodeWsEnvelope(msg) {
162
+ let wire;
163
+ if (msg.type === "websocket.send") {
164
+ if ("text" in msg && msg.text !== undefined) {
165
+ wire = { type: "text", data: msg.text };
166
+ }
167
+ else if ("bytes" in msg && msg.bytes !== undefined) {
168
+ wire = { type: "binary", data: msg.bytes.toString("base64") };
169
+ }
170
+ else {
171
+ wire = { type: "text", data: "" };
172
+ }
173
+ }
174
+ else if (msg.type === "websocket.close") {
175
+ wire = {
176
+ type: "close",
177
+ code: msg.code ?? 1000,
178
+ reason: msg.reason ?? "",
179
+ };
180
+ }
181
+ else {
182
+ wire = { type: "text", data: "" };
183
+ }
184
+ const json = Buffer.from(JSON.stringify(wire), "utf-8");
185
+ const out = Buffer.alloc(4 + json.length);
186
+ out.writeUInt32BE(json.length, 0);
187
+ json.copy(out, 4);
188
+ return out;
189
+ }
190
+ /**
191
+ * Length-prefixed-JSON envelope decoder. Stateful — call repeatedly
192
+ * with concatenated WS-frame payloads, get back fully-formed envelopes
193
+ * as they emerge.
194
+ *
195
+ * Binary envelopes have their `data` field strictly base64-validated
196
+ * (per the server contract). Malformed base64 is logged and dropped —
197
+ * the empty result is what the runtime delivers, mirroring Python's
198
+ * `_ws.py` behavior at the validate=True boundary.
199
+ */
200
+ export class WsEnvelopeDecoder {
201
+ buf = Buffer.alloc(0);
202
+ feed(chunk) {
203
+ if (chunk.length > 0) {
204
+ this.buf = this.buf.length === 0 ? chunk : Buffer.concat([this.buf, chunk]);
205
+ }
206
+ const out = [];
207
+ let cursor = 0;
208
+ while (this.buf.length - cursor >= 4) {
209
+ const length = this.buf.readUInt32BE(cursor);
210
+ if (this.buf.length - cursor - 4 < length)
211
+ break;
212
+ const payload = this.buf.subarray(cursor + 4, cursor + 4 + length);
213
+ cursor += 4 + length;
214
+ let parsed;
215
+ try {
216
+ parsed = JSON.parse(payload.toString("utf-8"));
217
+ }
218
+ catch {
219
+ continue;
220
+ }
221
+ const decoded = decodeOneEnvelope(parsed);
222
+ if (decoded !== null)
223
+ out.push(decoded);
224
+ }
225
+ if (cursor > 0) {
226
+ this.buf = cursor === this.buf.length
227
+ ? Buffer.alloc(0)
228
+ : Buffer.from(this.buf.subarray(cursor));
229
+ }
230
+ return out;
231
+ }
232
+ hasPartial() {
233
+ return this.buf.length > 0;
234
+ }
235
+ }
236
+ function decodeOneEnvelope(parsed) {
237
+ if (parsed.type === "text") {
238
+ return { type: "text", data: typeof parsed.data === "string" ? parsed.data : "" };
239
+ }
240
+ if (parsed.type === "binary") {
241
+ if (typeof parsed.data !== "string")
242
+ return null;
243
+ const decoded = decodeStrictBase64(parsed.data);
244
+ if (decoded === null)
245
+ return null;
246
+ return { type: "binary", data: decoded };
247
+ }
248
+ if (parsed.type === "close") {
249
+ return {
250
+ type: "close",
251
+ code: typeof parsed.code === "number" ? parsed.code : 1000,
252
+ reason: typeof parsed.reason === "string" ? parsed.reason : "",
253
+ };
254
+ }
255
+ return null;
256
+ }
257
+ /**
258
+ * Strict base64 decode: rejects non-base64 characters, requires
259
+ * padding. Mirrors Python `base64.b64decode(..., validate=True)`.
260
+ *
261
+ * Node's `Buffer.from(s, "base64")` is permissive (silently strips
262
+ * non-base64 chars and tolerates missing padding). We need the strict
263
+ * shape to match the server's outbound encoding exactly — otherwise a
264
+ * garbage `"@@@@"` decodes to an empty Buffer the user's app would
265
+ * mistake for a real binary message.
266
+ */
267
+ function decodeStrictBase64(s) {
268
+ if (s.length === 0)
269
+ return Buffer.alloc(0);
270
+ if (s.length % 4 !== 0)
271
+ return null;
272
+ if (!/^[A-Za-z0-9+/]+={0,2}$/.test(s))
273
+ return null;
274
+ const decoded = Buffer.from(s, "base64");
275
+ // Round-trip: re-encode and compare. Catches edge cases the regex
276
+ // above lets through (Node's Buffer is still tolerant of some inputs).
277
+ if (decoded.toString("base64") !== s)
278
+ return null;
279
+ return decoded;
280
+ }
281
+ export const __testing = { decodeStrictBase64 };
282
+ //# sourceMappingURL=_wsframe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_wsframe.js","sourceRoot":"","sources":["../../../src/tunnels/client/_wsframe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @inkbox/sdk/tunnels/connect — Node-only data-plane runtime.
3
+ *
4
+ * Imported as:
5
+ *
6
+ * ```ts
7
+ * import { connect } from "@inkbox/sdk/tunnels/connect";
8
+ * ```
9
+ *
10
+ * This subpath pulls in `node:http2`, `node:tls`, `node:fs`, and
11
+ * `node:os`, so it is NOT browser-safe. The main package entry
12
+ * (`@inkbox/sdk`) stays browser-safe; only this subpath gates on Node.
13
+ */
14
+ import type { Inkbox } from "../../inkbox.js";
15
+ import { TLSMode } from "../types.js";
16
+ import { type TunnelListener, type TunnelStatusCallback } from "./_listener.js";
17
+ import type { InkboxHandler } from "./_handler.js";
18
+ import type { InkboxWsHandler } from "./_ws.js";
19
+ export type { TunnelListener, TunnelStatusCallback } from "./_listener.js";
20
+ export { ForwardTargetRefused, validateEnvelopePath, validateForwardTarget, } from "./_validation.js";
21
+ export type { InkboxHandler, InkboxRequestContext } from "./_handler.js";
22
+ export type { InkboxWebSocket, InkboxWebSocketAcceptOpts, InkboxWsHandler, } from "./_ws.js";
23
+ export { WsAcceptDeadlineExceeded, WsClosed, WsProtocolMismatch, } from "./_ws.js";
24
+ export { TunnelAuthError } from "./_runtime.js";
25
+ /** Default tunnel zone — used when neither the server nor the state file specifies one. */
26
+ export declare const PROD_ZONE = "inkboxwire.com";
27
+ /**
28
+ * Raised by `connect()` when the supplied dispatch options are
29
+ * invalid — for example, both `forwardTo` and `handler` set, or
30
+ * `wsHandler` set without an HTTP path.
31
+ *
32
+ * Validation runs synchronously before any control-plane writes: a
33
+ * tunnel is never created or restored for an invalid configuration.
34
+ */
35
+ export declare class InvalidConnectOptions extends Error {
36
+ constructor(message: string);
37
+ }
38
+ export interface ConnectOptions {
39
+ /** Tunnel name (server-side `tunnel_name`). */
40
+ name: string;
41
+ /** URL forward path: forward inbound HTTP traffic to a local URL. */
42
+ forwardTo?: string;
43
+ /** In-process Fetch-API HTTP handler. Mutually exclusive with `forwardTo`. */
44
+ handler?: InkboxHandler;
45
+ /** In-process WS handler. Optional alongside an HTTP path. */
46
+ wsHandler?: InkboxWsHandler;
47
+ /** Expert-only override for the data-plane h2 endpoint. */
48
+ dataPlaneZone?: string;
49
+ /** `"edge"` (default) or `"passthrough"`. */
50
+ tlsMode?: TLSMode | "edge" | "passthrough";
51
+ /** Where state.json (and passthrough key/cert) live. */
52
+ stateDir?: string;
53
+ /** Free-form description, recorded server-side at create time. */
54
+ description?: string;
55
+ /** 1-32; omit to let the server decide. */
56
+ poolSize?: number;
57
+ /** Explicit override; wins over the state file. */
58
+ secret?: string;
59
+ /** Status transitions. */
60
+ onStatus?: TunnelStatusCallback;
61
+ /** `"auto_restore"` (default) or `"error"`. */
62
+ onPendingRemoval?: "auto_restore" | "error";
63
+ /** Cap on materialized inbound bodies. */
64
+ maxInboundBodyBytes?: number;
65
+ /**
66
+ * Cap on materialized outbound (response) bodies. Threaded into both
67
+ * the URL-forward and in-process-handler paths as the same value;
68
+ * different names imply different policies and confuse users.
69
+ */
70
+ maxResponseBytes?: number;
71
+ /** Bypass the loopback-only allowlist for `forwardTo`. */
72
+ allowRemoteForwarding?: boolean;
73
+ /** TTY-gated by default. */
74
+ printSecretToStderr?: boolean | null;
75
+ /** Signal-handler installation policy. */
76
+ installSignalHandlers?: boolean;
77
+ /**
78
+ * Default `true`. When `false`, passthrough advertises only
79
+ * `http/1.1` in ALPN — the h1 parser still handles inbound traffic
80
+ * uniformly (caps, validation, header injection). This is an
81
+ * ALPN-only escape hatch; the raw byte-pipe is gone.
82
+ */
83
+ enableH2Transcode?: boolean;
84
+ /**
85
+ * Verify the upstream's TLS certificate when `forwardTo` is `https://`.
86
+ * Default `true`. Set `false` for self-signed dev certs on loopback;
87
+ * pair with `forwardToCaBundle` for private CAs.
88
+ */
89
+ forwardToVerifyTls?: boolean;
90
+ /**
91
+ * Extra CA certificate(s) (PEM) to trust when verifying the upstream
92
+ * TLS certificate. Mutually exclusive with `forwardToVerifyTls=false`
93
+ * for sanity.
94
+ */
95
+ forwardToCaBundle?: Buffer | string;
96
+ }
97
+ /**
98
+ * Bring a tunnel online from this Node process.
99
+ */
100
+ export declare function connect(inkbox: Inkbox, options: ConnectOptions): Promise<TunnelListener>;
101
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAQ9C,OAAO,EAAE,OAAO,EAAwB,MAAM,aAAa,CAAC;AAa5D,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,eAAe,GAChB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,wBAAwB,EACxB,QAAQ,EACR,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAE1C;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;IAC3C,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAC5C,0CAA0C;IAC1C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,4BAA4B;IAC5B,mBAAmB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,0CAA0C;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACrC;AA0DD;;GAEG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAyLzB"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * @inkbox/sdk/tunnels/connect — Node-only data-plane runtime.
3
+ *
4
+ * Imported as:
5
+ *
6
+ * ```ts
7
+ * import { connect } from "@inkbox/sdk/tunnels/connect";
8
+ * ```
9
+ *
10
+ * This subpath pulls in `node:http2`, `node:tls`, `node:fs`, and
11
+ * `node:os`, so it is NOT browser-safe. The main package entry
12
+ * (`@inkbox/sdk`) stays browser-safe; only this subpath gates on Node.
13
+ */
14
+ import { POOL_SIZE_MAX, POOL_SIZE_MIN } from "../resources/tunnels.js";
15
+ import { TunnelRemoved, TunnelSecretUnavailable, TunnelStateConflict, } from "../exceptions.js";
16
+ import { validateTunnelName } from "../_validation.js";
17
+ import { TLSMode, TunnelStatus } from "../types.js";
18
+ import { validateForwardTarget, } from "./_validation.js";
19
+ import { defaultStateDir, ensurePrivateStateDir, loadState, printSecretOnce, saveState, } from "./_state.js";
20
+ import { TunnelListenerImpl, } from "./_listener.js";
21
+ import { DEFAULT_INBOUND_BODY_BYTES, DEFAULT_OUTBOUND_BODY_BYTES, TunnelRuntime, } from "./_runtime.js";
22
+ export { ForwardTargetRefused, validateEnvelopePath, validateForwardTarget, } from "./_validation.js";
23
+ export { WsAcceptDeadlineExceeded, WsClosed, WsProtocolMismatch, } from "./_ws.js";
24
+ export { TunnelAuthError } from "./_runtime.js";
25
+ /** Default tunnel zone — used when neither the server nor the state file specifies one. */
26
+ export const PROD_ZONE = "inkboxwire.com";
27
+ /**
28
+ * Raised by `connect()` when the supplied dispatch options are
29
+ * invalid — for example, both `forwardTo` and `handler` set, or
30
+ * `wsHandler` set without an HTTP path.
31
+ *
32
+ * Validation runs synchronously before any control-plane writes: a
33
+ * tunnel is never created or restored for an invalid configuration.
34
+ */
35
+ export class InvalidConnectOptions extends Error {
36
+ constructor(message) {
37
+ super(message);
38
+ this.name = "InvalidConnectOptions";
39
+ }
40
+ }
41
+ function validatePoolSize(poolSize) {
42
+ if (poolSize === undefined)
43
+ return;
44
+ if (!Number.isInteger(poolSize) ||
45
+ poolSize < POOL_SIZE_MIN ||
46
+ poolSize > POOL_SIZE_MAX) {
47
+ throw new RangeError(`poolSize must be an integer in [${POOL_SIZE_MIN}, ${POOL_SIZE_MAX}] (got ${poolSize})`);
48
+ }
49
+ }
50
+ /**
51
+ * Validate the `connect()` dispatch matrix synchronously, before any
52
+ * control-plane writes. The runtime never has to handle the ambiguous
53
+ * combinations because they can't reach it.
54
+ */
55
+ function validateDispatchOptions(opts) {
56
+ const hasForward = opts.forwardTo !== undefined;
57
+ const hasHandler = opts.handler !== undefined;
58
+ const hasWs = opts.wsHandler !== undefined;
59
+ if (hasForward && hasHandler) {
60
+ throw new InvalidConnectOptions("ambiguous HTTP path: both forwardTo and handler are set; pick one.");
61
+ }
62
+ if (!hasForward && !hasHandler && !hasWs) {
63
+ throw new InvalidConnectOptions("no dispatch path configured: pass forwardTo, handler, or wsHandler.");
64
+ }
65
+ if (!hasForward && !hasHandler && hasWs) {
66
+ throw new InvalidConnectOptions("wsHandler set without an HTTP path: pass forwardTo or handler too.");
67
+ }
68
+ }
69
+ function resolveZoneAndHost(opts) {
70
+ const publicHost = opts.serverPublicHost ?? opts.state?.publicHost ?? `${opts.name}.${PROD_ZONE}`;
71
+ const zone = opts.dataPlaneZoneOverride ??
72
+ opts.serverZone ??
73
+ opts.state?.zone ??
74
+ PROD_ZONE;
75
+ return { zone, publicHost };
76
+ }
77
+ /**
78
+ * Bring a tunnel online from this Node process.
79
+ */
80
+ export async function connect(inkbox, options) {
81
+ // --- Synchronous validation (cheap; runs before any disk or server I/O) ---
82
+ validateTunnelName(options.name);
83
+ validatePoolSize(options.poolSize);
84
+ validateDispatchOptions(options);
85
+ if (options.forwardTo !== undefined) {
86
+ validateForwardTarget(options.forwardTo, {
87
+ allowRemoteForwarding: options.allowRemoteForwarding,
88
+ });
89
+ }
90
+ const tlsMode = (typeof options.tlsMode === "string"
91
+ ? options.tlsMode
92
+ : options.tlsMode) ?? TLSMode.EDGE;
93
+ // Passthrough accepts both http:// and https:// forwardTo URLs.
94
+ // UpstreamUrlDispatch builds undici's tls.connect options from
95
+ // forwardToVerifyTls / forwardToCaBundle for https:// upstreams.
96
+ const onPendingRemoval = options.onPendingRemoval ?? "auto_restore";
97
+ const stateDirPath = options.stateDir ?? defaultStateDir(options.name);
98
+ ensurePrivateStateDir(stateDirPath);
99
+ const state = loadState(stateDirPath);
100
+ let secret = options.secret ?? state?.secret ?? null;
101
+ let tunnel = null;
102
+ if (state?.tunnelId) {
103
+ try {
104
+ tunnel = await inkbox.tunnels.get(state.tunnelId);
105
+ }
106
+ catch (err) {
107
+ const apiErr = err;
108
+ if (apiErr?.statusCode === 404) {
109
+ throw new TunnelRemoved(`tunnel ${options.name} (id=${state.tunnelId}) has been removed; ` +
110
+ `clear ${stateDirPath} and call inkbox.tunnels.create() to start fresh`);
111
+ }
112
+ throw err;
113
+ }
114
+ }
115
+ if (!tunnel) {
116
+ const list = await inkbox.tunnels.list();
117
+ tunnel = list.find((t) => t.tunnelName === options.name) ?? null;
118
+ }
119
+ if (!tunnel) {
120
+ const created = await inkbox.tunnels.create({
121
+ tunnelName: options.name,
122
+ tlsMode,
123
+ description: options.description,
124
+ });
125
+ tunnel = created.tunnel;
126
+ secret = created.connectSecret;
127
+ saveState(stateDirPath, {
128
+ tunnelId: tunnel.id,
129
+ name: options.name,
130
+ secret,
131
+ mode: tlsMode,
132
+ zone: tunnel.zone,
133
+ publicHost: tunnel.publicHost,
134
+ });
135
+ printSecretOnce({
136
+ secret,
137
+ statePath: `${stateDirPath}/state.json`,
138
+ printToStderr: options.printSecretToStderr ?? null,
139
+ });
140
+ }
141
+ else {
142
+ if (tunnel.tlsMode !== tlsMode) {
143
+ throw new TunnelStateConflict(409, `tls_mode mismatch: requested ${tlsMode} but tunnel reports ${tunnel.tlsMode}. ` +
144
+ "tls_mode is fixed at creation; delete the tunnel and recreate to change it.");
145
+ }
146
+ if (tunnel.status === TunnelStatus.PENDING_REMOVAL) {
147
+ if (onPendingRemoval === "error") {
148
+ throw new TunnelStateConflict(409, `tunnel ${options.name} is in pending_removal; pass ` +
149
+ "onPendingRemoval: 'auto_restore' to bring it back");
150
+ }
151
+ if (!secret) {
152
+ throw new TunnelSecretUnavailable(`connect_secret not available locally for tunnel ${options.name}; ` +
153
+ "pass secret explicitly, or rotate via inkbox.tunnels.rotateSecret(id) first.");
154
+ }
155
+ tunnel = await inkbox.tunnels.restore(tunnel.id);
156
+ }
157
+ if (!secret) {
158
+ throw new TunnelSecretUnavailable(`connect_secret not available locally for tunnel ${options.name}; ` +
159
+ "pass secret explicitly, or rotate via inkbox.tunnels.rotateSecret(id) first.");
160
+ }
161
+ }
162
+ // For passthrough, lazy-load _cert.ts so the edge-mode bundle stays
163
+ // clean of @peculiar/x509. The dynamic import keeps the dep out of
164
+ // the static module graph for edge users; M5 bundle verification is
165
+ // the forcing function.
166
+ let tlsTerminator = null;
167
+ if (tunnel.tlsMode === TLSMode.PASSTHROUGH) {
168
+ // Passthrough accepts either ``forwardTo`` (URL) or ``handler``
169
+ // (Fetch-style callable). The runtime constructs UpstreamUrlDispatch
170
+ // or CallableDispatch accordingly.
171
+ const cert = await import("./_cert.js");
172
+ const tls = await import("./_tls.js");
173
+ const keypair = await cert.loadOrCreateKeypair(stateDirPath);
174
+ const tunnelPublicHost = tunnel.publicHost ?? `${options.name}.${PROD_ZONE}`;
175
+ if (await cert.certNeedsSign(stateDirPath, keypair)) {
176
+ const csrPem = await cert.buildCsr(keypair, tunnelPublicHost);
177
+ const signed = await inkbox.tunnels.signCsr(tunnel.id, { csrPem });
178
+ cert.writeCertChain(stateDirPath, signed.certPem, signed.chainPem);
179
+ }
180
+ const certPath = `${stateDirPath}/cert_chain.pem`;
181
+ const certChainPem = await import("node:fs").then((fs) => fs.promises.readFile(certPath));
182
+ const keyPem = await cert.keyPemBytes(keypair);
183
+ // ALPN advertised in passthrough. enableH2Transcode=true (default)
184
+ // advertises h2 + http/1.1; the runtime selects the h1 parser or
185
+ // h2 transcoder per-connection by negotiated ALPN. Setting it
186
+ // false is the ALPN-only escape hatch — h1 parser still services
187
+ // inbound traffic, but h2 is never offered.
188
+ const enableH2 = options.enableH2Transcode !== false;
189
+ const alpnProtocols = enableH2
190
+ ? ["h2", "http/1.1"]
191
+ : ["http/1.1"];
192
+ tlsTerminator = new tls.TlsTerminator({
193
+ certChainPem,
194
+ keyPem,
195
+ alpnProtocols,
196
+ });
197
+ }
198
+ const { zone, publicHost } = resolveZoneAndHost({
199
+ name: options.name,
200
+ serverZone: tunnel.zone,
201
+ serverPublicHost: tunnel.publicHost,
202
+ state,
203
+ dataPlaneZoneOverride: options.dataPlaneZone ?? null,
204
+ });
205
+ saveState(stateDirPath, {
206
+ tunnelId: tunnel.id,
207
+ name: options.name,
208
+ secret,
209
+ mode: tunnel.tlsMode,
210
+ zone,
211
+ publicHost,
212
+ });
213
+ const runtime = new TunnelRuntime({
214
+ tunnelId: tunnel.id,
215
+ secret,
216
+ zone,
217
+ publicHost,
218
+ poolSize: options.poolSize ?? null,
219
+ dispatch: {
220
+ forwardTo: options.forwardTo,
221
+ httpHandler: options.handler,
222
+ wsHandler: options.wsHandler,
223
+ },
224
+ tlsTerminator: tlsTerminator ?? undefined,
225
+ maxInboundBodyBytes: options.maxInboundBodyBytes ?? DEFAULT_INBOUND_BODY_BYTES,
226
+ maxResponseBytes: options.maxResponseBytes ?? DEFAULT_OUTBOUND_BODY_BYTES,
227
+ allowRemoteForwarding: options.allowRemoteForwarding,
228
+ forwardToVerifyTls: options.forwardToVerifyTls,
229
+ forwardToCaBundle: options.forwardToCaBundle,
230
+ onStatus: options.onStatus,
231
+ });
232
+ const listenerOpts = {
233
+ installSignalHandlers: options.installSignalHandlers,
234
+ };
235
+ return new TunnelListenerImpl({
236
+ publicHost,
237
+ tunnel,
238
+ runtime,
239
+ listenerOpts,
240
+ });
241
+ }
242
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tunnels/client/index.ts"],"names":[],"mappings":"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"}