tailscale-web 0.1.10 → 0.1.11
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 +19 -1
- package/dist/index.d.ts +27 -0
- package/dist/main.wasm +0 -0
- package/dist/tailscale-web.es.js +116 -74
- package/dist/tailscale-web.umd.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/adrianosela/tailscale-web/blob/master/LICENSE)
|
|
6
6
|
[](https://goreportcard.com/report/github.com/adrianosela/tailscale-web)
|
|
7
7
|
|
|
8
|
-
Run a [Tailscale](https://tailscale.com) device directly in the browser. Make HTTP requests,
|
|
8
|
+
Run a [Tailscale](https://tailscale.com) device directly in the browser. Make HTTP requests, dial or listen for TCP connections, ping hosts, and use exit nodes for networking beyond Tailscale devices — all from a web page, with no server-side proxy required.
|
|
9
9
|
|
|
10
10
|
<details>
|
|
11
11
|
<summary>**Click here for motivation**</summary>
|
|
@@ -172,6 +172,24 @@ conn.write("hello\n")
|
|
|
172
172
|
conn.close()
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
+
### `network.listenTCP(port?, onConnection)`
|
|
176
|
+
|
|
177
|
+
Accept inbound TCP connections on a Tailscale port. Pass `0` (or omit) for an ephemeral port. Returns a `Listener` with the assigned `port` and a `close()` method.
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
const listener = await network.listenTCP(8080, conn => {
|
|
181
|
+
conn.onData(data => {
|
|
182
|
+
console.log(new TextDecoder().decode(data))
|
|
183
|
+
conn.write("pong\n")
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
console.log("listening on port", listener.port)
|
|
188
|
+
|
|
189
|
+
// stop accepting connections
|
|
190
|
+
listener.close()
|
|
191
|
+
```
|
|
192
|
+
|
|
175
193
|
### Exit nodes
|
|
176
194
|
|
|
177
195
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,13 @@ export declare interface InitOptions {
|
|
|
56
56
|
onAuthComplete?: () => void;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export declare interface Listener {
|
|
60
|
+
/** The port number the listener is bound to. */
|
|
61
|
+
port: number;
|
|
62
|
+
/** Stop the listener and release all resources. */
|
|
63
|
+
close(): void;
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
export declare const network: {
|
|
60
67
|
/**
|
|
61
68
|
* Initialize and connect the Tailscale node. Must be called before any
|
|
@@ -117,6 +124,26 @@ export declare const network: {
|
|
|
117
124
|
* conn.close()
|
|
118
125
|
*/
|
|
119
126
|
dialTCP(addr: string): Promise<Connection>;
|
|
127
|
+
/**
|
|
128
|
+
* Listen for inbound TCP connections on the given Tailscale port.
|
|
129
|
+
* Pass port 0 (default) to get an ephemeral port assigned automatically.
|
|
130
|
+
* onConnection is called for each accepted connection.
|
|
131
|
+
* Returns a Listener with the assigned port number and a close() method.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* const listener = await network.listenTCP(8080, conn => {
|
|
135
|
+
* conn.onData(data => console.log(new TextDecoder().decode(data)))
|
|
136
|
+
* conn.write("hello\n")
|
|
137
|
+
* })
|
|
138
|
+
* console.log("listening on port", listener.port)
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* // Ephemeral port
|
|
142
|
+
* const listener = await network.listenTCP(0, conn => { conn.close() })
|
|
143
|
+
* console.log("assigned port:", listener.port)
|
|
144
|
+
* listener.close()
|
|
145
|
+
*/
|
|
146
|
+
listenTCP(port: number | undefined, onConnection: (conn: Connection) => void): Promise<Listener>;
|
|
120
147
|
/**
|
|
121
148
|
* Make an HTTP request through the Tailscale network. Supports method,
|
|
122
149
|
* headers, and body. Does not yet support AbortSignal, streaming bodies
|
package/dist/main.wasm
CHANGED
|
Binary file
|
package/dist/tailscale-web.es.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
const n = () => {
|
|
3
|
-
const
|
|
4
|
-
return
|
|
3
|
+
const l = new Error("not implemented");
|
|
4
|
+
return l.code = "ENOSYS", l;
|
|
5
5
|
};
|
|
6
6
|
if (!globalThis.fs) {
|
|
7
|
-
let
|
|
7
|
+
let l = "";
|
|
8
8
|
globalThis.fs = {
|
|
9
9
|
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 },
|
|
10
10
|
// unused
|
|
11
11
|
writeSync(i, s) {
|
|
12
|
-
|
|
13
|
-
const r =
|
|
12
|
+
l += d.decode(s);
|
|
13
|
+
const r = l.lastIndexOf(`
|
|
14
14
|
`);
|
|
15
|
-
return r != -1 && (console.log(
|
|
15
|
+
return r != -1 && (console.log(l.substring(0, r)), l = l.substring(r + 1)), s.length;
|
|
16
16
|
},
|
|
17
|
-
write(i, s, r,
|
|
18
|
-
if (r !== 0 ||
|
|
17
|
+
write(i, s, r, c, y, u) {
|
|
18
|
+
if (r !== 0 || c !== s.length || y !== null) {
|
|
19
19
|
u(n());
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
chmod(i, s, r) {
|
|
26
26
|
r(n());
|
|
27
27
|
},
|
|
28
|
-
chown(i, s, r,
|
|
29
|
-
|
|
28
|
+
chown(i, s, r, c) {
|
|
29
|
+
c(n());
|
|
30
30
|
},
|
|
31
31
|
close(i, s) {
|
|
32
32
|
s(n());
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
fchmod(i, s, r) {
|
|
35
35
|
r(n());
|
|
36
36
|
},
|
|
37
|
-
fchown(i, s, r,
|
|
38
|
-
|
|
37
|
+
fchown(i, s, r, c) {
|
|
38
|
+
c(n());
|
|
39
39
|
},
|
|
40
40
|
fstat(i, s) {
|
|
41
41
|
s(n());
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
ftruncate(i, s, r) {
|
|
47
47
|
r(n());
|
|
48
48
|
},
|
|
49
|
-
lchown(i, s, r,
|
|
50
|
-
|
|
49
|
+
lchown(i, s, r, c) {
|
|
50
|
+
c(n());
|
|
51
51
|
},
|
|
52
52
|
link(i, s, r) {
|
|
53
53
|
r(n());
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
mkdir(i, s, r) {
|
|
59
59
|
r(n());
|
|
60
60
|
},
|
|
61
|
-
open(i, s, r,
|
|
62
|
-
|
|
61
|
+
open(i, s, r, c) {
|
|
62
|
+
c(n());
|
|
63
63
|
},
|
|
64
|
-
read(i, s, r,
|
|
64
|
+
read(i, s, r, c, y, u) {
|
|
65
65
|
u(n());
|
|
66
66
|
},
|
|
67
67
|
readdir(i, s) {
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
unlink(i, s) {
|
|
89
89
|
s(n());
|
|
90
90
|
},
|
|
91
|
-
utimes(i, s, r,
|
|
92
|
-
|
|
91
|
+
utimes(i, s, r, c) {
|
|
92
|
+
c(n());
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
}
|
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
throw n();
|
|
122
122
|
}
|
|
123
123
|
}), globalThis.path || (globalThis.path = {
|
|
124
|
-
resolve(...
|
|
125
|
-
return
|
|
124
|
+
resolve(...l) {
|
|
125
|
+
return l.join("/");
|
|
126
126
|
}
|
|
127
127
|
}), !globalThis.crypto)
|
|
128
128
|
throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
throw new Error("globalThis.TextEncoder is not available, polyfill required");
|
|
133
133
|
if (!globalThis.TextDecoder)
|
|
134
134
|
throw new Error("globalThis.TextDecoder is not available, polyfill required");
|
|
135
|
-
const h = new TextEncoder("utf-8"),
|
|
135
|
+
const h = new TextEncoder("utf-8"), d = new TextDecoder("utf-8");
|
|
136
136
|
globalThis.Go = class {
|
|
137
137
|
constructor() {
|
|
138
138
|
this.argv = ["js"], this.env = {}, this.exit = (t) => {
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
}, this._exitPromise = new Promise((t) => {
|
|
141
141
|
this._resolveExitPromise = t;
|
|
142
142
|
}), this._pendingEvent = null, this._scheduledTimeouts = /* @__PURE__ */ new Map(), this._nextCallbackTimeoutID = 1;
|
|
143
|
-
const
|
|
143
|
+
const l = (t, e) => {
|
|
144
144
|
this.mem.setUint32(t + 0, e, !0), this.mem.setUint32(t + 4, Math.floor(e / 4294967296), !0);
|
|
145
145
|
}, i = (t) => {
|
|
146
146
|
const e = this.mem.getUint32(t + 0, !0), o = this.mem.getInt32(t + 4, !0);
|
|
@@ -166,8 +166,8 @@
|
|
|
166
166
|
this.mem.setFloat64(t, 0, !0);
|
|
167
167
|
return;
|
|
168
168
|
}
|
|
169
|
-
let
|
|
170
|
-
|
|
169
|
+
let a = this._ids.get(e);
|
|
170
|
+
a === void 0 && (a = this._idPool.pop(), a === void 0 && (a = this._values.length), this._values[a] = e, this._goRefCounts[a] = 0, this._ids.set(e, a)), this._goRefCounts[a]++;
|
|
171
171
|
let m = 0;
|
|
172
172
|
switch (typeof e) {
|
|
173
173
|
case "object":
|
|
@@ -183,19 +183,19 @@
|
|
|
183
183
|
m = 4;
|
|
184
184
|
break;
|
|
185
185
|
}
|
|
186
|
-
this.mem.setUint32(t + 4, 2146959360 | m, !0), this.mem.setUint32(t,
|
|
187
|
-
},
|
|
186
|
+
this.mem.setUint32(t + 4, 2146959360 | m, !0), this.mem.setUint32(t, a, !0);
|
|
187
|
+
}, c = (t) => {
|
|
188
188
|
const e = i(t + 0), o = i(t + 8);
|
|
189
189
|
return new Uint8Array(this._inst.exports.mem.buffer, e, o);
|
|
190
190
|
}, y = (t) => {
|
|
191
|
-
const e = i(t + 0), o = i(t + 8),
|
|
191
|
+
const e = i(t + 0), o = i(t + 8), a = new Array(o);
|
|
192
192
|
for (let m = 0; m < o; m++)
|
|
193
|
-
|
|
194
|
-
return
|
|
193
|
+
a[m] = s(e + m * 8);
|
|
194
|
+
return a;
|
|
195
195
|
}, u = (t) => {
|
|
196
196
|
const e = i(t + 0), o = i(t + 8);
|
|
197
|
-
return
|
|
198
|
-
}, w = (t, e) => (this._inst.exports.testExport0(), this._inst.exports.testExport(t, e)),
|
|
197
|
+
return d.decode(new DataView(this._inst.exports.mem.buffer, e, o));
|
|
198
|
+
}, w = (t, e) => (this._inst.exports.testExport0(), this._inst.exports.testExport(t, e)), g = Date.now() - performance.now();
|
|
199
199
|
this.importObject = {
|
|
200
200
|
_gotest: {
|
|
201
201
|
add: (t, e) => t + e,
|
|
@@ -215,8 +215,8 @@
|
|
|
215
215
|
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
|
216
216
|
"runtime.wasmWrite": (t) => {
|
|
217
217
|
t >>>= 0;
|
|
218
|
-
const e = i(t + 8), o = i(t + 16),
|
|
219
|
-
fs.writeSync(e, new Uint8Array(this._inst.exports.mem.buffer, o,
|
|
218
|
+
const e = i(t + 8), o = i(t + 16), a = this.mem.getInt32(t + 24, !0);
|
|
219
|
+
fs.writeSync(e, new Uint8Array(this._inst.exports.mem.buffer, o, a));
|
|
220
220
|
},
|
|
221
221
|
// func resetMemoryDataView()
|
|
222
222
|
"runtime.resetMemoryDataView": (t) => {
|
|
@@ -224,13 +224,13 @@
|
|
|
224
224
|
},
|
|
225
225
|
// func nanotime1() int64
|
|
226
226
|
"runtime.nanotime1": (t) => {
|
|
227
|
-
t >>>= 0,
|
|
227
|
+
t >>>= 0, l(t + 8, (g + performance.now()) * 1e6);
|
|
228
228
|
},
|
|
229
229
|
// func walltime() (sec int64, nsec int32)
|
|
230
230
|
"runtime.walltime": (t) => {
|
|
231
231
|
t >>>= 0;
|
|
232
232
|
const e = (/* @__PURE__ */ new Date()).getTime();
|
|
233
|
-
|
|
233
|
+
l(t + 8, e / 1e3), this.mem.setInt32(t + 16, e % 1e3 * 1e6, !0);
|
|
234
234
|
},
|
|
235
235
|
// func scheduleTimeoutEvent(delay int64) int32
|
|
236
236
|
"runtime.scheduleTimeoutEvent": (t) => {
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
},
|
|
253
253
|
// func getRandomData(r []byte)
|
|
254
254
|
"runtime.getRandomData": (t) => {
|
|
255
|
-
t >>>= 0, crypto.getRandomValues(
|
|
255
|
+
t >>>= 0, crypto.getRandomValues(c(t + 8));
|
|
256
256
|
},
|
|
257
257
|
// func finalizeRef(v ref)
|
|
258
258
|
"syscall/js.finalizeRef": (t) => {
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
"syscall/js.valueCall": (t) => {
|
|
294
294
|
t >>>= 0;
|
|
295
295
|
try {
|
|
296
|
-
const e = s(t + 8), o = Reflect.get(e, u(t + 16)),
|
|
296
|
+
const e = s(t + 8), o = Reflect.get(e, u(t + 16)), a = y(t + 32), m = Reflect.apply(o, e, a);
|
|
297
297
|
t = this._inst.exports.getsp() >>> 0, r(t + 56, m), this.mem.setUint8(t + 64, 1);
|
|
298
298
|
} catch (e) {
|
|
299
299
|
t = this._inst.exports.getsp() >>> 0, r(t + 56, e), this.mem.setUint8(t + 64, 0);
|
|
@@ -303,8 +303,8 @@
|
|
|
303
303
|
"syscall/js.valueInvoke": (t) => {
|
|
304
304
|
t >>>= 0;
|
|
305
305
|
try {
|
|
306
|
-
const e = s(t + 8), o = y(t + 16),
|
|
307
|
-
t = this._inst.exports.getsp() >>> 0, r(t + 40,
|
|
306
|
+
const e = s(t + 8), o = y(t + 16), a = Reflect.apply(e, void 0, o);
|
|
307
|
+
t = this._inst.exports.getsp() >>> 0, r(t + 40, a), this.mem.setUint8(t + 48, 1);
|
|
308
308
|
} catch (e) {
|
|
309
309
|
t = this._inst.exports.getsp() >>> 0, r(t + 40, e), this.mem.setUint8(t + 48, 0);
|
|
310
310
|
}
|
|
@@ -313,27 +313,27 @@
|
|
|
313
313
|
"syscall/js.valueNew": (t) => {
|
|
314
314
|
t >>>= 0;
|
|
315
315
|
try {
|
|
316
|
-
const e = s(t + 8), o = y(t + 16),
|
|
317
|
-
t = this._inst.exports.getsp() >>> 0, r(t + 40,
|
|
316
|
+
const e = s(t + 8), o = y(t + 16), a = Reflect.construct(e, o);
|
|
317
|
+
t = this._inst.exports.getsp() >>> 0, r(t + 40, a), this.mem.setUint8(t + 48, 1);
|
|
318
318
|
} catch (e) {
|
|
319
319
|
t = this._inst.exports.getsp() >>> 0, r(t + 40, e), this.mem.setUint8(t + 48, 0);
|
|
320
320
|
}
|
|
321
321
|
},
|
|
322
322
|
// func valueLength(v ref) int
|
|
323
323
|
"syscall/js.valueLength": (t) => {
|
|
324
|
-
t >>>= 0,
|
|
324
|
+
t >>>= 0, l(t + 16, parseInt(s(t + 8).length));
|
|
325
325
|
},
|
|
326
326
|
// valuePrepareString(v ref) (ref, int)
|
|
327
327
|
"syscall/js.valuePrepareString": (t) => {
|
|
328
328
|
t >>>= 0;
|
|
329
329
|
const e = h.encode(String(s(t + 8)));
|
|
330
|
-
r(t + 16, e),
|
|
330
|
+
r(t + 16, e), l(t + 24, e.length);
|
|
331
331
|
},
|
|
332
332
|
// valueLoadString(v ref, b []byte)
|
|
333
333
|
"syscall/js.valueLoadString": (t) => {
|
|
334
334
|
t >>>= 0;
|
|
335
335
|
const e = s(t + 8);
|
|
336
|
-
|
|
336
|
+
c(t + 16).set(e);
|
|
337
337
|
},
|
|
338
338
|
// func valueInstanceOf(v ref, t ref) bool
|
|
339
339
|
"syscall/js.valueInstanceOf": (t) => {
|
|
@@ -342,24 +342,24 @@
|
|
|
342
342
|
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
343
343
|
"syscall/js.copyBytesToGo": (t) => {
|
|
344
344
|
t >>>= 0;
|
|
345
|
-
const e =
|
|
345
|
+
const e = c(t + 8), o = s(t + 32);
|
|
346
346
|
if (!(o instanceof Uint8Array || o instanceof Uint8ClampedArray)) {
|
|
347
347
|
this.mem.setUint8(t + 48, 0);
|
|
348
348
|
return;
|
|
349
349
|
}
|
|
350
|
-
const
|
|
351
|
-
e.set(
|
|
350
|
+
const a = o.subarray(0, e.length);
|
|
351
|
+
e.set(a), l(t + 40, a.length), this.mem.setUint8(t + 48, 1);
|
|
352
352
|
},
|
|
353
353
|
// func copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
354
354
|
"syscall/js.copyBytesToJS": (t) => {
|
|
355
355
|
t >>>= 0;
|
|
356
|
-
const e = s(t + 8), o =
|
|
356
|
+
const e = s(t + 8), o = c(t + 16);
|
|
357
357
|
if (!(e instanceof Uint8Array || e instanceof Uint8ClampedArray)) {
|
|
358
358
|
this.mem.setUint8(t + 48, 0);
|
|
359
359
|
return;
|
|
360
360
|
}
|
|
361
|
-
const
|
|
362
|
-
e.set(
|
|
361
|
+
const a = o.subarray(0, e.length);
|
|
362
|
+
e.set(a), l(t + 40, a.length), this.mem.setUint8(t + 48, 1);
|
|
363
363
|
},
|
|
364
364
|
debug: (t) => {
|
|
365
365
|
console.log(t);
|
|
@@ -367,10 +367,10 @@
|
|
|
367
367
|
}
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
async run(
|
|
371
|
-
if (!(
|
|
370
|
+
async run(l) {
|
|
371
|
+
if (!(l instanceof WebAssembly.Instance))
|
|
372
372
|
throw new Error("Go.run: WebAssembly.Instance expected");
|
|
373
|
-
this._inst =
|
|
373
|
+
this._inst = l, this.mem = new DataView(this._inst.exports.mem.buffer), this._values = [
|
|
374
374
|
// JS values that Go currently has references to, indexed by reference id
|
|
375
375
|
NaN,
|
|
376
376
|
0,
|
|
@@ -389,18 +389,18 @@
|
|
|
389
389
|
[this, 6]
|
|
390
390
|
]), this._idPool = [], this.exited = !1;
|
|
391
391
|
let i = 4096;
|
|
392
|
-
const s = (
|
|
393
|
-
const t = i, e = h.encode(
|
|
392
|
+
const s = (g) => {
|
|
393
|
+
const t = i, e = h.encode(g + "\0");
|
|
394
394
|
return new Uint8Array(this.mem.buffer, i, e.length).set(e), i += e.length, i % 8 !== 0 && (i += 8 - i % 8), t;
|
|
395
|
-
}, r = this.argv.length,
|
|
396
|
-
this.argv.forEach((
|
|
397
|
-
|
|
398
|
-
}),
|
|
399
|
-
|
|
400
|
-
}),
|
|
395
|
+
}, r = this.argv.length, c = [];
|
|
396
|
+
this.argv.forEach((g) => {
|
|
397
|
+
c.push(s(g));
|
|
398
|
+
}), c.push(0), Object.keys(this.env).sort().forEach((g) => {
|
|
399
|
+
c.push(s(`${g}=${this.env[g]}`));
|
|
400
|
+
}), c.push(0);
|
|
401
401
|
const u = i;
|
|
402
|
-
if (
|
|
403
|
-
this.mem.setUint32(i,
|
|
402
|
+
if (c.forEach((g) => {
|
|
403
|
+
this.mem.setUint32(i, g, !0), this.mem.setUint32(i + 4, 0, !0), i += 8;
|
|
404
404
|
}), i >= 12288)
|
|
405
405
|
throw new Error("total length of command line and environment variables exceeds limit");
|
|
406
406
|
this._inst.exports.run(r, u), this.exited && this._resolveExitPromise(), await this._exitPromise;
|
|
@@ -410,25 +410,25 @@
|
|
|
410
410
|
throw new Error("Go program has already exited");
|
|
411
411
|
this._inst.exports.resume(), this.exited && this._resolveExitPromise();
|
|
412
412
|
}
|
|
413
|
-
_makeFuncWrapper(
|
|
413
|
+
_makeFuncWrapper(l) {
|
|
414
414
|
const i = this;
|
|
415
415
|
return function() {
|
|
416
|
-
const s = { id:
|
|
416
|
+
const s = { id: l, this: this, args: arguments };
|
|
417
417
|
return i._pendingEvent = s, i._resume(), s.result;
|
|
418
418
|
};
|
|
419
419
|
}
|
|
420
420
|
};
|
|
421
421
|
})();
|
|
422
|
-
const
|
|
422
|
+
const x = new URL("main.wasm", import.meta.url).href;
|
|
423
423
|
(() => {
|
|
424
424
|
const n = globalThis, h = "process";
|
|
425
425
|
n[h] ? n[h].pid == null && (n[h].pid = 1) : n[h] = { pid: 1 };
|
|
426
426
|
})();
|
|
427
427
|
let _ = !1;
|
|
428
|
-
async function
|
|
428
|
+
async function b() {
|
|
429
429
|
if (_) return;
|
|
430
430
|
const n = new globalThis.Go(), h = await WebAssembly.instantiateStreaming(
|
|
431
|
-
fetch(
|
|
431
|
+
fetch(x),
|
|
432
432
|
n.importObject
|
|
433
433
|
);
|
|
434
434
|
n.run(h.instance), _ = !0;
|
|
@@ -481,7 +481,7 @@ const p = {
|
|
|
481
481
|
* })
|
|
482
482
|
*/
|
|
483
483
|
async init(n = {}) {
|
|
484
|
-
return await
|
|
484
|
+
return await b(), f().init(n);
|
|
485
485
|
},
|
|
486
486
|
/**
|
|
487
487
|
* Send an ICMP ping to addr and measure round-trip time.
|
|
@@ -515,12 +515,12 @@ const p = {
|
|
|
515
515
|
async dialTCP(n) {
|
|
516
516
|
const h = await f().dialTCP(n);
|
|
517
517
|
return {
|
|
518
|
-
onData(
|
|
519
|
-
h.onData(
|
|
518
|
+
onData(d) {
|
|
519
|
+
h.onData(d);
|
|
520
520
|
},
|
|
521
|
-
write(
|
|
521
|
+
write(d) {
|
|
522
522
|
h.write(
|
|
523
|
-
typeof
|
|
523
|
+
typeof d == "string" ? new TextEncoder().encode(d) : d
|
|
524
524
|
);
|
|
525
525
|
},
|
|
526
526
|
close() {
|
|
@@ -528,6 +528,48 @@ const p = {
|
|
|
528
528
|
}
|
|
529
529
|
};
|
|
530
530
|
},
|
|
531
|
+
/**
|
|
532
|
+
* Listen for inbound TCP connections on the given Tailscale port.
|
|
533
|
+
* Pass port 0 (default) to get an ephemeral port assigned automatically.
|
|
534
|
+
* onConnection is called for each accepted connection.
|
|
535
|
+
* Returns a Listener with the assigned port number and a close() method.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* const listener = await network.listenTCP(8080, conn => {
|
|
539
|
+
* conn.onData(data => console.log(new TextDecoder().decode(data)))
|
|
540
|
+
* conn.write("hello\n")
|
|
541
|
+
* })
|
|
542
|
+
* console.log("listening on port", listener.port)
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* // Ephemeral port
|
|
546
|
+
* const listener = await network.listenTCP(0, conn => { conn.close() })
|
|
547
|
+
* console.log("assigned port:", listener.port)
|
|
548
|
+
* listener.close()
|
|
549
|
+
*/
|
|
550
|
+
async listenTCP(n = 0, h) {
|
|
551
|
+
const d = await f().listenTCP(n, (l) => {
|
|
552
|
+
h({
|
|
553
|
+
onData(i) {
|
|
554
|
+
l.onData(i);
|
|
555
|
+
},
|
|
556
|
+
write(i) {
|
|
557
|
+
l.write(
|
|
558
|
+
typeof i == "string" ? new TextEncoder().encode(i) : i
|
|
559
|
+
);
|
|
560
|
+
},
|
|
561
|
+
close() {
|
|
562
|
+
l.close();
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
return {
|
|
567
|
+
port: d.port,
|
|
568
|
+
close() {
|
|
569
|
+
d.close();
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
},
|
|
531
573
|
/**
|
|
532
574
|
* Make an HTTP request through the Tailscale network. Supports method,
|
|
533
575
|
* headers, and body. Does not yet support AbortSignal, streaming bodies
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(w,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(w=typeof globalThis<"u"?globalThis:w||self,_(w["tailscale-web"]={}))})(this,(function(w){"use strict";(()=>{const n=()=>{const
|
|
2
|
-
`);return r!=-1&&(console.log(
|
|
1
|
+
(function(w,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(w=typeof globalThis<"u"?globalThis:w||self,_(w["tailscale-web"]={}))})(this,(function(w){"use strict";(()=>{const n=()=>{const l=new Error("not implemented");return l.code="ENOSYS",l};if(!globalThis.fs){let l="";globalThis.fs={constants:{O_WRONLY:-1,O_RDWR:-1,O_CREAT:-1,O_TRUNC:-1,O_APPEND:-1,O_EXCL:-1,O_DIRECTORY:-1},writeSync(i,s){l+=f.decode(s);const r=l.lastIndexOf(`
|
|
2
|
+
`);return r!=-1&&(console.log(l.substring(0,r)),l=l.substring(r+1)),s.length},write(i,s,r,c,y,h){if(r!==0||c!==s.length||y!==null){h(n());return}const b=this.writeSync(i,s);h(null,b)},chmod(i,s,r){r(n())},chown(i,s,r,c){c(n())},close(i,s){s(n())},fchmod(i,s,r){r(n())},fchown(i,s,r,c){c(n())},fstat(i,s){s(n())},fsync(i,s){s(null)},ftruncate(i,s,r){r(n())},lchown(i,s,r,c){c(n())},link(i,s,r){r(n())},lstat(i,s){s(n())},mkdir(i,s,r){r(n())},open(i,s,r,c){c(n())},read(i,s,r,c,y,h){h(n())},readdir(i,s){s(n())},readlink(i,s){s(n())},rename(i,s,r){r(n())},rmdir(i,s){s(n())},stat(i,s){s(n())},symlink(i,s,r){r(n())},truncate(i,s,r){r(n())},unlink(i,s){s(n())},utimes(i,s,r,c){c(n())}}}if(globalThis.process||(globalThis.process={getuid(){return-1},getgid(){return-1},geteuid(){return-1},getegid(){return-1},getgroups(){throw n()},pid:-1,ppid:-1,umask(){throw n()},cwd(){throw n()},chdir(){throw n()}}),globalThis.path||(globalThis.path={resolve(...l){return l.join("/")}}),!globalThis.crypto)throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");if(!globalThis.performance)throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");if(!globalThis.TextEncoder)throw new Error("globalThis.TextEncoder is not available, polyfill required");if(!globalThis.TextDecoder)throw new Error("globalThis.TextDecoder is not available, polyfill required");const u=new TextEncoder("utf-8"),f=new TextDecoder("utf-8");globalThis.Go=class{constructor(){this.argv=["js"],this.env={},this.exit=t=>{t!==0&&console.warn("exit code:",t)},this._exitPromise=new Promise(t=>{this._resolveExitPromise=t}),this._pendingEvent=null,this._scheduledTimeouts=new Map,this._nextCallbackTimeoutID=1;const l=(t,e)=>{this.mem.setUint32(t+0,e,!0),this.mem.setUint32(t+4,Math.floor(e/4294967296),!0)},i=t=>{const e=this.mem.getUint32(t+0,!0),o=this.mem.getInt32(t+4,!0);return e+o*4294967296},s=t=>{const e=this.mem.getFloat64(t,!0);if(e===0)return;if(!isNaN(e))return e;const o=this.mem.getUint32(t,!0);return this._values[o]},r=(t,e)=>{if(typeof e=="number"&&e!==0){if(isNaN(e)){this.mem.setUint32(t+4,2146959360,!0),this.mem.setUint32(t,0,!0);return}this.mem.setFloat64(t,e,!0);return}if(e===void 0){this.mem.setFloat64(t,0,!0);return}let a=this._ids.get(e);a===void 0&&(a=this._idPool.pop(),a===void 0&&(a=this._values.length),this._values[a]=e,this._goRefCounts[a]=0,this._ids.set(e,a)),this._goRefCounts[a]++;let m=0;switch(typeof e){case"object":e!==null&&(m=1);break;case"string":m=2;break;case"symbol":m=3;break;case"function":m=4;break}this.mem.setUint32(t+4,2146959360|m,!0),this.mem.setUint32(t,a,!0)},c=t=>{const e=i(t+0),o=i(t+8);return new Uint8Array(this._inst.exports.mem.buffer,e,o)},y=t=>{const e=i(t+0),o=i(t+8),a=new Array(o);for(let m=0;m<o;m++)a[m]=s(e+m*8);return a},h=t=>{const e=i(t+0),o=i(t+8);return f.decode(new DataView(this._inst.exports.mem.buffer,e,o))},b=(t,e)=>(this._inst.exports.testExport0(),this._inst.exports.testExport(t,e)),g=Date.now()-performance.now();this.importObject={_gotest:{add:(t,e)=>t+e,callExport:b},gojs:{"runtime.wasmExit":t=>{t>>>=0;const e=this.mem.getInt32(t+8,!0);this.exited=!0,delete this._inst,delete this._values,delete this._goRefCounts,delete this._ids,delete this._idPool,this.exit(e)},"runtime.wasmWrite":t=>{t>>>=0;const e=i(t+8),o=i(t+16),a=this.mem.getInt32(t+24,!0);fs.writeSync(e,new Uint8Array(this._inst.exports.mem.buffer,o,a))},"runtime.resetMemoryDataView":t=>{this.mem=new DataView(this._inst.exports.mem.buffer)},"runtime.nanotime1":t=>{t>>>=0,l(t+8,(g+performance.now())*1e6)},"runtime.walltime":t=>{t>>>=0;const e=new Date().getTime();l(t+8,e/1e3),this.mem.setInt32(t+16,e%1e3*1e6,!0)},"runtime.scheduleTimeoutEvent":t=>{t>>>=0;const e=this._nextCallbackTimeoutID;this._nextCallbackTimeoutID++,this._scheduledTimeouts.set(e,setTimeout(()=>{for(this._resume();this._scheduledTimeouts.has(e);)console.warn("scheduleTimeoutEvent: missed timeout event"),this._resume()},i(t+8))),this.mem.setInt32(t+16,e,!0)},"runtime.clearTimeoutEvent":t=>{t>>>=0;const e=this.mem.getInt32(t+8,!0);clearTimeout(this._scheduledTimeouts.get(e)),this._scheduledTimeouts.delete(e)},"runtime.getRandomData":t=>{t>>>=0,crypto.getRandomValues(c(t+8))},"syscall/js.finalizeRef":t=>{t>>>=0;const e=this.mem.getUint32(t+8,!0);if(this._goRefCounts[e]--,this._goRefCounts[e]===0){const o=this._values[e];this._values[e]=null,this._ids.delete(o),this._idPool.push(e)}},"syscall/js.stringVal":t=>{t>>>=0,r(t+24,h(t+8))},"syscall/js.valueGet":t=>{t>>>=0;const e=Reflect.get(s(t+8),h(t+16));t=this._inst.exports.getsp()>>>0,r(t+32,e)},"syscall/js.valueSet":t=>{t>>>=0,Reflect.set(s(t+8),h(t+16),s(t+32))},"syscall/js.valueDelete":t=>{t>>>=0,Reflect.deleteProperty(s(t+8),h(t+16))},"syscall/js.valueIndex":t=>{t>>>=0,r(t+24,Reflect.get(s(t+8),i(t+16)))},"syscall/js.valueSetIndex":t=>{t>>>=0,Reflect.set(s(t+8),i(t+16),s(t+24))},"syscall/js.valueCall":t=>{t>>>=0;try{const e=s(t+8),o=Reflect.get(e,h(t+16)),a=y(t+32),m=Reflect.apply(o,e,a);t=this._inst.exports.getsp()>>>0,r(t+56,m),this.mem.setUint8(t+64,1)}catch(e){t=this._inst.exports.getsp()>>>0,r(t+56,e),this.mem.setUint8(t+64,0)}},"syscall/js.valueInvoke":t=>{t>>>=0;try{const e=s(t+8),o=y(t+16),a=Reflect.apply(e,void 0,o);t=this._inst.exports.getsp()>>>0,r(t+40,a),this.mem.setUint8(t+48,1)}catch(e){t=this._inst.exports.getsp()>>>0,r(t+40,e),this.mem.setUint8(t+48,0)}},"syscall/js.valueNew":t=>{t>>>=0;try{const e=s(t+8),o=y(t+16),a=Reflect.construct(e,o);t=this._inst.exports.getsp()>>>0,r(t+40,a),this.mem.setUint8(t+48,1)}catch(e){t=this._inst.exports.getsp()>>>0,r(t+40,e),this.mem.setUint8(t+48,0)}},"syscall/js.valueLength":t=>{t>>>=0,l(t+16,parseInt(s(t+8).length))},"syscall/js.valuePrepareString":t=>{t>>>=0;const e=u.encode(String(s(t+8)));r(t+16,e),l(t+24,e.length)},"syscall/js.valueLoadString":t=>{t>>>=0;const e=s(t+8);c(t+16).set(e)},"syscall/js.valueInstanceOf":t=>{t>>>=0,this.mem.setUint8(t+24,s(t+8)instanceof s(t+16)?1:0)},"syscall/js.copyBytesToGo":t=>{t>>>=0;const e=c(t+8),o=s(t+32);if(!(o instanceof Uint8Array||o instanceof Uint8ClampedArray)){this.mem.setUint8(t+48,0);return}const a=o.subarray(0,e.length);e.set(a),l(t+40,a.length),this.mem.setUint8(t+48,1)},"syscall/js.copyBytesToJS":t=>{t>>>=0;const e=s(t+8),o=c(t+16);if(!(e instanceof Uint8Array||e instanceof Uint8ClampedArray)){this.mem.setUint8(t+48,0);return}const a=o.subarray(0,e.length);e.set(a),l(t+40,a.length),this.mem.setUint8(t+48,1)},debug:t=>{console.log(t)}}}}async run(l){if(!(l instanceof WebAssembly.Instance))throw new Error("Go.run: WebAssembly.Instance expected");this._inst=l,this.mem=new DataView(this._inst.exports.mem.buffer),this._values=[NaN,0,null,!0,!1,globalThis,this],this._goRefCounts=new Array(this._values.length).fill(1/0),this._ids=new Map([[0,1],[null,2],[!0,3],[!1,4],[globalThis,5],[this,6]]),this._idPool=[],this.exited=!1;let i=4096;const s=g=>{const t=i,e=u.encode(g+"\0");return new Uint8Array(this.mem.buffer,i,e.length).set(e),i+=e.length,i%8!==0&&(i+=8-i%8),t},r=this.argv.length,c=[];this.argv.forEach(g=>{c.push(s(g))}),c.push(0),Object.keys(this.env).sort().forEach(g=>{c.push(s(`${g}=${this.env[g]}`))}),c.push(0);const h=i;if(c.forEach(g=>{this.mem.setUint32(i,g,!0),this.mem.setUint32(i+4,0,!0),i+=8}),i>=12288)throw new Error("total length of command line and environment variables exceeds limit");this._inst.exports.run(r,h),this.exited&&this._resolveExitPromise(),await this._exitPromise}_resume(){if(this.exited)throw new Error("Go program has already exited");this._inst.exports.resume(),this.exited&&this._resolveExitPromise()}_makeFuncWrapper(l){const i=this;return function(){const s={id:l,this:this,args:arguments};return i._pendingEvent=s,i._resume(),s.result}}}})();const _=typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__dirname+"/main.wasm").href:new URL("main.wasm",typeof document>"u"?location.href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&document.currentScript.src||document.baseURI).href;(()=>{const n=globalThis,u="process";n[u]?n[u].pid==null&&(n[u].pid=1):n[u]={pid:1}})();let x=!1;async function p(){if(x)return;const n=new globalThis.Go,u=await WebAssembly.instantiateStreaming(fetch(_),n.importObject);n.run(u.instance),x=!0}function d(){return globalThis.__tailscaleWeb}function T(n){return{status:n.status,statusText:n.statusText,ok:n.ok,headers:n.headers,text:async()=>new TextDecoder().decode(n.body),json:async()=>JSON.parse(new TextDecoder().decode(n.body)),arrayBuffer:async()=>n.body.buffer,bytes:async()=>n.body}}const v={async init(n={}){return await p(),d().init(n)},async ping(n){return d().ping(n)},async dialTCP(n){const u=await d().dialTCP(n);return{onData(f){u.onData(f)},write(f){u.write(typeof f=="string"?new TextEncoder().encode(f):f)},close(){u.close()}}},async listenTCP(n=0,u){const f=await d().listenTCP(n,l=>{u({onData(i){l.onData(i)},write(i){l.write(typeof i=="string"?new TextEncoder().encode(i):i)},close(){l.close()}})});return{port:f.port,close(){f.close()}}},async fetch(n,u={}){return T(await d().fetch(n,u))},getPrefs(){return d().getPrefs()},async setAcceptRoutes(n){return d().setAcceptRoutes(n)},listExitNodes(){return Array.from(d().listExitNodes())},async setExitNode(n=""){return d().setExitNode(n)},getRoutes(){return Array.from(d().getRoutes())},getDNS(){return d().getDNS()}};w.network=v,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})}));
|