@dxos/signal 0.6.13 → 0.6.14-main.2b6a0f3

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.
@@ -33,6 +33,7 @@ __export(node_exports, {
33
33
  runTestSignalServer: () => runTestSignalServer
34
34
  });
35
35
  module.exports = __toCommonJS(node_exports);
36
+ var import_find_process = __toESM(require("find-process"));
36
37
  var import_node_fetch = __toESM(require("node-fetch"));
37
38
  var import_node_child_process = require("node:child_process");
38
39
  var import_node_fs = __toESM(require("node:fs"));
@@ -55,27 +56,26 @@ var SignalServerRunner = class {
55
56
  this._shell = shell;
56
57
  this._killExisting = killExisting;
57
58
  this.onError = onError;
58
- this._serverProcess = this.startProcess();
59
59
  }
60
- startProcess() {
60
+ async startProcess() {
61
61
  if (this._cwd && !import_node_fs.default.existsSync(this._cwd)) {
62
62
  throw new Error(`CWD not exists: ${this._cwd}`);
63
63
  }
64
64
  if (!this._port) {
65
65
  while (true) {
66
66
  this._port = (0, import_util.randomInt)(1e4, 5e4);
67
- const pid = checkPort(this._port);
67
+ const pid = await checkPort(this._port);
68
68
  if (pid.length === 0) {
69
69
  break;
70
70
  }
71
71
  }
72
72
  } else {
73
- const pid = checkPort(this._port);
73
+ const pid = await checkPort(this._port);
74
74
  if (pid.length > 0) {
75
75
  if (this._killExisting) {
76
76
  import_log.log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`, void 0, {
77
77
  F: __dxlog_file,
78
- L: 89,
78
+ L: 88,
79
79
  S: this,
80
80
  C: (f, a) => f(...a)
81
81
  });
@@ -92,7 +92,7 @@ var SignalServerRunner = class {
92
92
  port: this._port
93
93
  }, {
94
94
  F: __dxlog_file,
95
- L: 98,
95
+ L: 97,
96
96
  S: this,
97
97
  C: (f, a) => f(...a)
98
98
  });
@@ -114,7 +114,7 @@ var SignalServerRunner = class {
114
114
  server.stdout.on("data", (data) => {
115
115
  (0, import_log.log)(`TestServer stdout: ${data}`, void 0, {
116
116
  F: __dxlog_file,
117
- L: 118,
117
+ L: 117,
118
118
  S: this,
119
119
  C: (f, a) => f(...a)
120
120
  });
@@ -122,7 +122,7 @@ var SignalServerRunner = class {
122
122
  server.stderr.on("data", (data) => {
123
123
  import_log.log.info(`TestServer stderr: ${data}`, void 0, {
124
124
  F: __dxlog_file,
125
- L: 122,
125
+ L: 121,
126
126
  S: this,
127
127
  C: (f, a) => f(...a)
128
128
  });
@@ -130,7 +130,7 @@ var SignalServerRunner = class {
130
130
  server.on("error", (err) => {
131
131
  import_log.log.error(`TestServer ERROR: ${err}`, void 0, {
132
132
  F: __dxlog_file,
133
- L: 126,
133
+ L: 125,
134
134
  S: this,
135
135
  C: (f, a) => f(...a)
136
136
  });
@@ -146,7 +146,7 @@ var SignalServerRunner = class {
146
146
  } else {
147
147
  import_log.log.info(`TestServer exited with code ${code}`, void 0, {
148
148
  F: __dxlog_file,
149
- L: 138,
149
+ L: 137,
150
150
  S: this,
151
151
  C: (f, a) => f(...a)
152
152
  });
@@ -163,7 +163,7 @@ var SignalServerRunner = class {
163
163
  const response = await (0, import_node_fetch.default)(`http://localhost:${this._port}/.well-known/dx/signal`);
164
164
  (0, import_log.log)(`Fetching broker. Response=${JSON.stringify(response)}`, void 0, {
165
165
  F: __dxlog_file,
166
- L: 152,
166
+ L: 151,
167
167
  S: this,
168
168
  C: (f, a) => f(...a)
169
169
  });
@@ -175,7 +175,7 @@ var SignalServerRunner = class {
175
175
  }
176
176
  if (waited >= this._timeout) {
177
177
  await this.stop();
178
- this._serverProcess = this.startProcess();
178
+ await this.startProcess();
179
179
  this._startRetries++;
180
180
  if (this._startRetries > this._retriesLimit) {
181
181
  throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);
@@ -184,11 +184,11 @@ var SignalServerRunner = class {
184
184
  }
185
185
  }
186
186
  async stop() {
187
- const pid = this._serverProcess.pid;
187
+ const pid = this._serverProcess?.pid;
188
188
  if (!pid) {
189
189
  import_log.log.warn("pid not found", void 0, {
190
190
  F: __dxlog_file,
191
- L: 175,
191
+ L: 174,
192
192
  S: this,
193
193
  C: (f, a) => f(...a)
194
194
  });
@@ -196,7 +196,7 @@ var SignalServerRunner = class {
196
196
  }
197
197
  import_log.log.info(`sending SIGINT to process group ${pid}`, void 0, {
198
198
  F: __dxlog_file,
199
- L: 178,
199
+ L: 177,
200
200
  S: this,
201
201
  C: (f, a) => f(...a)
202
202
  });
@@ -205,7 +205,7 @@ var SignalServerRunner = class {
205
205
  if (!delivered) {
206
206
  import_log.log.warn("kill signal was not delivered to child process", void 0, {
207
207
  F: __dxlog_file,
208
- L: 183,
208
+ L: 182,
209
209
  S: this,
210
210
  C: (f, a) => f(...a)
211
211
  });
@@ -215,7 +215,7 @@ var SignalServerRunner = class {
215
215
  err
216
216
  }, {
217
217
  F: __dxlog_file,
218
- L: 186,
218
+ L: 185,
219
219
  S: this,
220
220
  C: (f, a) => f(...a)
221
221
  });
@@ -255,13 +255,17 @@ var runTestSignalServer = async ({ port, mode = "server", killExisting = false }
255
255
  port,
256
256
  killExisting
257
257
  });
258
+ await server.startProcess();
258
259
  await server.waitUntilStarted();
259
260
  return server;
260
261
  };
261
- var checkPort = (port) => {
262
+ var checkPort = async (port) => {
262
263
  let pid = "";
263
264
  try {
264
- pid = (0, import_node_child_process.execSync)(`lsof -t -i:${port}`).toString().trim();
265
+ const list = await (0, import_find_process.default)("port", port);
266
+ if (list.length > 0) {
267
+ pid = list[0].pid.toString();
268
+ }
265
269
  } catch (err) {
266
270
  if (typeof err === "object" && err !== null) {
267
271
  if (err.status !== 1) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/signal-server-runner.ts"],
4
- "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport fetch from 'node-fetch';\nimport { type ChildProcessWithoutNullStreams, execSync, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path, { dirname } from 'node:path';\nimport pkgUp from 'pkg-up';\n\nimport { sleep } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { randomInt } from '@dxos/util';\n\ninterface TestBrokerOptions {\n binCommand: string;\n signalArguments: string[];\n cwd?: string;\n port?: number;\n timeout?: number;\n env?: Record<string, string>;\n killExisting?: boolean;\n onError?: (err: any) => void;\n\n /**\n * Allows arbitrary commands. WARNING: It stalls on Linux machine if `true`.\n */\n shell?: boolean;\n}\n\n// TODO(burdon): Convert to TestBuilder pattern.\nexport class SignalServerRunner {\n private readonly _binCommand: string;\n private readonly _signalArguments: string[];\n private readonly _cwd?: string;\n private readonly _env: Record<string, string>;\n private readonly _shell: boolean;\n private readonly _killExisting: boolean;\n private readonly onError?: (err: any) => void;\n\n private _startRetries = 0;\n private readonly _retriesLimit = 3;\n private _port: number | undefined;\n private readonly _timeout: number;\n private _serverProcess: ChildProcessWithoutNullStreams;\n\n constructor({\n binCommand,\n signalArguments,\n cwd,\n port,\n timeout = 60_000,\n env = {},\n shell = false,\n killExisting = false,\n onError,\n }: TestBrokerOptions) {\n this._binCommand = binCommand;\n this._signalArguments = signalArguments;\n this._cwd = cwd;\n this._port = port;\n this._timeout = timeout;\n this._env = env;\n this._shell = shell;\n this._killExisting = killExisting;\n this.onError = onError;\n\n this._serverProcess = this.startProcess();\n }\n\n public startProcess(): ChildProcessWithoutNullStreams {\n if (this._cwd && !fs.existsSync(this._cwd)) {\n throw new Error(`CWD not exists: ${this._cwd}`);\n }\n if (!this._port) {\n // find a port that does not have another process listening on it.\n while (true) {\n this._port = randomInt(10000, 50000);\n const pid = checkPort(this._port);\n\n if (pid.length === 0) {\n break;\n }\n }\n } else {\n const pid = checkPort(this._port);\n if (pid.length > 0) {\n if (this._killExisting) {\n log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`);\n // TODO(nf): verify the process is actually a signal server\n process.kill(-Number(pid), 'SIGINT');\n } else {\n throw new Error(`Port ${this._port} is already in use by process ${pid}`);\n }\n }\n }\n\n log('starting', {\n binCommand: this._binCommand,\n signalArguments: this._signalArguments,\n cwd: this._cwd,\n port: this._port,\n });\n\n const server = spawn(this._binCommand, [...this._signalArguments, '--port', this._port.toString()], {\n cwd: this._cwd,\n shell: this._shell,\n env: {\n ...process.env,\n ...this._env,\n },\n // Force creation of process group to ensure all child processes are killed.\n // https://nodejs.org/api/child_process.html#optionsdetached\n detached: true,\n });\n\n server.stdout.on('data', (data) => {\n log(`TestServer stdout: ${data}`);\n });\n\n server.stderr.on('data', (data) => {\n log.info(`TestServer stderr: ${data}`);\n });\n\n server.on('error', (err) => {\n log.error(`TestServer ERROR: ${err}`);\n this.onError?.(err);\n });\n\n server.on('close', (code) => {\n if ((code! -= 0)) {\n if (this.onError) {\n this.onError?.(new Error(`TestServer exited with code ${code}`));\n } else {\n throw new Error(`TestServer exited with code ${code}`);\n }\n } else {\n log.info(`TestServer exited with code ${code}`);\n }\n });\n\n this._serverProcess = server;\n return server;\n }\n\n public async waitUntilStarted(): Promise<void> {\n let waited = 0;\n const waitInc = 20;\n while (waited < this._timeout) {\n try {\n const response = await fetch(`http://localhost:${this._port}/.well-known/dx/signal`);\n log(`Fetching broker. Response=${JSON.stringify(response)}`);\n return;\n } catch (err) {\n await sleep(waitInc);\n waited = waited + waitInc;\n }\n }\n\n if (waited >= this._timeout) {\n await this.stop();\n this._serverProcess = this.startProcess();\n this._startRetries++;\n if (this._startRetries > this._retriesLimit) {\n throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);\n }\n\n return await this.waitUntilStarted();\n }\n }\n\n public async stop(): Promise<void> {\n const pid = this._serverProcess.pid;\n if (!pid) {\n log.warn('pid not found');\n return;\n }\n log.info(`sending SIGINT to process group ${pid}`);\n // kill process group so that all child processes can be killed, e.g. https://github.com/golang/go/issues/40467\n try {\n const delivered = process.kill(-pid, 'SIGINT');\n if (!delivered) {\n log.warn('kill signal was not delivered to child process');\n }\n } catch (err: any) {\n log.warn('kill error', { err });\n }\n }\n\n public url(): string {\n return `ws://localhost:${this._port}/.well-known/dx/signal`;\n }\n}\nconst ARCH = ['x64', 'amd64', 'ppc64'].includes(process.arch)\n ? 'amd64'\n : ['arm64'].includes(process.arch)\n ? 'arm64'\n : '32';\n\nconst OS = process.platform;\n\n/**\n * Creates a test instance of the signal server with swarming disabled and starts it.\n *\n * @param port Port to start the signal server on, random by default.\n */\n// TODO(burdon): Convert to TestBuilder pattern.\nexport const runTestSignalServer = async ({\n port,\n mode = 'server',\n killExisting = false,\n}: {\n port?: number;\n\n /**\n * Signal binary mode, `server` is in memory implementation.\n * @see https://github.com/dxos/kube\n */\n mode?: 'client' | 'server' | 'p2pserver' | 'keypair' | 'pubsubserver';\n killExisting?: boolean;\n} = {}): Promise<SignalServerRunner> => {\n if (ARCH === '32') {\n throw new Error('32 bit architecture not supported');\n }\n\n if (!['darwin', 'linux'].includes(OS)) {\n throw new Error(`Unsupported platform: ${OS}`);\n }\n\n const binPath = `./signal-test-${OS}-${ARCH}`;\n const server = new SignalServerRunner({\n binCommand: binPath,\n signalArguments: [mode],\n cwd: path.join(dirname(pkgUp.sync({ cwd: __dirname })!), 'bin'),\n port,\n killExisting,\n });\n await server.waitUntilStarted();\n return server;\n};\n\nexport const checkPort = (port: number) => {\n let pid = '';\n try {\n pid = execSync(`lsof -t -i:${port}`).toString().trim();\n } catch (err) {\n if (typeof err === 'object' && err !== null) {\n // lsof responds with status 1 if pattern does match, along with other errors :(, so this is the best we can do\n if ((err as Record<string, unknown>).status !== 1) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n return pid;\n};\n"],
5
- "mappings": "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",
6
- "names": ["SignalServerRunner", "constructor", "binCommand", "signalArguments", "cwd", "port", "timeout", "env", "shell", "killExisting", "onError", "_startRetries", "_retriesLimit", "_binCommand", "_signalArguments", "_cwd", "_port", "_timeout", "_env", "_shell", "_killExisting", "_serverProcess", "startProcess", "fs", "existsSync", "Error", "randomInt", "pid", "checkPort", "length", "log", "warn", "process", "kill", "Number", "server", "spawn", "toString", "detached", "stdout", "on", "data", "stderr", "info", "err", "error", "code", "waitUntilStarted", "waited", "waitInc", "response", "fetch", "JSON", "stringify", "sleep", "stop", "delivered", "url", "ARCH", "includes", "arch", "OS", "platform", "runTestSignalServer", "mode", "binPath", "path", "join", "dirname", "pkgUp", "sync", "__dirname", "execSync", "trim", "status"]
4
+ "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport find from 'find-process';\nimport fetch from 'node-fetch';\nimport { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path, { dirname } from 'node:path';\nimport pkgUp from 'pkg-up';\n\nimport { sleep } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { randomInt } from '@dxos/util';\n\ninterface TestBrokerOptions {\n binCommand: string;\n signalArguments: string[];\n cwd?: string;\n port?: number;\n timeout?: number;\n env?: Record<string, string>;\n killExisting?: boolean;\n onError?: (err: any) => void;\n\n /**\n * Allows arbitrary commands. WARNING: It stalls on Linux machine if `true`.\n */\n shell?: boolean;\n}\n\n// TODO(burdon): Convert to TestBuilder pattern.\nexport class SignalServerRunner {\n private readonly _binCommand: string;\n private readonly _signalArguments: string[];\n private readonly _cwd?: string;\n private readonly _env: Record<string, string>;\n private readonly _shell: boolean;\n private readonly _killExisting: boolean;\n private readonly onError?: (err: any) => void;\n\n private _startRetries = 0;\n private readonly _retriesLimit = 3;\n private _port: number | undefined;\n private readonly _timeout: number;\n private _serverProcess: ChildProcessWithoutNullStreams | undefined;\n\n constructor({\n binCommand,\n signalArguments,\n cwd,\n port,\n timeout = 60_000,\n env = {},\n shell = false,\n killExisting = false,\n onError,\n }: TestBrokerOptions) {\n this._binCommand = binCommand;\n this._signalArguments = signalArguments;\n this._cwd = cwd;\n this._port = port;\n this._timeout = timeout;\n this._env = env;\n this._shell = shell;\n this._killExisting = killExisting;\n this.onError = onError;\n }\n\n public async startProcess(): Promise<ChildProcessWithoutNullStreams> {\n if (this._cwd && !fs.existsSync(this._cwd)) {\n throw new Error(`CWD not exists: ${this._cwd}`);\n }\n if (!this._port) {\n // find a port that does not have another process listening on it.\n while (true) {\n this._port = randomInt(10000, 50000);\n const pid = await checkPort(this._port);\n\n if (pid.length === 0) {\n break;\n }\n }\n } else {\n const pid = await checkPort(this._port);\n if (pid.length > 0) {\n if (this._killExisting) {\n log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`);\n // TODO(nf): verify the process is actually a signal server\n process.kill(-Number(pid), 'SIGINT');\n } else {\n throw new Error(`Port ${this._port} is already in use by process ${pid}`);\n }\n }\n }\n\n log('starting', {\n binCommand: this._binCommand,\n signalArguments: this._signalArguments,\n cwd: this._cwd,\n port: this._port,\n });\n\n const server = spawn(this._binCommand, [...this._signalArguments, '--port', this._port.toString()], {\n cwd: this._cwd,\n shell: this._shell,\n env: {\n ...process.env,\n ...this._env,\n },\n // Force creation of process group to ensure all child processes are killed.\n // https://nodejs.org/api/child_process.html#optionsdetached\n detached: true,\n });\n\n server.stdout.on('data', (data) => {\n log(`TestServer stdout: ${data}`);\n });\n\n server.stderr.on('data', (data) => {\n log.info(`TestServer stderr: ${data}`);\n });\n\n server.on('error', (err) => {\n log.error(`TestServer ERROR: ${err}`);\n this.onError?.(err);\n });\n\n server.on('close', (code) => {\n if ((code! -= 0)) {\n if (this.onError) {\n this.onError?.(new Error(`TestServer exited with code ${code}`));\n } else {\n throw new Error(`TestServer exited with code ${code}`);\n }\n } else {\n log.info(`TestServer exited with code ${code}`);\n }\n });\n\n this._serverProcess = server;\n return server;\n }\n\n public async waitUntilStarted(): Promise<void> {\n let waited = 0;\n const waitInc = 20;\n while (waited < this._timeout) {\n try {\n const response = await fetch(`http://localhost:${this._port}/.well-known/dx/signal`);\n log(`Fetching broker. Response=${JSON.stringify(response)}`);\n return;\n } catch (err) {\n await sleep(waitInc);\n waited = waited + waitInc;\n }\n }\n\n if (waited >= this._timeout) {\n await this.stop();\n await this.startProcess();\n this._startRetries++;\n if (this._startRetries > this._retriesLimit) {\n throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);\n }\n\n return await this.waitUntilStarted();\n }\n }\n\n public async stop(): Promise<void> {\n const pid = this._serverProcess?.pid;\n if (!pid) {\n log.warn('pid not found');\n return;\n }\n log.info(`sending SIGINT to process group ${pid}`);\n // kill process group so that all child processes can be killed, e.g. https://github.com/golang/go/issues/40467\n try {\n const delivered = process.kill(-pid, 'SIGINT');\n if (!delivered) {\n log.warn('kill signal was not delivered to child process');\n }\n } catch (err: any) {\n log.warn('kill error', { err });\n }\n }\n\n public url(): string {\n return `ws://localhost:${this._port}/.well-known/dx/signal`;\n }\n}\nconst ARCH = ['x64', 'amd64', 'ppc64'].includes(process.arch)\n ? 'amd64'\n : ['arm64'].includes(process.arch)\n ? 'arm64'\n : '32';\n\nconst OS = process.platform;\n\n/**\n * Creates a test instance of the signal server with swarming disabled and starts it.\n *\n * @param port Port to start the signal server on, random by default.\n */\n// TODO(burdon): Convert to TestBuilder pattern.\nexport const runTestSignalServer = async ({\n port,\n mode = 'server',\n killExisting = false,\n}: {\n port?: number;\n\n /**\n * Signal binary mode, `server` is in memory implementation.\n * @see https://github.com/dxos/kube\n */\n mode?: 'client' | 'server' | 'p2pserver' | 'keypair' | 'pubsubserver';\n killExisting?: boolean;\n} = {}): Promise<SignalServerRunner> => {\n if (ARCH === '32') {\n throw new Error('32 bit architecture not supported');\n }\n\n if (!['darwin', 'linux'].includes(OS)) {\n throw new Error(`Unsupported platform: ${OS}`);\n }\n\n const binPath = `./signal-test-${OS}-${ARCH}`;\n const server = new SignalServerRunner({\n binCommand: binPath,\n signalArguments: [mode],\n cwd: path.join(dirname(pkgUp.sync({ cwd: __dirname })!), 'bin'),\n port,\n killExisting,\n });\n await server.startProcess();\n await server.waitUntilStarted();\n return server;\n};\n\nexport const checkPort = async (port: number) => {\n let pid = '';\n try {\n const list = await find('port', port);\n if (list.length > 0) {\n pid = list[0].pid.toString();\n }\n } catch (err) {\n if (typeof err === 'object' && err !== null) {\n // lsof responds with status 1 if pattern does match, along with other errors :(, so this is the best we can do\n if ((err as Record<string, unknown>).status !== 1) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n return pid;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["SignalServerRunner", "constructor", "binCommand", "signalArguments", "cwd", "port", "timeout", "env", "shell", "killExisting", "onError", "_startRetries", "_retriesLimit", "_binCommand", "_signalArguments", "_cwd", "_port", "_timeout", "_env", "_shell", "_killExisting", "startProcess", "fs", "existsSync", "Error", "randomInt", "pid", "checkPort", "length", "log", "warn", "process", "kill", "Number", "server", "spawn", "toString", "detached", "stdout", "on", "data", "stderr", "info", "err", "error", "code", "_serverProcess", "waitUntilStarted", "waited", "waitInc", "response", "fetch", "JSON", "stringify", "sleep", "stop", "delivered", "url", "ARCH", "includes", "arch", "OS", "platform", "runTestSignalServer", "mode", "binPath", "path", "join", "dirname", "pkgUp", "sync", "__dirname", "list", "find", "status"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytes":26379,"imports":[{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/signal/src/index.ts":{"bytes":529,"imports":[{"path":"packages/core/mesh/signal/src/signal-server-runner.ts","kind":"import-statement","original":"./signal-server-runner"}],"format":"esm"}},"outputs":{"packages/core/mesh/signal/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":12092},"packages/core/mesh/signal/dist/lib/node/index.cjs":{"imports":[{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["SignalServerRunner","checkPort","runTestSignalServer"],"entryPoint":"packages/core/mesh/signal/src/index.ts","inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytesInOutput":6429},"packages/core/mesh/signal/src/index.ts":{"bytesInOutput":0}},"bytes":6590}}}
1
+ {"inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytes":26639,"imports":[{"path":"find-process","kind":"import-statement","external":true},{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/signal/src/index.ts":{"bytes":529,"imports":[{"path":"packages/core/mesh/signal/src/signal-server-runner.ts","kind":"import-statement","original":"./signal-server-runner"}],"format":"esm"}},"outputs":{"packages/core/mesh/signal/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":12250},"packages/core/mesh/signal/dist/lib/node/index.cjs":{"imports":[{"path":"find-process","kind":"import-statement","external":true},{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["SignalServerRunner","checkPort","runTestSignalServer"],"entryPoint":"packages/core/mesh/signal/src/index.ts","inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytesInOutput":6497},"packages/core/mesh/signal/src/index.ts":{"bytesInOutput":0}},"bytes":6658}}}
@@ -0,0 +1,253 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+
3
+ // packages/core/mesh/signal/src/signal-server-runner.ts
4
+ import find from "find-process";
5
+ import fetch from "node-fetch";
6
+ import { spawn } from "node:child_process";
7
+ import fs from "node:fs";
8
+ import path, { dirname } from "node:path";
9
+ import pkgUp from "pkg-up";
10
+ import { sleep } from "@dxos/async";
11
+ import { log } from "@dxos/log";
12
+ import { randomInt } from "@dxos/util";
13
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/signal/src/signal-server-runner.ts";
14
+ var SignalServerRunner = class {
15
+ constructor({ binCommand, signalArguments, cwd, port, timeout = 6e4, env = {}, shell = false, killExisting = false, onError }) {
16
+ this._startRetries = 0;
17
+ this._retriesLimit = 3;
18
+ this._binCommand = binCommand;
19
+ this._signalArguments = signalArguments;
20
+ this._cwd = cwd;
21
+ this._port = port;
22
+ this._timeout = timeout;
23
+ this._env = env;
24
+ this._shell = shell;
25
+ this._killExisting = killExisting;
26
+ this.onError = onError;
27
+ }
28
+ async startProcess() {
29
+ if (this._cwd && !fs.existsSync(this._cwd)) {
30
+ throw new Error(`CWD not exists: ${this._cwd}`);
31
+ }
32
+ if (!this._port) {
33
+ while (true) {
34
+ this._port = randomInt(1e4, 5e4);
35
+ const pid = await checkPort(this._port);
36
+ if (pid.length === 0) {
37
+ break;
38
+ }
39
+ }
40
+ } else {
41
+ const pid = await checkPort(this._port);
42
+ if (pid.length > 0) {
43
+ if (this._killExisting) {
44
+ log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`, void 0, {
45
+ F: __dxlog_file,
46
+ L: 88,
47
+ S: this,
48
+ C: (f, a) => f(...a)
49
+ });
50
+ process.kill(-Number(pid), "SIGINT");
51
+ } else {
52
+ throw new Error(`Port ${this._port} is already in use by process ${pid}`);
53
+ }
54
+ }
55
+ }
56
+ log("starting", {
57
+ binCommand: this._binCommand,
58
+ signalArguments: this._signalArguments,
59
+ cwd: this._cwd,
60
+ port: this._port
61
+ }, {
62
+ F: __dxlog_file,
63
+ L: 97,
64
+ S: this,
65
+ C: (f, a) => f(...a)
66
+ });
67
+ const server = spawn(this._binCommand, [
68
+ ...this._signalArguments,
69
+ "--port",
70
+ this._port.toString()
71
+ ], {
72
+ cwd: this._cwd,
73
+ shell: this._shell,
74
+ env: {
75
+ ...process.env,
76
+ ...this._env
77
+ },
78
+ // Force creation of process group to ensure all child processes are killed.
79
+ // https://nodejs.org/api/child_process.html#optionsdetached
80
+ detached: true
81
+ });
82
+ server.stdout.on("data", (data) => {
83
+ log(`TestServer stdout: ${data}`, void 0, {
84
+ F: __dxlog_file,
85
+ L: 117,
86
+ S: this,
87
+ C: (f, a) => f(...a)
88
+ });
89
+ });
90
+ server.stderr.on("data", (data) => {
91
+ log.info(`TestServer stderr: ${data}`, void 0, {
92
+ F: __dxlog_file,
93
+ L: 121,
94
+ S: this,
95
+ C: (f, a) => f(...a)
96
+ });
97
+ });
98
+ server.on("error", (err) => {
99
+ log.error(`TestServer ERROR: ${err}`, void 0, {
100
+ F: __dxlog_file,
101
+ L: 125,
102
+ S: this,
103
+ C: (f, a) => f(...a)
104
+ });
105
+ this.onError?.(err);
106
+ });
107
+ server.on("close", (code) => {
108
+ if (code -= 0) {
109
+ if (this.onError) {
110
+ this.onError?.(new Error(`TestServer exited with code ${code}`));
111
+ } else {
112
+ throw new Error(`TestServer exited with code ${code}`);
113
+ }
114
+ } else {
115
+ log.info(`TestServer exited with code ${code}`, void 0, {
116
+ F: __dxlog_file,
117
+ L: 137,
118
+ S: this,
119
+ C: (f, a) => f(...a)
120
+ });
121
+ }
122
+ });
123
+ this._serverProcess = server;
124
+ return server;
125
+ }
126
+ async waitUntilStarted() {
127
+ let waited = 0;
128
+ const waitInc = 20;
129
+ while (waited < this._timeout) {
130
+ try {
131
+ const response = await fetch(`http://localhost:${this._port}/.well-known/dx/signal`);
132
+ log(`Fetching broker. Response=${JSON.stringify(response)}`, void 0, {
133
+ F: __dxlog_file,
134
+ L: 151,
135
+ S: this,
136
+ C: (f, a) => f(...a)
137
+ });
138
+ return;
139
+ } catch (err) {
140
+ await sleep(waitInc);
141
+ waited = waited + waitInc;
142
+ }
143
+ }
144
+ if (waited >= this._timeout) {
145
+ await this.stop();
146
+ await this.startProcess();
147
+ this._startRetries++;
148
+ if (this._startRetries > this._retriesLimit) {
149
+ throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);
150
+ }
151
+ return await this.waitUntilStarted();
152
+ }
153
+ }
154
+ async stop() {
155
+ const pid = this._serverProcess?.pid;
156
+ if (!pid) {
157
+ log.warn("pid not found", void 0, {
158
+ F: __dxlog_file,
159
+ L: 174,
160
+ S: this,
161
+ C: (f, a) => f(...a)
162
+ });
163
+ return;
164
+ }
165
+ log.info(`sending SIGINT to process group ${pid}`, void 0, {
166
+ F: __dxlog_file,
167
+ L: 177,
168
+ S: this,
169
+ C: (f, a) => f(...a)
170
+ });
171
+ try {
172
+ const delivered = process.kill(-pid, "SIGINT");
173
+ if (!delivered) {
174
+ log.warn("kill signal was not delivered to child process", void 0, {
175
+ F: __dxlog_file,
176
+ L: 182,
177
+ S: this,
178
+ C: (f, a) => f(...a)
179
+ });
180
+ }
181
+ } catch (err) {
182
+ log.warn("kill error", {
183
+ err
184
+ }, {
185
+ F: __dxlog_file,
186
+ L: 185,
187
+ S: this,
188
+ C: (f, a) => f(...a)
189
+ });
190
+ }
191
+ }
192
+ url() {
193
+ return `ws://localhost:${this._port}/.well-known/dx/signal`;
194
+ }
195
+ };
196
+ var ARCH = [
197
+ "x64",
198
+ "amd64",
199
+ "ppc64"
200
+ ].includes(process.arch) ? "amd64" : [
201
+ "arm64"
202
+ ].includes(process.arch) ? "arm64" : "32";
203
+ var OS = process.platform;
204
+ var runTestSignalServer = async ({ port, mode = "server", killExisting = false } = {}) => {
205
+ if (ARCH === "32") {
206
+ throw new Error("32 bit architecture not supported");
207
+ }
208
+ if (![
209
+ "darwin",
210
+ "linux"
211
+ ].includes(OS)) {
212
+ throw new Error(`Unsupported platform: ${OS}`);
213
+ }
214
+ const binPath = `./signal-test-${OS}-${ARCH}`;
215
+ const server = new SignalServerRunner({
216
+ binCommand: binPath,
217
+ signalArguments: [
218
+ mode
219
+ ],
220
+ cwd: path.join(dirname(pkgUp.sync({
221
+ cwd: __dirname
222
+ })), "bin"),
223
+ port,
224
+ killExisting
225
+ });
226
+ await server.startProcess();
227
+ await server.waitUntilStarted();
228
+ return server;
229
+ };
230
+ var checkPort = async (port) => {
231
+ let pid = "";
232
+ try {
233
+ const list = await find("port", port);
234
+ if (list.length > 0) {
235
+ pid = list[0].pid.toString();
236
+ }
237
+ } catch (err) {
238
+ if (typeof err === "object" && err !== null) {
239
+ if (err.status !== 1) {
240
+ throw err;
241
+ }
242
+ } else {
243
+ throw err;
244
+ }
245
+ }
246
+ return pid;
247
+ };
248
+ export {
249
+ SignalServerRunner,
250
+ checkPort,
251
+ runTestSignalServer
252
+ };
253
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/signal-server-runner.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport find from 'find-process';\nimport fetch from 'node-fetch';\nimport { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path, { dirname } from 'node:path';\nimport pkgUp from 'pkg-up';\n\nimport { sleep } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { randomInt } from '@dxos/util';\n\ninterface TestBrokerOptions {\n binCommand: string;\n signalArguments: string[];\n cwd?: string;\n port?: number;\n timeout?: number;\n env?: Record<string, string>;\n killExisting?: boolean;\n onError?: (err: any) => void;\n\n /**\n * Allows arbitrary commands. WARNING: It stalls on Linux machine if `true`.\n */\n shell?: boolean;\n}\n\n// TODO(burdon): Convert to TestBuilder pattern.\nexport class SignalServerRunner {\n private readonly _binCommand: string;\n private readonly _signalArguments: string[];\n private readonly _cwd?: string;\n private readonly _env: Record<string, string>;\n private readonly _shell: boolean;\n private readonly _killExisting: boolean;\n private readonly onError?: (err: any) => void;\n\n private _startRetries = 0;\n private readonly _retriesLimit = 3;\n private _port: number | undefined;\n private readonly _timeout: number;\n private _serverProcess: ChildProcessWithoutNullStreams | undefined;\n\n constructor({\n binCommand,\n signalArguments,\n cwd,\n port,\n timeout = 60_000,\n env = {},\n shell = false,\n killExisting = false,\n onError,\n }: TestBrokerOptions) {\n this._binCommand = binCommand;\n this._signalArguments = signalArguments;\n this._cwd = cwd;\n this._port = port;\n this._timeout = timeout;\n this._env = env;\n this._shell = shell;\n this._killExisting = killExisting;\n this.onError = onError;\n }\n\n public async startProcess(): Promise<ChildProcessWithoutNullStreams> {\n if (this._cwd && !fs.existsSync(this._cwd)) {\n throw new Error(`CWD not exists: ${this._cwd}`);\n }\n if (!this._port) {\n // find a port that does not have another process listening on it.\n while (true) {\n this._port = randomInt(10000, 50000);\n const pid = await checkPort(this._port);\n\n if (pid.length === 0) {\n break;\n }\n }\n } else {\n const pid = await checkPort(this._port);\n if (pid.length > 0) {\n if (this._killExisting) {\n log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`);\n // TODO(nf): verify the process is actually a signal server\n process.kill(-Number(pid), 'SIGINT');\n } else {\n throw new Error(`Port ${this._port} is already in use by process ${pid}`);\n }\n }\n }\n\n log('starting', {\n binCommand: this._binCommand,\n signalArguments: this._signalArguments,\n cwd: this._cwd,\n port: this._port,\n });\n\n const server = spawn(this._binCommand, [...this._signalArguments, '--port', this._port.toString()], {\n cwd: this._cwd,\n shell: this._shell,\n env: {\n ...process.env,\n ...this._env,\n },\n // Force creation of process group to ensure all child processes are killed.\n // https://nodejs.org/api/child_process.html#optionsdetached\n detached: true,\n });\n\n server.stdout.on('data', (data) => {\n log(`TestServer stdout: ${data}`);\n });\n\n server.stderr.on('data', (data) => {\n log.info(`TestServer stderr: ${data}`);\n });\n\n server.on('error', (err) => {\n log.error(`TestServer ERROR: ${err}`);\n this.onError?.(err);\n });\n\n server.on('close', (code) => {\n if ((code! -= 0)) {\n if (this.onError) {\n this.onError?.(new Error(`TestServer exited with code ${code}`));\n } else {\n throw new Error(`TestServer exited with code ${code}`);\n }\n } else {\n log.info(`TestServer exited with code ${code}`);\n }\n });\n\n this._serverProcess = server;\n return server;\n }\n\n public async waitUntilStarted(): Promise<void> {\n let waited = 0;\n const waitInc = 20;\n while (waited < this._timeout) {\n try {\n const response = await fetch(`http://localhost:${this._port}/.well-known/dx/signal`);\n log(`Fetching broker. Response=${JSON.stringify(response)}`);\n return;\n } catch (err) {\n await sleep(waitInc);\n waited = waited + waitInc;\n }\n }\n\n if (waited >= this._timeout) {\n await this.stop();\n await this.startProcess();\n this._startRetries++;\n if (this._startRetries > this._retriesLimit) {\n throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);\n }\n\n return await this.waitUntilStarted();\n }\n }\n\n public async stop(): Promise<void> {\n const pid = this._serverProcess?.pid;\n if (!pid) {\n log.warn('pid not found');\n return;\n }\n log.info(`sending SIGINT to process group ${pid}`);\n // kill process group so that all child processes can be killed, e.g. https://github.com/golang/go/issues/40467\n try {\n const delivered = process.kill(-pid, 'SIGINT');\n if (!delivered) {\n log.warn('kill signal was not delivered to child process');\n }\n } catch (err: any) {\n log.warn('kill error', { err });\n }\n }\n\n public url(): string {\n return `ws://localhost:${this._port}/.well-known/dx/signal`;\n }\n}\nconst ARCH = ['x64', 'amd64', 'ppc64'].includes(process.arch)\n ? 'amd64'\n : ['arm64'].includes(process.arch)\n ? 'arm64'\n : '32';\n\nconst OS = process.platform;\n\n/**\n * Creates a test instance of the signal server with swarming disabled and starts it.\n *\n * @param port Port to start the signal server on, random by default.\n */\n// TODO(burdon): Convert to TestBuilder pattern.\nexport const runTestSignalServer = async ({\n port,\n mode = 'server',\n killExisting = false,\n}: {\n port?: number;\n\n /**\n * Signal binary mode, `server` is in memory implementation.\n * @see https://github.com/dxos/kube\n */\n mode?: 'client' | 'server' | 'p2pserver' | 'keypair' | 'pubsubserver';\n killExisting?: boolean;\n} = {}): Promise<SignalServerRunner> => {\n if (ARCH === '32') {\n throw new Error('32 bit architecture not supported');\n }\n\n if (!['darwin', 'linux'].includes(OS)) {\n throw new Error(`Unsupported platform: ${OS}`);\n }\n\n const binPath = `./signal-test-${OS}-${ARCH}`;\n const server = new SignalServerRunner({\n binCommand: binPath,\n signalArguments: [mode],\n cwd: path.join(dirname(pkgUp.sync({ cwd: __dirname })!), 'bin'),\n port,\n killExisting,\n });\n await server.startProcess();\n await server.waitUntilStarted();\n return server;\n};\n\nexport const checkPort = async (port: number) => {\n let pid = '';\n try {\n const list = await find('port', port);\n if (list.length > 0) {\n pid = list[0].pid.toString();\n }\n } catch (err) {\n if (typeof err === 'object' && err !== null) {\n // lsof responds with status 1 if pattern does match, along with other errors :(, so this is the best we can do\n if ((err as Record<string, unknown>).status !== 1) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n return pid;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["find", "fetch", "spawn", "fs", "path", "dirname", "pkgUp", "sleep", "log", "randomInt", "SignalServerRunner", "constructor", "binCommand", "signalArguments", "cwd", "port", "timeout", "env", "shell", "killExisting", "onError", "_startRetries", "_retriesLimit", "_binCommand", "_signalArguments", "_cwd", "_port", "_timeout", "_env", "_shell", "_killExisting", "startProcess", "existsSync", "Error", "pid", "checkPort", "length", "warn", "process", "kill", "Number", "server", "toString", "detached", "stdout", "on", "data", "stderr", "info", "err", "error", "code", "_serverProcess", "waitUntilStarted", "waited", "waitInc", "response", "JSON", "stringify", "stop", "delivered", "url", "ARCH", "includes", "arch", "OS", "platform", "runTestSignalServer", "mode", "binPath", "join", "sync", "__dirname", "list", "status"]
7
+ }
@@ -0,0 +1 @@
1
+ {"inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytes":26639,"imports":[{"path":"find-process","kind":"import-statement","external":true},{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/signal/src/index.ts":{"bytes":529,"imports":[{"path":"packages/core/mesh/signal/src/signal-server-runner.ts","kind":"import-statement","original":"./signal-server-runner"}],"format":"esm"}},"outputs":{"packages/core/mesh/signal/dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":12252},"packages/core/mesh/signal/dist/lib/node-esm/index.mjs":{"imports":[{"path":"find-process","kind":"import-statement","external":true},{"path":"node-fetch","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"pkg-up","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["SignalServerRunner","checkPort","runTestSignalServer"],"entryPoint":"packages/core/mesh/signal/src/index.ts","inputs":{"packages/core/mesh/signal/src/signal-server-runner.ts":{"bytesInOutput":6497},"packages/core/mesh/signal/src/index.ts":{"bytesInOutput":0}},"bytes":6751}}}
@@ -27,7 +27,7 @@ export declare class SignalServerRunner {
27
27
  private readonly _timeout;
28
28
  private _serverProcess;
29
29
  constructor({ binCommand, signalArguments, cwd, port, timeout, env, shell, killExisting, onError, }: TestBrokerOptions);
30
- startProcess(): ChildProcessWithoutNullStreams;
30
+ startProcess(): Promise<ChildProcessWithoutNullStreams>;
31
31
  waitUntilStarted(): Promise<void>;
32
32
  stop(): Promise<void>;
33
33
  url(): string;
@@ -46,6 +46,6 @@ export declare const runTestSignalServer: ({ port, mode, killExisting, }?: {
46
46
  mode?: "client" | "server" | "p2pserver" | "keypair" | "pubsubserver";
47
47
  killExisting?: boolean;
48
48
  }) => Promise<SignalServerRunner>;
49
- export declare const checkPort: (port: number) => string;
49
+ export declare const checkPort: (port: number) => Promise<string>;
50
50
  export {};
51
51
  //# sourceMappingURL=signal-server-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signal-server-runner.d.ts","sourceRoot":"","sources":["../../../src/signal-server-runner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,8BAA8B,EAAmB,MAAM,oBAAoB,CAAC;AAS1F,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAE7B;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAqB;IAE9C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAK;IACnC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,cAAc,CAAiC;gBAE3C,EACV,UAAU,EACV,eAAe,EACf,GAAG,EACH,IAAI,EACJ,OAAgB,EAChB,GAAQ,EACR,KAAa,EACb,YAAoB,EACpB,OAAO,GACR,EAAE,iBAAiB;IAcb,YAAY,IAAI,8BAA8B;IA2ExC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B,GAAG,IAAI,MAAM;CAGrB;AASD;;;;GAIG;AAEH,eAAO,MAAM,mBAAmB,mCAI7B;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,cAAc,CAAC;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,KAAQ,OAAO,CAAC,kBAAkB,CAmBlC,CAAC;AAEF,eAAO,MAAM,SAAS,SAAU,MAAM,WAerC,CAAC"}
1
+ {"version":3,"file":"signal-server-runner.d.ts","sourceRoot":"","sources":["../../../src/signal-server-runner.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAC;AAShF,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAE7B;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAqB;IAE9C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAK;IACnC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,cAAc,CAA6C;gBAEvD,EACV,UAAU,EACV,eAAe,EACf,GAAG,EACH,IAAI,EACJ,OAAgB,EAChB,GAAQ,EACR,KAAa,EACb,YAAoB,EACpB,OAAO,GACR,EAAE,iBAAiB;IAYP,YAAY,IAAI,OAAO,CAAC,8BAA8B,CAAC;IA2EvD,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B,GAAG,IAAI,MAAM;CAGrB;AASD;;;;GAIG;AAEH,eAAO,MAAM,mBAAmB,mCAI7B;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,cAAc,CAAC;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,KAAQ,OAAO,CAAC,kBAAkB,CAoBlC,CAAC;AAEF,eAAO,MAAM,SAAS,SAAgB,MAAM,oBAkB3C,CAAC"}
package/package.json CHANGED
@@ -1,16 +1,18 @@
1
1
  {
2
2
  "name": "@dxos/signal",
3
- "version": "0.6.13",
3
+ "version": "0.6.14-main.2b6a0f3",
4
4
  "description": "DXOS signal server.",
5
5
  "homepage": "https://github.com/dxos/dxos/tree/main/packages/core/mesh/protocol-plugin-replicator#readme",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
7
  "repository": "github:dxos/dxos",
8
8
  "license": "MIT",
9
9
  "author": "DXOS.org",
10
+ "sideEffects": false,
10
11
  "exports": {
11
12
  ".": {
12
13
  "node": {
13
- "default": "./dist/lib/node/index.cjs"
14
+ "require": "./dist/lib/node/index.cjs",
15
+ "default": "./dist/lib/node-esm/index.mjs"
14
16
  },
15
17
  "types": "./dist/types/src/index.d.ts"
16
18
  }
@@ -20,17 +22,16 @@
20
22
  "*": {}
21
23
  },
22
24
  "dependencies": {
25
+ "find-process": "^1.4.7",
23
26
  "node-fetch": "^2.6.0",
24
27
  "pkg-up": "^3.1.0",
25
- "@dxos/async": "0.6.13",
26
- "@dxos/log": "0.6.13",
27
- "@dxos/util": "0.6.13"
28
+ "@dxos/async": "0.6.14-main.2b6a0f3",
29
+ "@dxos/log": "0.6.14-main.2b6a0f3",
30
+ "@dxos/util": "0.6.14-main.2b6a0f3"
28
31
  },
29
32
  "devDependencies": {
30
- "@types/node": "^18.11.9",
31
33
  "@types/node-fetch": "^2.5.10",
32
- "@dxos/protocols": "0.6.13",
33
- "@dxos/util": "0.6.13"
34
+ "@dxos/util": "0.6.14-main.2b6a0f3"
34
35
  },
35
36
  "publishConfig": {
36
37
  "access": "public"
package/project.json CHANGED
@@ -21,6 +21,7 @@
21
21
  "lint": {}
22
22
  },
23
23
  "implicitDependencies": [
24
- "esbuild"
24
+ "esbuild",
25
+ "node-std"
25
26
  ]
26
27
  }
@@ -2,8 +2,9 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
+ import find from 'find-process';
5
6
  import fetch from 'node-fetch';
6
- import { type ChildProcessWithoutNullStreams, execSync, spawn } from 'node:child_process';
7
+ import { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';
7
8
  import fs from 'node:fs';
8
9
  import path, { dirname } from 'node:path';
9
10
  import pkgUp from 'pkg-up';
@@ -42,7 +43,7 @@ export class SignalServerRunner {
42
43
  private readonly _retriesLimit = 3;
43
44
  private _port: number | undefined;
44
45
  private readonly _timeout: number;
45
- private _serverProcess: ChildProcessWithoutNullStreams;
46
+ private _serverProcess: ChildProcessWithoutNullStreams | undefined;
46
47
 
47
48
  constructor({
48
49
  binCommand,
@@ -64,11 +65,9 @@ export class SignalServerRunner {
64
65
  this._shell = shell;
65
66
  this._killExisting = killExisting;
66
67
  this.onError = onError;
67
-
68
- this._serverProcess = this.startProcess();
69
68
  }
70
69
 
71
- public startProcess(): ChildProcessWithoutNullStreams {
70
+ public async startProcess(): Promise<ChildProcessWithoutNullStreams> {
72
71
  if (this._cwd && !fs.existsSync(this._cwd)) {
73
72
  throw new Error(`CWD not exists: ${this._cwd}`);
74
73
  }
@@ -76,14 +75,14 @@ export class SignalServerRunner {
76
75
  // find a port that does not have another process listening on it.
77
76
  while (true) {
78
77
  this._port = randomInt(10000, 50000);
79
- const pid = checkPort(this._port);
78
+ const pid = await checkPort(this._port);
80
79
 
81
80
  if (pid.length === 0) {
82
81
  break;
83
82
  }
84
83
  }
85
84
  } else {
86
- const pid = checkPort(this._port);
85
+ const pid = await checkPort(this._port);
87
86
  if (pid.length > 0) {
88
87
  if (this._killExisting) {
89
88
  log.warn(`Port ${this._port} is already in use by process ${pid}, killing it`);
@@ -159,7 +158,7 @@ export class SignalServerRunner {
159
158
 
160
159
  if (waited >= this._timeout) {
161
160
  await this.stop();
162
- this._serverProcess = this.startProcess();
161
+ await this.startProcess();
163
162
  this._startRetries++;
164
163
  if (this._startRetries > this._retriesLimit) {
165
164
  throw new Error(`Test Signal server was not started in ${this._retriesLimit} retries`);
@@ -170,7 +169,7 @@ export class SignalServerRunner {
170
169
  }
171
170
 
172
171
  public async stop(): Promise<void> {
173
- const pid = this._serverProcess.pid;
172
+ const pid = this._serverProcess?.pid;
174
173
  if (!pid) {
175
174
  log.warn('pid not found');
176
175
  return;
@@ -235,14 +234,18 @@ export const runTestSignalServer = async ({
235
234
  port,
236
235
  killExisting,
237
236
  });
237
+ await server.startProcess();
238
238
  await server.waitUntilStarted();
239
239
  return server;
240
240
  };
241
241
 
242
- export const checkPort = (port: number) => {
242
+ export const checkPort = async (port: number) => {
243
243
  let pid = '';
244
244
  try {
245
- pid = execSync(`lsof -t -i:${port}`).toString().trim();
245
+ const list = await find('port', port);
246
+ if (list.length > 0) {
247
+ pid = list[0].pid.toString();
248
+ }
246
249
  } catch (err) {
247
250
  if (typeof err === 'object' && err !== null) {
248
251
  // lsof responds with status 1 if pattern does match, along with other errors :(, so this is the best we can do
package/tsconfig.json CHANGED
@@ -1,23 +1,8 @@
1
1
  {
2
2
  "extends": "../../../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist/types"
5
- },
3
+ "compilerOptions": {},
6
4
  "include": [
7
5
  "src/**/*"
8
6
  ],
9
- "references": [
10
- {
11
- "path": "../../../common/async"
12
- },
13
- {
14
- "path": "../../../common/log"
15
- },
16
- {
17
- "path": "../../../common/util"
18
- },
19
- {
20
- "path": "../../protocols"
21
- }
22
- ]
7
+ "references": []
23
8
  }