prool 0.0.13 → 0.0.15

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # prool
2
2
 
3
+ ## 0.0.15
4
+
5
+ ### Patch Changes
6
+
7
+ - [#20](https://github.com/wevm/prool/pull/20) [`e1ebc61`](https://github.com/wevm/prool/commit/e1ebc61a888751298526f7126fe69d042551da7b) Thanks [@jxom](https://github.com/jxom)! - Added Silius instance.
8
+
9
+ ## 0.0.14
10
+
11
+ ### Patch Changes
12
+
13
+ - [`0187ef8`](https://github.com/wevm/prool/commit/0187ef8a00ea4b25367b8427ed00d217388f3d65) Thanks [@jxom](https://github.com/jxom)! - Added Rundler instance.
14
+
3
15
  ## 0.0.13
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -39,7 +39,7 @@ Prool is a library that provides programmatic HTTP testing instances for Ethereu
39
39
  Prool contains a set of pre-configured instances that can be used to simulate Ethereum server environments, being:
40
40
 
41
41
  - **Local Execution Nodes:** [`anvil`](#anvil-execution-node)
42
- - **Bundler Nodes:** [`alto`](#alto-bundler-node), [`rundler`](#rundler), `silius`⚠️, [`stackup`](#stackup-bundler-node)
42
+ - **Bundler Nodes:** [`alto`](#alto-bundler-node), [`rundler`](#rundler-bundler-node), [`silius`](#silius-bundler-node), [`stackup`](#stackup-bundler-node)
43
43
  - **Indexer Nodes:** `ponder`⚠️
44
44
 
45
45
  ⚠️ = soon
@@ -53,6 +53,7 @@ You can also create your own custom instances by using the [`defineInstance` fun
53
53
  - [Anvil (Execution Node)](#anvil-execution-node)
54
54
  - [Alto (Bundler Node)](#alto-bundler-node)
55
55
  - [Rundler (Bundler Node)](#rundler-bundler-node)
56
+ - [Silius (Bundler Node)](#silius-bundler-node)
56
57
  - [Stackup (Bundler Node)](#stackup-bundler-node)
57
58
  - [Reference](#reference)
58
59
  - [`createServer`](#createserver)
@@ -188,6 +189,48 @@ await bundlerServer.start()
188
189
 
189
190
  See [RundlerParameters]().
190
191
 
192
+ ### Silius (Bundler Node)
193
+
194
+ #### Requirements
195
+
196
+ - [Docker](https://docs.docker.com/get-docker/)
197
+ - Silius Docker Image: `docker pull silius-rs/silius`
198
+
199
+ #### Usage
200
+
201
+ ```ts
202
+ import { createServer } from 'prool'
203
+ import { anvil, silius } from 'prool/instances'
204
+
205
+ const executionServer = createServer({
206
+ instance: anvil(),
207
+ port: 8545
208
+ })
209
+ await executionServer.start()
210
+ // Instances accessible at:
211
+ // "http://localhost:8545/1"
212
+ // "http://localhost:8545/2"
213
+ // "http://localhost:8545/3"
214
+ // "http://localhost:8545/n"
215
+
216
+ const bundlerServer = createServer({
217
+ instance: (key) => silius({
218
+ ethClientAddress: `http://localhost:8545/${key}`,
219
+ mnemonicPath: './keys/0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
220
+ })
221
+ })
222
+ await bundlerServer.start()
223
+ // Instances accessible at:
224
+ // "http://localhost:4000/1" (→ http://localhost:8545/1)
225
+ // "http://localhost:4000/2" (→ http://localhost:8545/2)
226
+ // "http://localhost:4000/3" (→ http://localhost:8545/3)
227
+ // "http://localhost:4000/n" (→ http://localhost:8545/n)
228
+ ```
229
+
230
+ #### Parameters
231
+
232
+ See [`SiliusParameters`]().
233
+
191
234
  ### Stackup (Bundler Node)
192
235
 
193
236
  #### Requirements
@@ -1,5 +1,6 @@
1
1
  export { alto, type AltoParameters } from '../instances/alto.js';
2
2
  export { anvil, type AnvilParameters } from '../instances/anvil.js';
3
3
  export { rundler, type RundlerParameters } from '../instances/rundler.js';
4
+ export { silius, type SiliusParameters } from '../instances/silius.js';
4
5
  export { stackup, type StackupParameters } from '../instances/stackup.js';
5
6
  //# sourceMappingURL=instances.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../exports/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../exports/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,MAAM,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
@@ -1,5 +1,6 @@
1
1
  export { alto } from '../instances/alto.js';
2
2
  export { anvil } from '../instances/anvil.js';
3
3
  export { rundler } from '../instances/rundler.js';
4
+ export { silius } from '../instances/silius.js';
4
5
  export { stackup } from '../instances/stackup.js';
5
6
  //# sourceMappingURL=instances.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../exports/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAwB,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,OAAO,EAA0B,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,OAAO,EAA0B,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../exports/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAwB,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,OAAO,EAA0B,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,MAAM,EAAyB,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,OAAO,EAA0B,MAAM,yBAAyB,CAAA"}
@@ -0,0 +1,224 @@
1
+ export type SiliusParameters = {
2
+ /**
3
+ * The bundler beneficiary address.
4
+ */
5
+ beneficiary?: string | undefined;
6
+ /**
7
+ * The bundle interval in seconds.
8
+ * @default 10
9
+ */
10
+ bundleInterval?: number | undefined;
11
+ bundler?: {
12
+ /**
13
+ * Bundler gRPC address to listen on.
14
+ * @default '127.0.0.1'
15
+ */
16
+ addr?: string | undefined;
17
+ /**
18
+ * Bundler gRPC port to listen on.
19
+ * @default 3003
20
+ */
21
+ port?: number | undefined;
22
+ } | undefined;
23
+ /**
24
+ * The chain id.
25
+ * @default 1
26
+ */
27
+ chain?: number | undefined;
28
+ /**
29
+ * Path to the data directory.
30
+ */
31
+ dataDir?: string | undefined;
32
+ discovery?: {
33
+ /**
34
+ * The udp4 port to broadcast to peers in order to reach back for discovery.
35
+ * @default 9000
36
+ */
37
+ port?: number | undefined;
38
+ } | undefined;
39
+ /**
40
+ * Indicates whether the access list is enabled.
41
+ */
42
+ enableAccessList?: boolean | undefined;
43
+ /**
44
+ * Indicates whether the P2P mode is enabled.
45
+ */
46
+ enableP2p?: boolean | undefined;
47
+ /**
48
+ * Indicates whether the metrics are enabled.
49
+ */
50
+ enableMetrics?: boolean | undefined;
51
+ /**
52
+ * The entry points for the bundler.
53
+ */
54
+ entryPoints?: string[] | undefined;
55
+ /**
56
+ * RPC URL of the execution client.
57
+ */
58
+ ethClientAddress?: string | undefined;
59
+ /**
60
+ * Ethereum execution client proxy HTTP RPC endpoint.
61
+ */
62
+ ethClientProxyAddress?: string | undefined;
63
+ http?: {
64
+ /**
65
+ * HTTP address to listen on.
66
+ * @default '127.0.0.1'
67
+ */
68
+ addr?: string | undefined;
69
+ /**
70
+ * Configures the HTTP RPC API modules
71
+ * @default 'eth'
72
+ */
73
+ api?: string[] | undefined;
74
+ /**
75
+ * Configures the allowed CORS domains.
76
+ * @default '*'
77
+ */
78
+ corsdomain?: string[] | undefined;
79
+ /**
80
+ * HTTP port to listen on.
81
+ * @default 3000
82
+ */
83
+ port?: number | undefined;
84
+ } | undefined;
85
+ /**
86
+ * Maximum gas for verification.
87
+ * @default 5000000
88
+ */
89
+ maxVerificationGas?: bigint | undefined;
90
+ metrics?: {
91
+ /**
92
+ * Metrics address to listen on.
93
+ * @default '127.0.0.1'
94
+ */
95
+ addr?: string | undefined;
96
+ /**
97
+ * Metrics port to listen on.
98
+ * @default 3030
99
+ */
100
+ port?: number | undefined;
101
+ } | undefined;
102
+ /**
103
+ * Minimum balance for the beneficiary account.
104
+ * @default 100000000000000000 wei
105
+ */
106
+ minBalance?: bigint | undefined;
107
+ /**
108
+ * Minimum priority fee per gas.
109
+ * @default 0
110
+ */
111
+ minPriorityFeePerGas?: bigint | undefined;
112
+ /**
113
+ * Minimum stake required for entities.
114
+ * @default 1
115
+ */
116
+ minStake?: number | undefined;
117
+ /**
118
+ * Path to the mnemonic file.
119
+ */
120
+ mnemonicPath: string | undefined;
121
+ /**
122
+ * The path to the file where the p2p private key is stored.
123
+ */
124
+ nodekey?: string | undefined;
125
+ /**
126
+ * The path to the file where the p2p enr is stored.
127
+ */
128
+ nodeenr?: string | undefined;
129
+ p2p?: {
130
+ /**
131
+ * Sets the p2p listen address
132
+ * @default '0.0.0.0'
133
+ */
134
+ addr?: string | undefined;
135
+ /**
136
+ * The ipv4 address to broadcast to peers about which address we are listening on.
137
+ */
138
+ baddr?: string | undefined;
139
+ /**
140
+ * The tcp4 port to boardcast to peers in order to reach back for discovery.
141
+ * @default 9000
142
+ */
143
+ bport?: number | undefined;
144
+ } | undefined;
145
+ /**
146
+ * Poll interval event filters and pending transactions in milliseconds.
147
+ * @default 500
148
+ */
149
+ pollInterval?: number | undefined;
150
+ /**
151
+ * Port to start the instance on.
152
+ */
153
+ port?: number | undefined;
154
+ /**
155
+ * Sets the send bundle mode.
156
+ * @default "ethereum-client"
157
+ */
158
+ sendBundleMode?: string | undefined;
159
+ uopool?: {
160
+ /**
161
+ * UoPool gRPC address to listen on.
162
+ * @default '127.0.0.1'
163
+ */
164
+ addr?: string | undefined;
165
+ /**
166
+ * UoPool gRPC port to listen on.
167
+ * @default 3002
168
+ */
169
+ port?: number | undefined;
170
+ } | undefined;
171
+ /**
172
+ * Sets the UoPool mode.
173
+ */
174
+ uopoolMode?: string | undefined;
175
+ /**
176
+ * Sets the verbosity level.
177
+ * @default 2
178
+ */
179
+ verbosity?: number | undefined;
180
+ /**
181
+ * Addresses of whitelisted entities.
182
+ */
183
+ whitelist?: string[] | undefined;
184
+ ws?: {
185
+ /**
186
+ * WS address to listen on.
187
+ * @default '127.0.0.1'
188
+ */
189
+ addr?: string | undefined;
190
+ /**
191
+ * Configures the HTTP RPC API modules
192
+ * @default 'eth'
193
+ */
194
+ api?: string[] | undefined;
195
+ /**
196
+ * Configures the allowed WS origins.
197
+ * @default '*'
198
+ */
199
+ origins?: string[] | undefined;
200
+ /**
201
+ * WS port to listen on.
202
+ * @default 3001
203
+ */
204
+ port?: number | undefined;
205
+ } | undefined;
206
+ };
207
+ /**
208
+ * Defines an Anvil instance.
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * const instance = silius({
213
+ * port: 4337,
214
+ * })
215
+ * await instance.start()
216
+ * // ...
217
+ * await instance.stop()
218
+ * ```
219
+ */
220
+ export declare const silius: import("../instance.js").DefineInstanceReturnType<{
221
+ args: SiliusParameters;
222
+ readonly process: import("../processes/execa.js").Process_internal;
223
+ }, SiliusParameters | undefined>;
224
+ //# sourceMappingURL=silius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silius.d.ts","sourceRoot":"","sources":["../../instances/silius.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { platform } from 'node:os';
2
+ import { rmSync } from 'node:fs';
3
+ import { defineInstance } from '../instance.js';
4
+ import { execa } from '../processes/execa.js';
5
+ import { toArgs } from '../utils.js';
6
+ /**
7
+ * Defines an Anvil instance.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const instance = silius({
12
+ * port: 4337,
13
+ * })
14
+ * await instance.start()
15
+ * // ...
16
+ * await instance.stop()
17
+ * ```
18
+ */
19
+ export const silius = defineInstance((parameters) => {
20
+ const args = (parameters || {});
21
+ const { dataDir = '.local', mnemonicPath, port: _, ...rest } = args;
22
+ const host = 'localhost';
23
+ const name = 'silius';
24
+ const process = execa({ name });
25
+ let port = args.port ?? 4000;
26
+ return {
27
+ _internal: {
28
+ args,
29
+ get process() {
30
+ return process._internal.process;
31
+ },
32
+ },
33
+ host,
34
+ name,
35
+ port,
36
+ async start({ port: port_ = port }, options) {
37
+ port = port_;
38
+ const args_ = [
39
+ ...(platform() === 'linux' ? ['--net', 'host'] : []),
40
+ '--add-host',
41
+ 'host.docker.internal:host-gateway',
42
+ '--add-host',
43
+ 'localhost:host-gateway',
44
+ '-p',
45
+ `${port}:${port}`,
46
+ '-v',
47
+ `${mnemonicPath}:/data/silius/mnemonic`,
48
+ '-v',
49
+ `./${dataDir}/${port_}/db:/data/silius/db`,
50
+ 'ghcr.io/silius-rs/silius:latest',
51
+ 'node',
52
+ '--datadir',
53
+ 'data/silius',
54
+ '--mnemonic-file',
55
+ 'data/silius/mnemonic',
56
+ '--http',
57
+ '--ws',
58
+ ...toArgs({
59
+ ...rest,
60
+ beneficiary: rest.beneficiary ?? '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
61
+ bundler: {
62
+ ...rest.bundler,
63
+ addr: rest.bundler?.addr ?? '0.0.0.0',
64
+ },
65
+ entryPoints: rest.entryPoints ?? [
66
+ '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
67
+ ],
68
+ ethClientAddress: rest.ethClientAddress?.replaceAll(/127\.0\.0\.1|0\.0\.0\.0/g, 'host.docker.internal'),
69
+ ethClientProxyAddress: rest.ethClientProxyAddress?.replaceAll(/127\.0\.0\.1|0\.0\.0\.0/g, 'host.docker.internal'),
70
+ http: {
71
+ ...rest.http,
72
+ addr: rest.http?.addr ?? '0.0.0.0',
73
+ api: rest.http?.api ?? ['eth', 'debug', 'web3'],
74
+ port,
75
+ },
76
+ metrics: {
77
+ ...rest.metrics,
78
+ addr: rest.metrics?.addr ?? '0.0.0.0',
79
+ },
80
+ uopool: {
81
+ ...rest.uopool,
82
+ addr: rest.uopool?.addr ?? '0.0.0.0',
83
+ },
84
+ ws: {
85
+ ...rest.ws,
86
+ addr: rest.ws?.addr ?? '0.0.0.0',
87
+ api: rest.ws?.api ?? ['eth', 'debug', 'web3'],
88
+ port: rest.ws?.port ?? 4001,
89
+ },
90
+ }),
91
+ ];
92
+ return await process.start(($) => $ `docker run ${args_}`, {
93
+ ...options,
94
+ resolver({ process, resolve, reject }) {
95
+ process.stdout.on('data', (data) => {
96
+ const message = data.toString();
97
+ if (message.includes('Started bundler JSON-RPC server'))
98
+ resolve();
99
+ });
100
+ process.stderr.on('data', (data) => {
101
+ if (data.toString().includes('WARNING'))
102
+ return;
103
+ reject(data);
104
+ });
105
+ },
106
+ });
107
+ },
108
+ async stop() {
109
+ try {
110
+ rmSync(`${dataDir}/${port}`, { recursive: true, force: true });
111
+ }
112
+ catch { }
113
+ await process.stop();
114
+ },
115
+ };
116
+ });
117
+ //# sourceMappingURL=silius.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silius.js","sourceRoot":"","sources":["../../instances/silius.ts"],"names":[],"mappings":"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"}
package/_lib/utils.js CHANGED
@@ -48,7 +48,7 @@ export function toArgs(obj, options = { casing: 'kebab' }) {
48
48
  if (subValue === undefined)
49
49
  return [];
50
50
  const flag = toFlagCase(`${key}.${subKey}`, casing === 'kebab' ? '-' : '_');
51
- return [flag, subValue];
51
+ return [flag, Array.isArray(subValue) ? subValue.join(',') : subValue];
52
52
  });
53
53
  }
54
54
  const flag = toFlagCase(key, casing === 'kebab' ? '-' : '_');
package/_lib/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ test('exports', () => {
7
7
  "alto",
8
8
  "anvil",
9
9
  "rundler",
10
+ "silius",
10
11
  "stackup",
11
12
  ]
12
13
  `)
@@ -1,4 +1,5 @@
1
1
  export { alto, type AltoParameters } from '../instances/alto.js'
2
2
  export { anvil, type AnvilParameters } from '../instances/anvil.js'
3
3
  export { rundler, type RundlerParameters } from '../instances/rundler.js'
4
+ export { silius, type SiliusParameters } from '../instances/silius.js'
4
5
  export { stackup, type StackupParameters } from '../instances/stackup.js'
@@ -86,7 +86,7 @@ test('behavior: can subscribe to stderr', async () => {
86
86
  )
87
87
  })
88
88
 
89
- test('behavior: starts anvil with custom options', async () => {
89
+ test.skip('behavior: starts anvil with custom options', async () => {
90
90
  const instance = defineInstance({
91
91
  timestamp,
92
92
  chainId: 123,
@@ -0,0 +1,108 @@
1
+ import getPort from 'get-port'
2
+ import { afterEach, beforeAll, expect, test } from 'vitest'
3
+
4
+ import { siliusOptions } from '../../test/utils.js'
5
+ import type { Instance } from '../instance.js'
6
+ import { anvil } from './anvil.js'
7
+ import { silius } from './silius.js'
8
+
9
+ const instances: Instance[] = []
10
+
11
+ const port = await getPort()
12
+
13
+ const defineInstance = (parameters?: Partial<{}>) => {
14
+ const instance = silius({
15
+ ...siliusOptions({ port }),
16
+ ...parameters,
17
+ })
18
+ instances.push(instance)
19
+ return instance
20
+ }
21
+
22
+ beforeAll(() => anvil({ port }).start())
23
+
24
+ afterEach(async () => {
25
+ for (const instance of instances) await instance.stop().catch(() => {})
26
+ })
27
+
28
+ test('default', async () => {
29
+ const messages: string[] = []
30
+ const stdouts: string[] = []
31
+
32
+ const instance = defineInstance()
33
+
34
+ instance.on('message', (m) => messages.push(m))
35
+ instance.on('stdout', (m) => stdouts.push(m))
36
+
37
+ expect(instance.messages.get()).toMatchInlineSnapshot('[]')
38
+
39
+ await instance.start()
40
+ expect(instance.status).toEqual('started')
41
+
42
+ expect(messages.join('')).toBeDefined()
43
+ expect(stdouts.join('')).toBeDefined()
44
+ expect(instance.messages.get().join('')).toBeDefined()
45
+
46
+ await instance.stop()
47
+ expect(instance.status).toEqual('stopped')
48
+
49
+ expect(messages.join('')).toBeDefined()
50
+ expect(stdouts.join('')).toBeDefined()
51
+ expect(instance.messages.get()).toMatchInlineSnapshot('[]')
52
+ })
53
+
54
+ test('behavior: instance errored (duplicate ports)', async () => {
55
+ const instance_1 = defineInstance({
56
+ port: 1337,
57
+ })
58
+ const instance_2 = defineInstance({
59
+ port: 1337,
60
+ })
61
+
62
+ await instance_1.start()
63
+ await expect(() => instance_2.start()).rejects.toThrowError()
64
+ })
65
+
66
+ test('behavior: start and stop multiple times', async () => {
67
+ const instance = defineInstance()
68
+
69
+ await instance.start()
70
+ await instance.stop()
71
+ await instance.start()
72
+ await instance.stop()
73
+ await instance.start()
74
+ await instance.stop()
75
+ await instance.start()
76
+ await instance.stop()
77
+ })
78
+
79
+ test('behavior: can subscribe to stderr', async () => {
80
+ const messages: string[] = []
81
+
82
+ const instance_1 = defineInstance({ port: 1338 })
83
+ const instance_2 = defineInstance({ port: 1338 })
84
+
85
+ await instance_1.start()
86
+ instance_2.on('stderr', (message) => messages.push(message))
87
+ await expect(instance_2.start()).rejects.toThrowError()
88
+ })
89
+
90
+ test('behavior: exit', async () => {
91
+ const instance = defineInstance()
92
+ const { promise, resolve } = Promise.withResolvers<void>()
93
+
94
+ let exitCode: number | null | undefined = undefined
95
+ instance.on('exit', (code) => {
96
+ exitCode = code
97
+ resolve()
98
+ })
99
+
100
+ await instance.start()
101
+ expect(instance.status).toEqual('started')
102
+
103
+ instance._internal.process.kill()
104
+
105
+ await promise
106
+ expect(instance.status).toEqual('stopped')
107
+ expect(typeof exitCode !== 'undefined').toBeTruthy()
108
+ })