@enbox/local-node 0.0.1

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.
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env bun
2
+ import { AllowOriginPairingBroker, LocalNode, TtyPairingBroker } from './index.js';
3
+ function parseArgs(args) {
4
+ const options = {
5
+ allowedOrigins: [],
6
+ help: false,
7
+ webSocketSupport: true,
8
+ };
9
+ for (let i = 0; i < args.length; i += 1) {
10
+ const arg = args[i];
11
+ if (arg === '--help' || arg === '-h') {
12
+ options.help = true;
13
+ }
14
+ else if (arg === '--allow-origin') {
15
+ options.allowedOrigins.push(readValue(args, i, arg));
16
+ i += 1;
17
+ }
18
+ else if (arg === '--host') {
19
+ options.hostname = readValue(args, i, arg);
20
+ i += 1;
21
+ }
22
+ else if (arg === '--no-ws') {
23
+ options.webSocketSupport = false;
24
+ }
25
+ else if (arg === '--port') {
26
+ options.port = parsePort(readValue(args, i, arg));
27
+ i += 1;
28
+ }
29
+ else if (arg === '--storage-url') {
30
+ options.storageUrl = readValue(args, i, arg);
31
+ i += 1;
32
+ }
33
+ else {
34
+ throw new Error(`Unknown option: ${arg}`);
35
+ }
36
+ }
37
+ return options;
38
+ }
39
+ function readValue(args, index, flag) {
40
+ const value = args[index + 1];
41
+ if (value === undefined || value.startsWith('-')) {
42
+ throw new Error(`${flag} requires a value.`);
43
+ }
44
+ return value;
45
+ }
46
+ function parsePort(value) {
47
+ const port = Number.parseInt(value, 10);
48
+ if (!Number.isInteger(port) || port <= 0 || port > 65_535) {
49
+ throw new Error(`Invalid port: ${value}`);
50
+ }
51
+ return port;
52
+ }
53
+ function printHelp() {
54
+ console.log(`Usage: enbox-local-node [options]
55
+
56
+ Options:
57
+ --allow-origin <origin> Auto-approve a browser origin for dev/CI. Repeatable.
58
+ --host <hostname> Loopback bind hostname. Defaults to 127.0.0.1.
59
+ --port <port> Bind a single port instead of the shared candidate list.
60
+ --storage-url <url> DWN Level/SQL storage URL. Defaults to dwn-server config.
61
+ --no-ws Disable WebSocket support.
62
+ -h, --help Show this help text.
63
+ `);
64
+ }
65
+ async function run() {
66
+ const options = parseArgs(process.argv.slice(2));
67
+ if (options.help) {
68
+ printHelp();
69
+ return;
70
+ }
71
+ const node = new LocalNode({
72
+ allowedOrigins: options.allowedOrigins,
73
+ hostname: options.hostname,
74
+ pairingBroker: new AllowOriginPairingBroker(options.allowedOrigins, new TtyPairingBroker()),
75
+ portCandidates: options.port === undefined ? undefined : [options.port],
76
+ storageUrl: options.storageUrl,
77
+ webSocketSupport: options.webSocketSupport,
78
+ });
79
+ const result = await node.start();
80
+ console.log(`Enbox local node listening on ${result.endpoint}`);
81
+ console.log(`Discovery file: ${result.discoveryFilePath}`);
82
+ const shutdown = async () => {
83
+ await node.stop();
84
+ process.exit(0);
85
+ };
86
+ process.on('SIGINT', () => {
87
+ void shutdown();
88
+ });
89
+ process.on('SIGTERM', () => {
90
+ void shutdown();
91
+ });
92
+ await new Promise(() => { });
93
+ }
94
+ try {
95
+ await run();
96
+ }
97
+ catch (error) {
98
+ console.error(error);
99
+ process.exit(1);
100
+ }
101
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,wBAAwB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAWnF,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,OAAO,GAAe;QAC1B,cAAc,EAAK,EAAE;QACrB,IAAI,EAAe,KAAK;QACxB,gBAAgB,EAAG,IAAI;KACxB,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;YACpC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrD,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YAC3C,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,CAAC,gBAAgB,GAAG,KAAK,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAClD,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YACnC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,KAAa,EAAE,IAAY;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;CASb,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC;QACzB,cAAc,EAAK,OAAO,CAAC,cAAc;QACzC,QAAQ,EAAW,OAAO,CAAC,QAAQ;QACnC,aAAa,EAAM,IAAI,wBAAwB,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,gBAAgB,EAAE,CAAC;QAC/F,cAAc,EAAK,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC1E,UAAU,EAAS,OAAO,CAAC,UAAU;QACrC,gBAAgB,EAAG,OAAO,CAAC,gBAAgB;KAC5C,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAE3D,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,KAAK,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACzB,KAAK,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAC,GAAS,EAAE,GAAE,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,IAAI,CAAC;IACH,MAAM,GAAG,EAAE,CAAC;AACd,CAAC;AAAC,OAAO,KAAc,EAAE,CAAC;IACxB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './local-node.js';
2
+ export * from './local-node-config.js';
3
+ export * from './pairing-session-store.js';
4
+ export * from './pairing-broker.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { defaultDwnServerConfig } from '@enbox/dwn-server';
5
+ export const defaultLocalNodeHostname = '127.0.0.1';
6
+ export const defaultLocalNodeStorageUrl = pathToFileURL(join(homedir(), '.enbox', 'dwn')).href.replace('file:', 'level:');
7
+ export function createLocalNodeDwnServerConfig(options) {
8
+ const hostname = options.hostname ?? defaultLocalNodeHostname;
9
+ const storageUrl = options.storageUrl ?? process.env.DWN_STORAGE ?? defaultLocalNodeStorageUrl;
10
+ return {
11
+ ...defaultDwnServerConfig,
12
+ baseUrl: options.baseUrl ?? `http://${hostname}:${options.port}`,
13
+ dataStore: options.dataStore ?? process.env.DWN_STORAGE_DATA ?? storageUrl,
14
+ deliveryEnabled: options.deliveryEnabled ?? true,
15
+ eventBusPluginPath: options.eventBusPluginPath ?? defaultDwnServerConfig.eventBusPluginPath,
16
+ forwardingEnabled: options.forwardingEnabled ?? true,
17
+ hostname,
18
+ localNodeAllowedOrigins: options.allowedOrigins ?? [],
19
+ localNodeProfileEnabled: true,
20
+ logLevel: options.logLevel ?? defaultDwnServerConfig.logLevel,
21
+ maxRecordDataSize: options.maxRecordDataSize ?? 1_073_741_824,
22
+ messageStore: options.messageStore ?? process.env.DWN_STORAGE_MESSAGES ?? storageUrl,
23
+ packageJsonPath: options.packageJsonPath ?? defaultDwnServerConfig.packageJsonPath,
24
+ port: options.port,
25
+ registrationStoreUrl: options.registrationStoreUrl ?? defaultDwnServerConfig.registrationStoreUrl,
26
+ resumableTaskStore: options.resumableTaskStore ?? process.env.DWN_STORAGE_RESUMABLE_TASKS ?? storageUrl,
27
+ serverName: options.serverName ?? defaultDwnServerConfig.serverName,
28
+ termsOfServiceFilePath: options.termsOfServiceFilePath ?? defaultDwnServerConfig.termsOfServiceFilePath,
29
+ ttlCacheUrl: options.ttlCacheUrl ?? defaultDwnServerConfig.ttlCacheUrl,
30
+ webSocketSupport: options.webSocketSupport ?? defaultDwnServerConfig.webSocketSupport,
31
+ };
32
+ }
33
+ //# sourceMappingURL=local-node-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-node-config.js","sourceRoot":"","sources":["../../src/local-node-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAwB3D,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CAAC;AACpD,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAE1H,MAAM,UAAU,8BAA8B,CAAC,OAAqC;IAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAwB,CAAC;IAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,0BAA0B,CAAC;IAE/F,OAAO;QACL,GAAG,sBAAsB;QACzB,OAAO,EAAmB,OAAO,CAAC,OAAO,IAAI,UAAU,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;QACjF,SAAS,EAAiB,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,UAAU;QACzF,eAAe,EAAW,OAAO,CAAC,eAAe,IAAI,IAAI;QACzD,kBAAkB,EAAQ,OAAO,CAAC,kBAAkB,IAAI,sBAAsB,CAAC,kBAAkB;QACjG,iBAAiB,EAAS,OAAO,CAAC,iBAAiB,IAAI,IAAI;QAC3D,QAAQ;QACR,uBAAuB,EAAG,OAAO,CAAC,cAAc,IAAI,EAAE;QACtD,uBAAuB,EAAG,IAAI;QAC9B,QAAQ,EAAkB,OAAO,CAAC,QAAQ,IAAI,sBAAsB,CAAC,QAAQ;QAC7E,iBAAiB,EAAS,OAAO,CAAC,iBAAiB,IAAI,aAAa;QACpE,YAAY,EAAc,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,UAAU;QAChG,eAAe,EAAW,OAAO,CAAC,eAAe,IAAI,sBAAsB,CAAC,eAAe;QAC3F,IAAI,EAAsB,OAAO,CAAC,IAAI;QACtC,oBAAoB,EAAM,OAAO,CAAC,oBAAoB,IAAI,sBAAsB,CAAC,oBAAoB;QACrG,kBAAkB,EAAQ,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,UAAU;QAC7G,UAAU,EAAgB,OAAO,CAAC,UAAU,IAAI,sBAAsB,CAAC,UAAU;QACjF,sBAAsB,EAAI,OAAO,CAAC,sBAAsB,IAAI,sBAAsB,CAAC,sBAAsB;QACzG,WAAW,EAAe,OAAO,CAAC,WAAW,IAAI,sBAAsB,CAAC,WAAW;QACnF,gBAAgB,EAAU,OAAO,CAAC,gBAAgB,IAAI,sBAAsB,CAAC,gBAAgB;KAC9F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,395 @@
1
+ var _a;
2
+ import { DwnDiscoveryFile as DefaultDwnDiscoveryFile, localDwnPortCandidates, localDwnServerName, } from '@enbox/agent';
3
+ import { LocalNodePairingManager as DefaultLocalNodePairingManager, DwnServer } from '@enbox/dwn-server';
4
+ import { createLocalNodeDwnServerConfig } from './local-node-config.js';
5
+ import { LocalNodePairingSessionFile } from './pairing-session-store.js';
6
+ export class LocalNodeAlreadyRunningError extends Error {
7
+ endpoint;
8
+ pid;
9
+ constructor(existingNode) {
10
+ super(`LocalNode: local node is already running at ${existingNode.endpoint}.`);
11
+ this.name = 'LocalNodeAlreadyRunningError';
12
+ this.endpoint = existingNode.endpoint;
13
+ this.pid = existingNode.pid;
14
+ }
15
+ }
16
+ export class LocalNode {
17
+ #allowedOrigins;
18
+ #configOptions;
19
+ #createServer;
20
+ #discoveryFile;
21
+ #fetch;
22
+ #pairingBroker;
23
+ #pairingManager;
24
+ #pairingPollIntervalMs;
25
+ #pairingSessionStore;
26
+ #pid;
27
+ #portCandidates;
28
+ #endpoint;
29
+ #localNodeToken;
30
+ #pairingBrokerLoopFailure;
31
+ #pairingBrokerProcessing;
32
+ #pairingBrokerTimer;
33
+ #pairingSessionChangeUnsubscribe;
34
+ #pairingSessionWriteFailure;
35
+ #pairingSessionWriteQueue = Promise.resolve();
36
+ #port;
37
+ #server;
38
+ #state = 'stopped';
39
+ constructor(options = {}) {
40
+ this.#allowedOrigins = options.allowedOrigins ?? [];
41
+ this.#configOptions = {
42
+ baseUrl: options.baseUrl,
43
+ dataStore: options.dataStore,
44
+ deliveryEnabled: options.deliveryEnabled,
45
+ eventBusPluginPath: options.eventBusPluginPath,
46
+ forwardingEnabled: options.forwardingEnabled,
47
+ hostname: options.hostname,
48
+ logLevel: options.logLevel,
49
+ maxRecordDataSize: options.maxRecordDataSize,
50
+ messageStore: options.messageStore,
51
+ packageJsonPath: options.packageJsonPath,
52
+ registrationStoreUrl: options.registrationStoreUrl,
53
+ resumableTaskStore: options.resumableTaskStore,
54
+ serverName: options.serverName,
55
+ storageUrl: options.storageUrl,
56
+ termsOfServiceFilePath: options.termsOfServiceFilePath,
57
+ ttlCacheUrl: options.ttlCacheUrl,
58
+ webSocketSupport: options.webSocketSupport,
59
+ };
60
+ this.#createServer = options.createServer ?? _a.#createDwnServer;
61
+ this.#discoveryFile = options.discoveryFile ?? new DefaultDwnDiscoveryFile();
62
+ this.#fetch = options.fetch ?? fetch;
63
+ this.#pairingBroker = options.pairingBroker;
64
+ this.#pairingManager = options.pairingManager ?? new DefaultLocalNodePairingManager();
65
+ this.#pairingPollIntervalMs = options.pairingPollIntervalMs ?? 500;
66
+ this.#pairingSessionStore = options.pairingSessionStore ?? new LocalNodePairingSessionFile();
67
+ this.#pid = options.pid ?? process.pid;
68
+ this.#portCandidates = options.portCandidates ?? localDwnPortCandidates;
69
+ }
70
+ get discoveryFilePath() {
71
+ return this.#discoveryFile.path;
72
+ }
73
+ get endpoint() {
74
+ return this.#endpoint;
75
+ }
76
+ get pairingManager() {
77
+ return this.#pairingManager;
78
+ }
79
+ get state() {
80
+ return this.#state;
81
+ }
82
+ async start() {
83
+ if (this.#state === 'running') {
84
+ return this.#getStartResult();
85
+ }
86
+ const existingNode = await this.findExistingNode();
87
+ if (existingNode !== undefined) {
88
+ throw new LocalNodeAlreadyRunningError(existingNode);
89
+ }
90
+ await this.#loadPairingSessions();
91
+ const localNodeToken = this.#pairingManager.createSession(undefined);
92
+ this.#subscribeToPairingSessionChanges();
93
+ try {
94
+ const startResult = await this.#startFirstAvailableServer();
95
+ this.#server = startResult.server;
96
+ this.#port = startResult.port;
97
+ this.#endpoint = startResult.endpoint;
98
+ this.#localNodeToken = localNodeToken;
99
+ this.#state = 'running';
100
+ await this.#writeDiscoveryFile();
101
+ this.#startPairingBrokerLoop();
102
+ }
103
+ catch (error) {
104
+ await this.#cleanupStartedServer();
105
+ throw error;
106
+ }
107
+ return this.#getStartResult();
108
+ }
109
+ async stop() {
110
+ if (this.#state === 'stopped') {
111
+ return;
112
+ }
113
+ this.#stopPairingBrokerLoop();
114
+ let stopFailure;
115
+ try {
116
+ await this.#discoveryFile.remove();
117
+ }
118
+ catch (error) {
119
+ stopFailure = { error };
120
+ }
121
+ try {
122
+ await this.#server?.stop();
123
+ }
124
+ catch (error) {
125
+ stopFailure ??= { error };
126
+ }
127
+ this.#unsubscribeFromPairingSessionChanges();
128
+ try {
129
+ await this.#flushPairingSessionWrites();
130
+ }
131
+ catch (error) {
132
+ stopFailure ??= { error };
133
+ }
134
+ stopFailure ??= this.#pairingBrokerLoopFailure;
135
+ this.#endpoint = undefined;
136
+ this.#localNodeToken = undefined;
137
+ this.#pairingBrokerLoopFailure = undefined;
138
+ this.#port = undefined;
139
+ this.#server = undefined;
140
+ this.#state = 'stopped';
141
+ if (stopFailure !== undefined) {
142
+ throw stopFailure.error;
143
+ }
144
+ }
145
+ async findExistingNode() {
146
+ const record = await this.#discoveryFile.read();
147
+ if (record === undefined) {
148
+ return undefined;
149
+ }
150
+ const isLive = await this.#isLiveLocalNode(record.endpoint);
151
+ if (!isLive) {
152
+ await this.#discoveryFile.remove();
153
+ return undefined;
154
+ }
155
+ return {
156
+ endpoint: record.endpoint,
157
+ pid: record.pid,
158
+ };
159
+ }
160
+ getStatus() {
161
+ return {
162
+ discoveryFilePath: this.#discoveryFile.path,
163
+ endpoint: this.#endpoint,
164
+ localNodeToken: this.#localNodeToken,
165
+ pendingPairingRequests: this.#pairingManager.listPendingRequests(),
166
+ pid: this.#pid,
167
+ port: this.#port,
168
+ state: this.#state,
169
+ webSocketSupport: this.#configOptions.webSocketSupport ?? true,
170
+ };
171
+ }
172
+ async revokePairingToken(token) {
173
+ const revoked = this.#server?.revokeLocalNodePairingToken !== undefined
174
+ ? await this.#server.revokeLocalNodePairingToken(token)
175
+ : this.#pairingManager.revokeToken(token);
176
+ if (!revoked) {
177
+ return false;
178
+ }
179
+ await this.#flushPairingSessionWrites();
180
+ return true;
181
+ }
182
+ async processPendingPairingRequests() {
183
+ if (this.#pairingBroker === undefined) {
184
+ return;
185
+ }
186
+ if (this.#pairingBrokerProcessing !== undefined) {
187
+ await this.#pairingBrokerProcessing;
188
+ return;
189
+ }
190
+ const processing = this.#processPendingPairingRequests();
191
+ this.#pairingBrokerProcessing = processing;
192
+ try {
193
+ await processing;
194
+ }
195
+ finally {
196
+ this.#pairingBrokerProcessing = undefined;
197
+ }
198
+ }
199
+ async #processPendingPairingRequests() {
200
+ const pendingRequests = this.#pairingManager.listPendingRequests();
201
+ for (const request of pendingRequests) {
202
+ await this.#processPairingRequest(request);
203
+ }
204
+ }
205
+ static #createDwnServer(config, pairingManager) {
206
+ return new DwnServer({
207
+ config,
208
+ localNodePairingManager: pairingManager,
209
+ });
210
+ }
211
+ async #startFirstAvailableServer() {
212
+ for (const port of this.#portCandidates) {
213
+ const config = createLocalNodeDwnServerConfig({
214
+ ...this.#configOptions,
215
+ allowedOrigins: this.#allowedOrigins,
216
+ port,
217
+ });
218
+ const server = this.#createServer(config, this.#pairingManager);
219
+ try {
220
+ await server.start();
221
+ return {
222
+ endpoint: config.baseUrl,
223
+ port,
224
+ server,
225
+ };
226
+ }
227
+ catch (error) {
228
+ await _a.#closeFailedServer(server);
229
+ if (!isAddressInUseError(error) || this.#portCandidates.length === 1) {
230
+ throw error;
231
+ }
232
+ }
233
+ }
234
+ throw new Error(`LocalNode: no available port found in ${Array.from(this.#portCandidates).join(', ')}.`);
235
+ }
236
+ async #writeDiscoveryFile() {
237
+ if (this.#endpoint === undefined || this.#localNodeToken === undefined) {
238
+ throw new Error('LocalNode: cannot write discovery file before the node has started.');
239
+ }
240
+ const capabilities = this.#configOptions.webSocketSupport === false ? ['http'] : ['http', 'ws'];
241
+ const record = {
242
+ capabilities,
243
+ endpoint: this.#endpoint,
244
+ localNodeToken: this.#localNodeToken,
245
+ pid: this.#pid,
246
+ };
247
+ await this.#discoveryFile.write(record);
248
+ }
249
+ #startPairingBrokerLoop() {
250
+ if (this.#pairingBroker === undefined || this.#pairingBrokerTimer !== undefined) {
251
+ return;
252
+ }
253
+ void this.processPendingPairingRequests().catch((error) => {
254
+ this.#pairingBrokerLoopFailure ??= { error };
255
+ });
256
+ this.#pairingBrokerTimer = setInterval(() => {
257
+ void this.processPendingPairingRequests().catch((error) => {
258
+ this.#pairingBrokerLoopFailure ??= { error };
259
+ });
260
+ }, this.#pairingPollIntervalMs);
261
+ }
262
+ #stopPairingBrokerLoop() {
263
+ if (this.#pairingBrokerTimer === undefined) {
264
+ return;
265
+ }
266
+ clearInterval(this.#pairingBrokerTimer);
267
+ this.#pairingBrokerTimer = undefined;
268
+ }
269
+ async #processPairingRequest(request) {
270
+ const decision = await this.#pairingBroker.decidePairingRequest(request);
271
+ if (decision === 'approve') {
272
+ const approved = this.#pairingManager.approveRequest(request.id);
273
+ if (approved) {
274
+ await this.#flushPairingSessionWrites();
275
+ }
276
+ }
277
+ else {
278
+ this.#pairingManager.denyRequest(request.id);
279
+ }
280
+ }
281
+ async #isLiveLocalNode(endpoint) {
282
+ try {
283
+ const endpointWithTrailingSlash = endpoint.endsWith('/') ? endpoint : `${endpoint}/`;
284
+ const response = await this.#fetch(new URL('info', endpointWithTrailingSlash).toString());
285
+ if (!response.ok) {
286
+ return false;
287
+ }
288
+ const serverInfo = await response.json();
289
+ return serverInfo.server === localDwnServerName && serverInfo.localNode === true;
290
+ }
291
+ catch {
292
+ return false;
293
+ }
294
+ }
295
+ async #loadPairingSessions() {
296
+ const sessions = await this.#pairingSessionStore.read();
297
+ this.#pairingManager.importSessions(sessions);
298
+ }
299
+ #subscribeToPairingSessionChanges() {
300
+ this.#pairingSessionChangeUnsubscribe = this.#pairingManager.onSessionsChanged((sessions) => {
301
+ const browserSessions = sessions
302
+ .filter((session) => session.origin !== undefined);
303
+ this.#pairingSessionWriteQueue = this.#pairingSessionWriteQueue.then(async () => {
304
+ try {
305
+ await this.#pairingSessionStore.write(browserSessions);
306
+ }
307
+ catch (error) {
308
+ this.#pairingSessionWriteFailure ??= { error };
309
+ }
310
+ });
311
+ });
312
+ }
313
+ #unsubscribeFromPairingSessionChanges() {
314
+ this.#pairingSessionChangeUnsubscribe?.();
315
+ this.#pairingSessionChangeUnsubscribe = undefined;
316
+ }
317
+ async #flushPairingSessionWrites() {
318
+ let pendingWrites;
319
+ do {
320
+ pendingWrites = this.#pairingSessionWriteQueue;
321
+ await pendingWrites;
322
+ } while (pendingWrites !== this.#pairingSessionWriteQueue);
323
+ const failure = this.#pairingSessionWriteFailure;
324
+ this.#pairingSessionWriteFailure = undefined;
325
+ if (failure !== undefined) {
326
+ throw failure.error;
327
+ }
328
+ }
329
+ async #waitForPairingSessionWrites() {
330
+ let pendingWrites;
331
+ do {
332
+ pendingWrites = this.#pairingSessionWriteQueue;
333
+ await pendingWrites;
334
+ } while (pendingWrites !== this.#pairingSessionWriteQueue);
335
+ }
336
+ #getStartResult() {
337
+ if (this.#endpoint === undefined || this.#localNodeToken === undefined || this.#port === undefined) {
338
+ throw new Error('LocalNode: node is not running.');
339
+ }
340
+ return {
341
+ discoveryFilePath: this.#discoveryFile.path,
342
+ endpoint: this.#endpoint,
343
+ localNodeToken: this.#localNodeToken,
344
+ pid: this.#pid,
345
+ port: this.#port,
346
+ };
347
+ }
348
+ static async #closeFailedServer(server) {
349
+ try {
350
+ await server.stop();
351
+ }
352
+ catch {
353
+ // Best-effort cleanup for partially-started servers.
354
+ }
355
+ try {
356
+ await server.dwn?.close();
357
+ }
358
+ catch {
359
+ // Best-effort cleanup for partially-created DWN instances.
360
+ }
361
+ }
362
+ async #cleanupStartedServer() {
363
+ this.#stopPairingBrokerLoop();
364
+ try {
365
+ await this.#server?.stop();
366
+ }
367
+ finally {
368
+ this.#unsubscribeFromPairingSessionChanges();
369
+ await this.#waitForPairingSessionWrites();
370
+ this.#endpoint = undefined;
371
+ this.#localNodeToken = undefined;
372
+ this.#pairingBrokerLoopFailure = undefined;
373
+ this.#port = undefined;
374
+ this.#server = undefined;
375
+ this.#state = 'stopped';
376
+ }
377
+ }
378
+ }
379
+ _a = LocalNode;
380
+ function isAddressInUseError(error) {
381
+ if (!error || typeof error !== 'object') {
382
+ return false;
383
+ }
384
+ const maybeCode = error.code;
385
+ if (maybeCode === 'EADDRINUSE') {
386
+ return true;
387
+ }
388
+ const maybeMessage = error.message;
389
+ if (typeof maybeMessage === 'string' && maybeMessage.toLowerCase().includes('address already in use')) {
390
+ return true;
391
+ }
392
+ const maybeCause = error.cause;
393
+ return isAddressInUseError(maybeCause);
394
+ }
395
+ //# sourceMappingURL=local-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-node.js","sourceRoot":"","sources":["../../src/local-node.ts"],"names":[],"mappings":";AAWA,OAAO,EACL,gBAAgB,IAAI,uBAAuB,EAC3C,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,IAAI,8BAA8B,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEzG,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAqDzE,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrC,QAAQ,CAAS;IACjB,GAAG,CAAS;IAE5B,YAAmB,YAA+B;QAChD,KAAK,CAAC,+CAA+C,YAAY,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;QACtC,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,SAAS;IACX,eAAe,CAAW;IAC1B,cAAc,CAAgE;IAC9E,aAAa,CAA2F;IACxG,cAAc,CAAmB;IACjC,MAAM,CAAe;IACrB,cAAc,CAA4B;IAC1C,eAAe,CAA0B;IACzC,sBAAsB,CAAS;IAC/B,oBAAoB,CAA+B;IACnD,IAAI,CAAS;IACb,eAAe,CAAoB;IAE5C,SAAS,CAAqB;IAC9B,eAAe,CAAqB;IACpC,yBAAyB,CAAiC;IAC1D,wBAAwB,CAA4B;IACpD,mBAAmB,CAA6C;IAChE,gCAAgC,CAA2B;IAC3D,2BAA2B,CAAiC;IAC5D,yBAAyB,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7D,KAAK,CAAqB;IAC1B,OAAO,CAAiC;IACxC,MAAM,GAAmB,SAAS,CAAC;IAEnC,YAAmB,UAA4B,EAAE;QAC/C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;QACpD,IAAI,CAAC,cAAc,GAAG;YACpB,OAAO,EAAkB,OAAO,CAAC,OAAO;YACxC,SAAS,EAAgB,OAAO,CAAC,SAAS;YAC1C,eAAe,EAAU,OAAO,CAAC,eAAe;YAChD,kBAAkB,EAAO,OAAO,CAAC,kBAAkB;YACnD,iBAAiB,EAAQ,OAAO,CAAC,iBAAiB;YAClD,QAAQ,EAAiB,OAAO,CAAC,QAAQ;YACzC,QAAQ,EAAiB,OAAO,CAAC,QAAQ;YACzC,iBAAiB,EAAQ,OAAO,CAAC,iBAAiB;YAClD,YAAY,EAAa,OAAO,CAAC,YAAY;YAC7C,eAAe,EAAU,OAAO,CAAC,eAAe;YAChD,oBAAoB,EAAK,OAAO,CAAC,oBAAoB;YACrD,kBAAkB,EAAO,OAAO,CAAC,kBAAkB;YACnD,UAAU,EAAe,OAAO,CAAC,UAAU;YAC3C,UAAU,EAAe,OAAO,CAAC,UAAU;YAC3C,sBAAsB,EAAG,OAAO,CAAC,sBAAsB;YACvD,WAAW,EAAc,OAAO,CAAC,WAAW;YAC5C,gBAAgB,EAAS,OAAO,CAAC,gBAAgB;SAClD,CAAC;QACF,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,IAAI,EAAS,CAAC,gBAAgB,CAAC;QACxE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,uBAAuB,EAAE,CAAC;QAC7E,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,8BAA8B,EAAE,CAAC;QACtF,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,IAAI,GAAG,CAAC;QACnE,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI,2BAA2B,EAAE,CAAC;QAC7F,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,cAAc,IAAI,sBAAsB,CAAC;IAC1E,CAAC;IAED,IAAW,iBAAiB;QAC1B,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;IAClC,CAAC;IAED,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,IAAW,cAAc;QACvB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC;QAChC,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACnD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,4BAA4B,CAAC,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClC,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,CAAC,iCAAiC,EAAE,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAC5D,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC;YAClC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;YAC9B,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC;YACtC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;YACtC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YAExB,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACjC,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACnC,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC;IAChC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9B,IAAI,WAA2C,CAAC;QAEhD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,GAAG,EAAE,KAAK,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,KAAK,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,qCAAqC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,KAAK,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,WAAW,KAAK,IAAI,CAAC,yBAAyB,CAAC;QAC/C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,yBAAyB,GAAG,SAAS,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QAExB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,WAAW,CAAC,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,gBAAgB;QAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO;YACL,QAAQ,EAAG,MAAM,CAAC,QAAQ;YAC1B,GAAG,EAAQ,MAAM,CAAC,GAAG;SACtB,CAAC;IACJ,CAAC;IAEM,SAAS;QACd,OAAO;YACL,iBAAiB,EAAQ,IAAI,CAAC,cAAc,CAAC,IAAI;YACjD,QAAQ,EAAiB,IAAI,CAAC,SAAS;YACvC,cAAc,EAAW,IAAI,CAAC,eAAe;YAC7C,sBAAsB,EAAG,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE;YACnE,GAAG,EAAsB,IAAI,CAAC,IAAI;YAClC,IAAI,EAAqB,IAAI,CAAC,KAAK;YACnC,KAAK,EAAoB,IAAI,CAAC,MAAM;YACpC,gBAAgB,EAAS,IAAI,CAAC,cAAc,CAAC,gBAAgB,IAAI,IAAI;SACtE,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,KAAa;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,2BAA2B,KAAK,SAAS;YACrE,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,KAAK,CAAC;YACvD,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,IAAI,CAAC,0BAA0B,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,6BAA6B;QACxC,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAChD,MAAM,IAAI,CAAC,wBAAwB,CAAC;YACpC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,8BAA8B,EAAE,CAAC;QACzD,IAAI,CAAC,wBAAwB,GAAG,UAAU,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,UAAU,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,8BAA8B;QAClC,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE,CAAC;QACnE,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACtC,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,MAAuB,EAAE,cAAuC;QACtF,OAAO,IAAI,SAAS,CAAC;YACnB,MAAM;YACN,uBAAuB,EAAE,cAAc;SACxC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,0BAA0B;QAC9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,8BAA8B,CAAC;gBAC5C,GAAG,IAAI,CAAC,cAAc;gBACtB,cAAc,EAAE,IAAI,CAAC,eAAe;gBACpC,IAAI;aACL,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YAEhE,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;gBACrB,OAAO;oBACL,QAAQ,EAAE,MAAM,CAAC,OAAO;oBACxB,IAAI;oBACJ,MAAM;iBACP,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,EAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;gBAC3C,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrE,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3G,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChG,MAAM,MAAM,GAAuB;YACjC,YAAY;YACZ,QAAQ,EAAS,IAAI,CAAC,SAAS;YAC/B,cAAc,EAAG,IAAI,CAAC,eAAe;YACrC,GAAG,EAAc,IAAI,CAAC,IAAI;SAC3B,CAAC;QAEF,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,uBAAuB;QACrB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAChF,OAAO;QACT,CAAC;QAED,KAAK,IAAI,CAAC,6BAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAQ,EAAE;YACvE,IAAI,CAAC,yBAAyB,KAAK,EAAE,KAAK,EAAE,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,GAAS,EAAE;YAChD,KAAK,IAAI,CAAC,6BAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAQ,EAAE;gBACvE,IAAI,CAAC,yBAAyB,KAAK,EAAE,KAAK,EAAE,CAAC;YAC/C,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAClC,CAAC;IAED,sBAAsB;QACpB,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,aAAa,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACxC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,OAAoC;QAC/D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAe,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACjE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QACrC,IAAI,CAAC;YACH,MAAM,yBAAyB,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;YACrF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA2B,CAAC;YAClE,OAAO,UAAU,CAAC,MAAM,KAAK,kBAAkB,IAAI,UAAU,CAAC,SAAS,KAAK,IAAI,CAAC;QACnF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC;QACxD,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,iCAAiC;QAC/B,IAAI,CAAC,gCAAgC,GAAG,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAC5E,CAAC,QAAyC,EAAQ,EAAE;YAClD,MAAM,eAAe,GAAG,QAAQ;iBAC7B,MAAM,CAAC,CAAC,OAAsC,EAAW,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YAE7F,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,KAAK,IAAmB,EAAE;gBAC7F,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBACzD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,2BAA2B,KAAK,EAAE,KAAK,EAAE,CAAC;gBACjD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC;IAED,qCAAqC;QACnC,IAAI,CAAC,gCAAgC,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,gCAAgC,GAAG,SAAS,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,0BAA0B;QAC9B,IAAI,aAA4B,CAAC;QACjC,GAAG,CAAC;YACF,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC;YAC/C,MAAM,aAAa,CAAC;QACtB,CAAC,QAAQ,aAAa,KAAK,IAAI,CAAC,yBAAyB,EAAE;QAE3D,MAAM,OAAO,GAAG,IAAI,CAAC,2BAA2B,CAAC;QACjD,IAAI,CAAC,2BAA2B,GAAG,SAAS,CAAC;QAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,OAAO,CAAC,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,4BAA4B;QAChC,IAAI,aAA4B,CAAC;QACjC,GAAG,CAAC;YACF,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC;YAC/C,MAAM,aAAa,CAAC;QACtB,CAAC,QAAQ,aAAa,KAAK,IAAI,CAAC,yBAAyB,EAAE;IAC7D,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACnG,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,OAAO;YACL,iBAAiB,EAAG,IAAI,CAAC,cAAc,CAAC,IAAI;YAC5C,QAAQ,EAAY,IAAI,CAAC,SAAS;YAClC,cAAc,EAAM,IAAI,CAAC,eAAe;YACxC,GAAG,EAAiB,IAAI,CAAC,IAAI;YAC7B,IAAI,EAAgB,IAAI,CAAC,KAAK;SAC/B,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAA0B;QACxD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;QAC7D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAE9B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,qCAAqC,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,4BAA4B,EAAE,CAAC;YAC1C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;YAC3B,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;YACjC,IAAI,CAAC,yBAAyB,GAAG,SAAS,CAAC;YAC3C,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QAC1B,CAAC;IACH,CAAC;CACF;;AAED,SAAS,mBAAmB,CAAC,KAAc;IACzC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAI,KAA4B,CAAC,IAAI,CAAC;IACrD,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAI,KAA+B,CAAC,OAAO,CAAC;IAC9D,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACtG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAI,KAA6B,CAAC,KAAK,CAAC;IACxD,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ import { stdin as defaultInput, stdout as defaultOutput } from 'node:process';
3
+ export class AllowOriginPairingBroker {
4
+ #allowedOrigins;
5
+ #fallback;
6
+ constructor(allowedOrigins = [], fallback) {
7
+ this.#allowedOrigins = new Set(allowedOrigins);
8
+ this.#fallback = fallback;
9
+ }
10
+ async decidePairingRequest(request) {
11
+ if (this.#allowedOrigins.has(request.origin)) {
12
+ return 'approve';
13
+ }
14
+ if (this.#fallback !== undefined) {
15
+ return this.#fallback.decidePairingRequest(request);
16
+ }
17
+ return 'deny';
18
+ }
19
+ }
20
+ export class TtyPairingBroker {
21
+ #input;
22
+ #output;
23
+ constructor(options = {}) {
24
+ this.#input = options.input ?? defaultInput;
25
+ this.#output = options.output ?? defaultOutput;
26
+ }
27
+ async decidePairingRequest(request) {
28
+ if (this.#input.isTTY !== true || this.#output.isTTY !== true) {
29
+ return 'deny';
30
+ }
31
+ const readline = createInterface({
32
+ input: this.#input,
33
+ output: this.#output,
34
+ });
35
+ try {
36
+ const answer = await readline.question(`Approve local DWN pairing for ${request.origin}? [y/N] `);
37
+ return /^(?:y|yes)$/i.test(answer.trim()) ? 'approve' : 'deny';
38
+ }
39
+ finally {
40
+ readline.close();
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=pairing-broker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing-broker.js","sourceRoot":"","sources":["../../src/pairing-broker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,cAAc,CAAC;AAW9E,MAAM,OAAO,wBAAwB;IAC1B,eAAe,CAAc;IAC7B,SAAS,CAA4B;IAE9C,YAAmB,iBAA2B,EAAE,EAAE,QAAwB;QACxE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAAC,OAAoC;QACpE,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,MAAM,OAAO,gBAAgB;IAClB,MAAM,CAAc;IACpB,OAAO,CAAc;IAE9B,YAAmB,UAAyD,EAAE;QAC5E,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;QAC5C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAAC,OAAoC;QACpE,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC9D,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,QAAQ,GAAG,eAAe,CAAC;YAC/B,KAAK,EAAI,IAAI,CAAC,MAAM;YACpB,MAAM,EAAG,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,iCAAiC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;YAClG,OAAO,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}