@bridgething/adapter-network 0.1.4
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 +90 -0
- package/dist/discovery.d.ts +44 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +38 -0
- package/dist/discovery.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +344 -0
- package/dist/index.js.map +1 -0
- package/dist/mdns.d.ts +26 -0
- package/dist/mdns.d.ts.map +1 -0
- package/dist/mdns.js +107 -0
- package/dist/mdns.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @bridgething/adapter-network
|
|
2
|
+
|
|
3
|
+
Network-gateway transport for [`@bridgething/gateway`](../gateway/typescript).
|
|
4
|
+
Speaks the daemon's WebSocket gateway on TCP port 8892 (`bridgething.local`
|
|
5
|
+
by default), so any host that can open a WebSocket can drive a Car Thing
|
|
6
|
+
without native code, NAPI bindings, or platform-specific Bluetooth stacks.
|
|
7
|
+
|
|
8
|
+
Replaces the retired `@bridgething/adapter-node`.
|
|
9
|
+
|
|
10
|
+
## Quick start
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { BridgethingGateway } from '@bridgething/gateway';
|
|
14
|
+
import { NetworkAdapter } from '@bridgething/adapter-network';
|
|
15
|
+
|
|
16
|
+
const adapter = new NetworkAdapter(); // defaults to ws://bridgething.local:8892/
|
|
17
|
+
const gateway = new BridgethingGateway(adapter);
|
|
18
|
+
|
|
19
|
+
gateway.on(event => {
|
|
20
|
+
if (event.type === 'connected') console.log('up:', event.device);
|
|
21
|
+
if (event.type === 'disconnected') console.log('down:', event.deviceId);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await gateway.start();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Single device, custom host
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
new NetworkAdapter({ discovery: 'ws://10.42.1.1:8892/' });
|
|
31
|
+
new NetworkAdapter({ discovery: { id: 'lab-1', url: 'ws://thing-a.local:8892/', name: 'Lab A' } });
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Multiple known hosts
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
new NetworkAdapter({
|
|
38
|
+
discovery: [
|
|
39
|
+
{ id: 'rack-1', url: 'ws://thing-a.local:8892/' },
|
|
40
|
+
{ id: 'rack-2', url: 'ws://thing-b.local:8892/' },
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## mDNS browsing
|
|
46
|
+
|
|
47
|
+
For Node / Bun. Install the optional peer dependency first:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
bun add bonjour-service
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { NetworkAdapter } from '@bridgething/adapter-network';
|
|
55
|
+
import { MDNSDiscoverer } from '@bridgething/adapter-network/mdns';
|
|
56
|
+
|
|
57
|
+
const adapter = new NetworkAdapter({ discovery: new MDNSDiscoverer() });
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`MDNSDiscoverer` browses `_bridgething._tcp` and surfaces each daemon as
|
|
61
|
+
its own `Endpoint` with the device's mDNS-advertised nickname propagated
|
|
62
|
+
through `Endpoint.metadata.nickname`.
|
|
63
|
+
|
|
64
|
+
## Browser support
|
|
65
|
+
|
|
66
|
+
`NetworkAdapter` works in browsers that can open WebSockets. The default
|
|
67
|
+
URL (`ws://bridgething.local:8892/`) relies on the OS resolver for `.local`
|
|
68
|
+
hostnames (mDNS via systemd-resolved / mDNSResponder / Windows DNS Client).
|
|
69
|
+
mDNS *browsing* is not available in browsers; use the static-URL form.
|
|
70
|
+
|
|
71
|
+
For the in-browser Bluetooth Classic path, use `WebSerialAdapter` from
|
|
72
|
+
`@bridgething/gateway` instead — `NetworkAdapter` covers the dev-tether
|
|
73
|
+
(USB-CDC-ECM) case only.
|
|
74
|
+
|
|
75
|
+
## Reconnection
|
|
76
|
+
|
|
77
|
+
Per-peer auto-reconnect with exponential backoff (`500ms → 15s`, ladder
|
|
78
|
+
repeats). Configure with `options.reconnect`:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
new NetworkAdapter({ reconnect: false }); // off
|
|
82
|
+
new NetworkAdapter({ reconnect: [1000, 5000, 30000] }); // custom ladder
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Posture
|
|
86
|
+
|
|
87
|
+
The network gateway has no auth (matches the project posture). Treat the
|
|
88
|
+
WebSocket like a debug interface: only expose it on the USB-CDC-ECM
|
|
89
|
+
gadget link or a trusted LAN. The daemon binds `0.0.0.0:8892`, so deny
|
|
90
|
+
external reach with the host firewall if the device is wifi-bridged.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A discoverer surfaces bridgething daemons reachable over the network gateway WebSocket.
|
|
3
|
+
* The adapter opens/closes connections as `Endpoint` lifecycle events arrive.
|
|
4
|
+
*
|
|
5
|
+
* Two bundled implementations:
|
|
6
|
+
* - `StaticDiscoverer`: one fixed URL, works everywhere including browsers.
|
|
7
|
+
* - `MDNSDiscoverer`: browses `_bridgething._tcp` (Node/Bun only; optional `bonjour-service` peer dep).
|
|
8
|
+
*
|
|
9
|
+
* Callers can supply their own (e.g. polling a config file, resolving hostnames over DNS).
|
|
10
|
+
*/
|
|
11
|
+
/** A daemon reachable at `url`. `id` is stable for the endpoint's lifetime and used as the adapter's `deviceId`. */
|
|
12
|
+
export type Endpoint = {
|
|
13
|
+
id: string;
|
|
14
|
+
url: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
metadata?: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
export type DiscoveryListener = {
|
|
19
|
+
type: 'found';
|
|
20
|
+
endpoint: Endpoint;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'lost';
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
25
|
+
export interface Discoverer {
|
|
26
|
+
start(listener: (event: DiscoveryListener) => void): Promise<void>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Single fixed endpoint. The common case: USB-CDC-ECM tether with `bridgething.local:8892`.
|
|
31
|
+
* Works in the browser and on any host whose resolver understands `.local`.
|
|
32
|
+
*/
|
|
33
|
+
export declare class StaticDiscoverer implements Discoverer {
|
|
34
|
+
private readonly endpoint;
|
|
35
|
+
private started;
|
|
36
|
+
constructor(options: {
|
|
37
|
+
url: string;
|
|
38
|
+
id?: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
} | string);
|
|
41
|
+
start(listener: (event: DiscoveryListener) => void): Promise<void>;
|
|
42
|
+
stop(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,oHAAoH;AACpH,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAErG,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IASzE,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAItB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A discoverer surfaces bridgething daemons reachable over the network gateway WebSocket.
|
|
3
|
+
* The adapter opens/closes connections as `Endpoint` lifecycle events arrive.
|
|
4
|
+
*
|
|
5
|
+
* Two bundled implementations:
|
|
6
|
+
* - `StaticDiscoverer`: one fixed URL, works everywhere including browsers.
|
|
7
|
+
* - `MDNSDiscoverer`: browses `_bridgething._tcp` (Node/Bun only; optional `bonjour-service` peer dep).
|
|
8
|
+
*
|
|
9
|
+
* Callers can supply their own (e.g. polling a config file, resolving hostnames over DNS).
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Single fixed endpoint. The common case: USB-CDC-ECM tether with `bridgething.local:8892`.
|
|
13
|
+
* Works in the browser and on any host whose resolver understands `.local`.
|
|
14
|
+
*/
|
|
15
|
+
export class StaticDiscoverer {
|
|
16
|
+
endpoint;
|
|
17
|
+
started = false;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
const opts = typeof options === 'string' ? { url: options } : options;
|
|
20
|
+
this.endpoint = {
|
|
21
|
+
id: opts.id ?? opts.url,
|
|
22
|
+
url: opts.url,
|
|
23
|
+
name: opts.name,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
start(listener) {
|
|
27
|
+
if (this.started)
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
this.started = true;
|
|
30
|
+
listener({ type: 'found', endpoint: this.endpoint });
|
|
31
|
+
return Promise.resolve();
|
|
32
|
+
}
|
|
33
|
+
stop() {
|
|
34
|
+
this.started = false;
|
|
35
|
+
return Promise.resolve();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiBH;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IACV,QAAQ,CAAW;IAC5B,OAAO,GAAG,KAAK,CAAC;IAExB,YAAY,OAA6D;QACvE,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACtE,IAAI,CAAC,QAAQ,GAAG;YACd,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG;YACvB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAA4C;QAChD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Adapter, AdapterListener } from '@bridgething/gateway';
|
|
2
|
+
import { LogVerbosity } from '@bridgething/lib';
|
|
3
|
+
import { StaticDiscoverer, type Discoverer, type DiscoveryListener, type Endpoint } from './discovery';
|
|
4
|
+
export { StaticDiscoverer, type Discoverer, type DiscoveryListener, type Endpoint };
|
|
5
|
+
export type NetworkAdapterOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Where to look for daemons. Pass a string URL or an `Endpoint` for the
|
|
8
|
+
* common single-device case, an array for multiple known hosts, or a
|
|
9
|
+
* `Discoverer` for mDNS / custom strategies.
|
|
10
|
+
*/
|
|
11
|
+
discovery?: string | Endpoint | Endpoint[] | Discoverer;
|
|
12
|
+
/** Constructor for the underlying WebSocket. Defaults to the global. */
|
|
13
|
+
websocket?: typeof WebSocket;
|
|
14
|
+
/**
|
|
15
|
+
* Auto-reconnect dropped peers with exponential backoff. The default
|
|
16
|
+
* ladder is `[500, 1_000, 2_000, 4_000, 8_000, 15_000]` ms; the last
|
|
17
|
+
* entry repeats. Set to `false` to disable.
|
|
18
|
+
*/
|
|
19
|
+
reconnect?: boolean | number[];
|
|
20
|
+
logLevel?: LogVerbosity;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Byte-level transport for `@bridgething/gateway` over the daemon's network gateway WebSocket.
|
|
24
|
+
* One instance can hold many peers; each `Endpoint` becomes a `Device` whose `id` is the
|
|
25
|
+
* gateway-visible `deviceId`. Works wherever a `WebSocket` exists.
|
|
26
|
+
*/
|
|
27
|
+
export declare class NetworkAdapter implements Adapter {
|
|
28
|
+
private readonly logger;
|
|
29
|
+
private readonly listeners;
|
|
30
|
+
private readonly peers;
|
|
31
|
+
private readonly websocketCtor;
|
|
32
|
+
private readonly reconnectLadder;
|
|
33
|
+
private readonly discoverer;
|
|
34
|
+
private running;
|
|
35
|
+
constructor(options?: NetworkAdapterOptions);
|
|
36
|
+
on(listener: AdapterListener): void;
|
|
37
|
+
off(listener: AdapterListener): void;
|
|
38
|
+
start(): Promise<void>;
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
disconnect(deviceId: string): Promise<void>;
|
|
41
|
+
send(deviceId: string, frame: Uint8Array): Promise<void>;
|
|
42
|
+
private handleDiscovery;
|
|
43
|
+
private emit;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgB,eAAe,EAAU,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAU,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,CAAC;AAIpF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC;IAExD,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAE7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAAC;IAE/B,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,qBAAa,cAAe,YAAW,OAAO;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,qBAA0B;IAkB/C,EAAE,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAInC,GAAG,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,IAAI;CASb"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { Logger, LogVerbosity } from '@bridgething/lib';
|
|
2
|
+
import { StaticDiscoverer } from './discovery';
|
|
3
|
+
export { StaticDiscoverer };
|
|
4
|
+
const DEFAULT_RECONNECT_BACKOFF_MS = [500, 1_000, 2_000, 4_000, 8_000, 15_000];
|
|
5
|
+
/**
|
|
6
|
+
* Byte-level transport for `@bridgething/gateway` over the daemon's network gateway WebSocket.
|
|
7
|
+
* One instance can hold many peers; each `Endpoint` becomes a `Device` whose `id` is the
|
|
8
|
+
* gateway-visible `deviceId`. Works wherever a `WebSocket` exists.
|
|
9
|
+
*/
|
|
10
|
+
export class NetworkAdapter {
|
|
11
|
+
logger;
|
|
12
|
+
listeners = new Set();
|
|
13
|
+
peers = new Map();
|
|
14
|
+
websocketCtor;
|
|
15
|
+
reconnectLadder;
|
|
16
|
+
discoverer;
|
|
17
|
+
running = false;
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.logger = new Logger('NetworkAdapter', options.logLevel ?? LogVerbosity.Log);
|
|
20
|
+
this.websocketCtor =
|
|
21
|
+
options.websocket ?? (typeof WebSocket !== 'undefined' ? WebSocket : undefined);
|
|
22
|
+
if (!this.websocketCtor) {
|
|
23
|
+
throw new Error('NetworkAdapter: no global WebSocket. Pass `options.websocket` (e.g. import { WebSocket } from "ws" on older Node).');
|
|
24
|
+
}
|
|
25
|
+
this.reconnectLadder =
|
|
26
|
+
options.reconnect === false
|
|
27
|
+
? null
|
|
28
|
+
: Array.isArray(options.reconnect)
|
|
29
|
+
? options.reconnect
|
|
30
|
+
: DEFAULT_RECONNECT_BACKOFF_MS;
|
|
31
|
+
this.discoverer = resolveDiscoverer(options.discovery);
|
|
32
|
+
}
|
|
33
|
+
on(listener) {
|
|
34
|
+
this.listeners.add(listener);
|
|
35
|
+
}
|
|
36
|
+
off(listener) {
|
|
37
|
+
this.listeners.delete(listener);
|
|
38
|
+
}
|
|
39
|
+
async start() {
|
|
40
|
+
if (this.running)
|
|
41
|
+
return;
|
|
42
|
+
this.running = true;
|
|
43
|
+
await this.discoverer.start(event => this.handleDiscovery(event));
|
|
44
|
+
}
|
|
45
|
+
async stop() {
|
|
46
|
+
if (!this.running)
|
|
47
|
+
return;
|
|
48
|
+
this.running = false;
|
|
49
|
+
await this.discoverer.stop();
|
|
50
|
+
const peers = Array.from(this.peers.values());
|
|
51
|
+
this.peers.clear();
|
|
52
|
+
for (const peer of peers)
|
|
53
|
+
peer.shutdown('adapter-stop');
|
|
54
|
+
}
|
|
55
|
+
disconnect(deviceId) {
|
|
56
|
+
const peer = this.peers.get(deviceId);
|
|
57
|
+
if (!peer)
|
|
58
|
+
return Promise.resolve();
|
|
59
|
+
this.peers.delete(deviceId);
|
|
60
|
+
peer.shutdown('client-disconnect');
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
}
|
|
63
|
+
send(deviceId, frame) {
|
|
64
|
+
const peer = this.peers.get(deviceId);
|
|
65
|
+
if (!peer)
|
|
66
|
+
return Promise.reject(new Error(`network-adapter: no active peer for ${deviceId}`));
|
|
67
|
+
peer.send(frame);
|
|
68
|
+
return Promise.resolve();
|
|
69
|
+
}
|
|
70
|
+
handleDiscovery(event) {
|
|
71
|
+
if (event.type === 'found') {
|
|
72
|
+
const existing = this.peers.get(event.endpoint.id);
|
|
73
|
+
if (existing) {
|
|
74
|
+
existing.updateEndpoint(event.endpoint);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const peer = new Peer({
|
|
78
|
+
endpoint: event.endpoint,
|
|
79
|
+
websocketCtor: this.websocketCtor,
|
|
80
|
+
reconnectLadder: this.reconnectLadder,
|
|
81
|
+
logger: this.logger,
|
|
82
|
+
emit: e => this.emit(e),
|
|
83
|
+
});
|
|
84
|
+
this.peers.set(event.endpoint.id, peer);
|
|
85
|
+
peer.start();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const peer = this.peers.get(event.id);
|
|
89
|
+
if (!peer)
|
|
90
|
+
return;
|
|
91
|
+
this.peers.delete(event.id);
|
|
92
|
+
peer.shutdown('discoverer-lost');
|
|
93
|
+
}
|
|
94
|
+
emit(event) {
|
|
95
|
+
for (const listener of this.listeners) {
|
|
96
|
+
try {
|
|
97
|
+
listener(event);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
this.logger.error('listener threw', err);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function resolveDiscoverer(input) {
|
|
106
|
+
if (!input)
|
|
107
|
+
return new StaticDiscoverer({ url: defaultUrl() });
|
|
108
|
+
if (typeof input === 'string')
|
|
109
|
+
return new StaticDiscoverer({ url: input });
|
|
110
|
+
if (Array.isArray(input))
|
|
111
|
+
return new MultiStaticDiscoverer(input);
|
|
112
|
+
if (isDiscoverer(input))
|
|
113
|
+
return input;
|
|
114
|
+
return new StaticDiscoverer({ url: input.url, id: input.id, name: input.name });
|
|
115
|
+
}
|
|
116
|
+
function isDiscoverer(value) {
|
|
117
|
+
return ('start' in value &&
|
|
118
|
+
typeof value.start === 'function' &&
|
|
119
|
+
'stop' in value &&
|
|
120
|
+
typeof value.stop === 'function');
|
|
121
|
+
}
|
|
122
|
+
function defaultUrl() {
|
|
123
|
+
return 'ws://bridgething.local:8892/';
|
|
124
|
+
}
|
|
125
|
+
class MultiStaticDiscoverer {
|
|
126
|
+
endpoints;
|
|
127
|
+
started = false;
|
|
128
|
+
constructor(endpoints) {
|
|
129
|
+
this.endpoints = endpoints;
|
|
130
|
+
}
|
|
131
|
+
start(listener) {
|
|
132
|
+
if (this.started)
|
|
133
|
+
return Promise.resolve();
|
|
134
|
+
this.started = true;
|
|
135
|
+
for (const endpoint of this.endpoints) {
|
|
136
|
+
listener({ type: 'found', endpoint });
|
|
137
|
+
}
|
|
138
|
+
return Promise.resolve();
|
|
139
|
+
}
|
|
140
|
+
stop() {
|
|
141
|
+
this.started = false;
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
class Peer {
|
|
146
|
+
endpoint;
|
|
147
|
+
websocketCtor;
|
|
148
|
+
reconnectLadder;
|
|
149
|
+
logger;
|
|
150
|
+
emit;
|
|
151
|
+
socket = null;
|
|
152
|
+
connected = false;
|
|
153
|
+
intentionalClose = false;
|
|
154
|
+
reconnectTimer = null;
|
|
155
|
+
reconnectAttempt = 0;
|
|
156
|
+
sendQueue = [];
|
|
157
|
+
constructor(opts) {
|
|
158
|
+
this.endpoint = opts.endpoint;
|
|
159
|
+
this.websocketCtor = opts.websocketCtor;
|
|
160
|
+
this.reconnectLadder = opts.reconnectLadder;
|
|
161
|
+
this.logger = opts.logger;
|
|
162
|
+
this.emit = opts.emit;
|
|
163
|
+
}
|
|
164
|
+
start() {
|
|
165
|
+
this.openSocket();
|
|
166
|
+
}
|
|
167
|
+
updateEndpoint(next) {
|
|
168
|
+
const urlChanged = next.url !== this.endpoint.url;
|
|
169
|
+
this.endpoint = next;
|
|
170
|
+
if (!urlChanged)
|
|
171
|
+
return;
|
|
172
|
+
this.logger.log(`endpoint ${next.id} url changed to ${next.url}, reconnecting`);
|
|
173
|
+
this.reconnectSoon();
|
|
174
|
+
}
|
|
175
|
+
send(frame) {
|
|
176
|
+
if (this.socket && this.connected) {
|
|
177
|
+
try {
|
|
178
|
+
this.socket.send(toArrayBufferSlice(frame));
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
this.logger.warn(`send to ${this.endpoint.id} failed, queueing`, err);
|
|
182
|
+
this.sendQueue.push(frame);
|
|
183
|
+
this.reconnectSoon();
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this.sendQueue.push(frame);
|
|
188
|
+
}
|
|
189
|
+
shutdown(reason) {
|
|
190
|
+
this.intentionalClose = true;
|
|
191
|
+
if (this.reconnectTimer) {
|
|
192
|
+
clearTimeout(this.reconnectTimer);
|
|
193
|
+
this.reconnectTimer = null;
|
|
194
|
+
}
|
|
195
|
+
this.sendQueue = [];
|
|
196
|
+
const socket = this.socket;
|
|
197
|
+
this.socket = null;
|
|
198
|
+
if (socket) {
|
|
199
|
+
try {
|
|
200
|
+
socket.close(1000, reason);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// best-effort
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (this.connected) {
|
|
207
|
+
this.connected = false;
|
|
208
|
+
this.emit({ type: 'disconnected', deviceId: this.endpoint.id });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
openSocket() {
|
|
212
|
+
if (this.intentionalClose)
|
|
213
|
+
return;
|
|
214
|
+
let socket;
|
|
215
|
+
try {
|
|
216
|
+
socket = new this.websocketCtor(this.endpoint.url);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
this.logger.warn(`failed to construct websocket for ${this.endpoint.url}`, err);
|
|
220
|
+
this.scheduleReconnect();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
socket.binaryType = 'arraybuffer';
|
|
224
|
+
this.socket = socket;
|
|
225
|
+
socket.addEventListener('open', () => {
|
|
226
|
+
this.connected = true;
|
|
227
|
+
this.reconnectAttempt = 0;
|
|
228
|
+
this.emit({
|
|
229
|
+
type: 'connected',
|
|
230
|
+
device: this.deviceForEndpoint(),
|
|
231
|
+
});
|
|
232
|
+
this.flushQueue();
|
|
233
|
+
});
|
|
234
|
+
socket.addEventListener('message', event => this.handleMessage(event.data));
|
|
235
|
+
socket.addEventListener('close', () => {
|
|
236
|
+
this.socket = null;
|
|
237
|
+
if (this.connected) {
|
|
238
|
+
this.connected = false;
|
|
239
|
+
this.emit({ type: 'disconnected', deviceId: this.endpoint.id });
|
|
240
|
+
}
|
|
241
|
+
if (!this.intentionalClose)
|
|
242
|
+
this.scheduleReconnect();
|
|
243
|
+
});
|
|
244
|
+
socket.addEventListener('error', () => {
|
|
245
|
+
this.logger.trace(`ws error on ${this.endpoint.id}`);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
handleMessage(raw) {
|
|
249
|
+
let bytes = null;
|
|
250
|
+
if (raw instanceof ArrayBuffer)
|
|
251
|
+
bytes = new Uint8Array(raw);
|
|
252
|
+
else if (raw instanceof Uint8Array)
|
|
253
|
+
bytes = raw;
|
|
254
|
+
else if (ArrayBuffer.isView(raw)) {
|
|
255
|
+
const view = raw;
|
|
256
|
+
bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
257
|
+
}
|
|
258
|
+
else if (typeof raw === 'string') {
|
|
259
|
+
this.logger.warn(`unexpected text frame from ${this.endpoint.id}; network gateway is binary-only`);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
else if (raw && typeof raw.arrayBuffer === 'function') {
|
|
263
|
+
void raw
|
|
264
|
+
.arrayBuffer()
|
|
265
|
+
.then(buf => this.emit({ type: 'bytes', deviceId: this.endpoint.id, data: new Uint8Array(buf) }))
|
|
266
|
+
.catch(err => this.logger.warn(`failed to read Blob frame from ${this.endpoint.id}`, err));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (!bytes || bytes.byteLength === 0)
|
|
270
|
+
return;
|
|
271
|
+
this.emit({ type: 'bytes', deviceId: this.endpoint.id, data: bytes });
|
|
272
|
+
}
|
|
273
|
+
flushQueue() {
|
|
274
|
+
const queued = this.sendQueue;
|
|
275
|
+
this.sendQueue = [];
|
|
276
|
+
for (const frame of queued) {
|
|
277
|
+
if (!this.socket || !this.connected) {
|
|
278
|
+
this.sendQueue.push(frame);
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
this.socket.send(toArrayBufferSlice(frame));
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
this.logger.warn(`flush send to ${this.endpoint.id} failed`, err);
|
|
286
|
+
this.sendQueue.push(frame);
|
|
287
|
+
this.reconnectSoon();
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
reconnectSoon() {
|
|
293
|
+
if (this.intentionalClose)
|
|
294
|
+
return;
|
|
295
|
+
const socket = this.socket;
|
|
296
|
+
this.socket = null;
|
|
297
|
+
if (socket) {
|
|
298
|
+
try {
|
|
299
|
+
socket.close(1000, 'reconnect');
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
// best-effort
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (this.connected) {
|
|
306
|
+
this.connected = false;
|
|
307
|
+
this.emit({ type: 'disconnected', deviceId: this.endpoint.id });
|
|
308
|
+
}
|
|
309
|
+
this.scheduleReconnect();
|
|
310
|
+
}
|
|
311
|
+
scheduleReconnect() {
|
|
312
|
+
if (!this.reconnectLadder)
|
|
313
|
+
return;
|
|
314
|
+
const idx = Math.min(this.reconnectAttempt, this.reconnectLadder.length - 1);
|
|
315
|
+
const delay = this.reconnectLadder[idx];
|
|
316
|
+
this.reconnectAttempt += 1;
|
|
317
|
+
if (this.reconnectTimer)
|
|
318
|
+
clearTimeout(this.reconnectTimer);
|
|
319
|
+
this.reconnectTimer = setTimeout(() => {
|
|
320
|
+
this.reconnectTimer = null;
|
|
321
|
+
this.openSocket();
|
|
322
|
+
}, delay);
|
|
323
|
+
}
|
|
324
|
+
deviceForEndpoint() {
|
|
325
|
+
return {
|
|
326
|
+
id: this.endpoint.id,
|
|
327
|
+
name: this.endpoint.name ?? this.endpoint.url,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* DOM type checking rejects `Uint8Array<ArrayBufferLike>` because the union includes
|
|
333
|
+
* `SharedArrayBuffer`. The codec only produces `ArrayBuffer`-backed views, so this slice is safe.
|
|
334
|
+
*/
|
|
335
|
+
function toArrayBufferSlice(frame) {
|
|
336
|
+
const buffer = frame.buffer;
|
|
337
|
+
if (buffer instanceof ArrayBuffer && frame.byteOffset === 0 && frame.byteLength === buffer.byteLength) {
|
|
338
|
+
return buffer;
|
|
339
|
+
}
|
|
340
|
+
const out = new ArrayBuffer(frame.byteLength);
|
|
341
|
+
new Uint8Array(out).set(frame);
|
|
342
|
+
return out;
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/mdns.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Discoverer, DiscoveryListener } from './discovery';
|
|
2
|
+
export type MDNSDiscovererOptions = {
|
|
3
|
+
/** Service type without the `_…._tcp` decoration. Defaults to `bridgething`. */
|
|
4
|
+
serviceType?: string;
|
|
5
|
+
/** Override the URL builder. Default builds `ws://<host>:<port>/`. */
|
|
6
|
+
buildUrl?: (service: {
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
addresses: string[];
|
|
10
|
+
nickname?: string;
|
|
11
|
+
}) => string;
|
|
12
|
+
};
|
|
13
|
+
export declare class MDNSDiscoverer implements Discoverer {
|
|
14
|
+
private readonly serviceType;
|
|
15
|
+
private readonly buildUrl;
|
|
16
|
+
private bonjour;
|
|
17
|
+
private browser;
|
|
18
|
+
private readonly seen;
|
|
19
|
+
constructor(options?: MDNSDiscovererOptions);
|
|
20
|
+
start(listener: (event: DiscoveryListener) => void): Promise<void>;
|
|
21
|
+
stop(): Promise<void>;
|
|
22
|
+
private endpointFor;
|
|
23
|
+
}
|
|
24
|
+
/** Convenience factory mirroring the daemon's defaults. */
|
|
25
|
+
export declare function discoverBridgethingDaemons(options?: MDNSDiscovererOptions): MDNSDiscoverer;
|
|
26
|
+
//# sourceMappingURL=mdns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdns.d.ts","sourceRoot":"","sources":["../src/mdns.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAY,MAAM,aAAa,CAAC;AAgC3E,MAAM,MAAM,qBAAqB,GAAG;IAClC,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CACxG,CAAC;AAEF,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiD;IAC1E,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA+B;gBAExC,OAAO,GAAE,qBAA0B;IAKzC,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBxE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,OAAO,CAAC,WAAW;CAkBpB;AAED,2DAA2D;AAC3D,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,cAAc,CAM1F"}
|
package/dist/mdns.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { BRIDGETHING_MDNS_SERVICE_TYPE, BRIDGETHING_NETWORK_GATEWAY_PORT } from '@bridgething/lib';
|
|
2
|
+
export class MDNSDiscoverer {
|
|
3
|
+
serviceType;
|
|
4
|
+
buildUrl;
|
|
5
|
+
bonjour = null;
|
|
6
|
+
browser = null;
|
|
7
|
+
seen = new Map();
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.serviceType = options.serviceType ?? BRIDGETHING_MDNS_SERVICE_TYPE;
|
|
10
|
+
this.buildUrl = options.buildUrl ?? (({ host, port }) => `ws://${host}:${port}/`);
|
|
11
|
+
}
|
|
12
|
+
async start(listener) {
|
|
13
|
+
if (this.bonjour)
|
|
14
|
+
return;
|
|
15
|
+
const { Bonjour } = await loadBonjour();
|
|
16
|
+
this.bonjour = new Bonjour();
|
|
17
|
+
const handleUp = (svc) => {
|
|
18
|
+
const endpoint = this.endpointFor(svc);
|
|
19
|
+
if (!endpoint)
|
|
20
|
+
return;
|
|
21
|
+
const existing = this.seen.get(endpoint.id);
|
|
22
|
+
if (existing && existing.url === endpoint.url)
|
|
23
|
+
return;
|
|
24
|
+
this.seen.set(endpoint.id, endpoint);
|
|
25
|
+
listener({ type: 'found', endpoint });
|
|
26
|
+
};
|
|
27
|
+
const handleDown = (svc) => {
|
|
28
|
+
const id = serviceId(svc);
|
|
29
|
+
if (!this.seen.delete(id))
|
|
30
|
+
return;
|
|
31
|
+
listener({ type: 'lost', id });
|
|
32
|
+
};
|
|
33
|
+
this.browser = this.bonjour.find({ type: this.serviceType, protocol: 'tcp' }, handleUp);
|
|
34
|
+
this.browser.on('up', handleUp);
|
|
35
|
+
this.browser.on('down', handleDown);
|
|
36
|
+
}
|
|
37
|
+
stop() {
|
|
38
|
+
this.browser?.stop();
|
|
39
|
+
this.browser = null;
|
|
40
|
+
this.bonjour?.destroy();
|
|
41
|
+
this.bonjour = null;
|
|
42
|
+
this.seen.clear();
|
|
43
|
+
return Promise.resolve();
|
|
44
|
+
}
|
|
45
|
+
endpointFor(svc) {
|
|
46
|
+
if (!svc.host || !svc.port)
|
|
47
|
+
return null;
|
|
48
|
+
const addresses = svc.addresses ?? [];
|
|
49
|
+
const txt = normalizeTxt(svc.txt);
|
|
50
|
+
const nickname = txt['nickname'];
|
|
51
|
+
const url = this.buildUrl({
|
|
52
|
+
host: svc.host,
|
|
53
|
+
port: svc.port,
|
|
54
|
+
addresses,
|
|
55
|
+
nickname,
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
id: serviceId(svc),
|
|
59
|
+
url,
|
|
60
|
+
name: nickname || svc.name,
|
|
61
|
+
metadata: txt,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Convenience factory mirroring the daemon's defaults. */
|
|
66
|
+
export function discoverBridgethingDaemons(options) {
|
|
67
|
+
return new MDNSDiscoverer({
|
|
68
|
+
serviceType: BRIDGETHING_MDNS_SERVICE_TYPE,
|
|
69
|
+
buildUrl: ({ host, port }) => `ws://${host}:${port || BRIDGETHING_NETWORK_GATEWAY_PORT}/`,
|
|
70
|
+
...options,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function serviceId(svc) {
|
|
74
|
+
return svc.fqdn ?? `${svc.name}.${svc.type}.${svc.protocol}`;
|
|
75
|
+
}
|
|
76
|
+
function normalizeTxt(txt) {
|
|
77
|
+
if (!txt)
|
|
78
|
+
return {};
|
|
79
|
+
const out = {};
|
|
80
|
+
for (const [key, value] of Object.entries(txt)) {
|
|
81
|
+
if (typeof value === 'string') {
|
|
82
|
+
out[key] = value;
|
|
83
|
+
}
|
|
84
|
+
else if (value instanceof Uint8Array) {
|
|
85
|
+
out[key] = new TextDecoder().decode(value);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
out[key] = String(value);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
async function loadBonjour() {
|
|
94
|
+
try {
|
|
95
|
+
const mod = (await import('bonjour-service'));
|
|
96
|
+
if (mod.Bonjour)
|
|
97
|
+
return { Bonjour: mod.Bonjour };
|
|
98
|
+
if (mod.default?.Bonjour)
|
|
99
|
+
return { Bonjour: mod.default.Bonjour };
|
|
100
|
+
throw new Error('bonjour-service module did not export Bonjour');
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
throw new Error(`@bridgething/adapter-network: MDNSDiscoverer needs the optional 'bonjour-service' dependency. ` +
|
|
104
|
+
`Install it with 'bun add bonjour-service'. Underlying: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=mdns.js.map
|
package/dist/mdns.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdns.js","sourceRoot":"","sources":["../src/mdns.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bridgething/adapter-network",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Network-gateway WebSocket transport for @bridgething/gateway.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Joey Eamigh <55670930+JoeyEamigh@users.noreply.github.com> (https://github.com/JoeyEamigh)",
|
|
7
|
+
"homepage": "https://bridgething.com",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/JoeyEamigh/bridgething.git",
|
|
11
|
+
"directory": "packages/adapter-network"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/JoeyEamigh/bridgething/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": ["bridgething", "spotify", "car-thing", "superbird", "websocket", "transport"],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public",
|
|
19
|
+
"registry": "https://registry.npmjs.org/"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./mdns": {
|
|
29
|
+
"types": "./dist/mdns.d.ts",
|
|
30
|
+
"default": "./dist/mdns.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": ["dist"],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"prebuild": "rm -rf dist",
|
|
36
|
+
"build": "tsc -p tsconfig.build.json",
|
|
37
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"lint": "eslint ."
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@bridgething/gateway": "0.1.4",
|
|
43
|
+
"@bridgething/lib": "0.1.4"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"bonjour-service": "^1.3.0",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"bonjour-service": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|