@korajs/test 0.1.0
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/dist/index.cjs +434 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +239 -0
- package/dist/index.d.ts +239 -0
- package/dist/index.js +392 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { SchemaDefinition, Operation, KoraEventEmitter, VersionVector } from '@korajs/core';
|
|
2
|
+
import * as _korajs_server from '@korajs/server';
|
|
3
|
+
import { MemoryServerStore, ServerTransport } from '@korajs/server';
|
|
4
|
+
import { Store, CollectionAccessor } from '@korajs/store';
|
|
5
|
+
import { SyncTransport } from '@korajs/sync';
|
|
6
|
+
export { ChaosConfig, ChaosTransport } from '@korajs/sync';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-memory test server wrapping KoraSyncServer with MemoryServerStore.
|
|
10
|
+
* Handles client connections via memory transports.
|
|
11
|
+
*/
|
|
12
|
+
declare class TestServer {
|
|
13
|
+
readonly store: MemoryServerStore;
|
|
14
|
+
private readonly syncServer;
|
|
15
|
+
constructor(schema: SchemaDefinition);
|
|
16
|
+
/**
|
|
17
|
+
* Register a client connection transport with the server.
|
|
18
|
+
* Returns the session ID assigned by the server.
|
|
19
|
+
*/
|
|
20
|
+
handleConnection(transport: ServerTransport): string;
|
|
21
|
+
/**
|
|
22
|
+
* Get all operations stored on the server.
|
|
23
|
+
*/
|
|
24
|
+
getAllOperations(): Operation[];
|
|
25
|
+
/**
|
|
26
|
+
* Get the number of connected clients.
|
|
27
|
+
*/
|
|
28
|
+
getConnectionCount(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Shut down the server and close all sessions.
|
|
31
|
+
*/
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Options for creating a TestDevice.
|
|
37
|
+
*/
|
|
38
|
+
interface TestDeviceOptions {
|
|
39
|
+
/** Unique device name (used for DB file naming) */
|
|
40
|
+
name: string;
|
|
41
|
+
/** Schema definition */
|
|
42
|
+
schema: SchemaDefinition;
|
|
43
|
+
/** Test server to connect to */
|
|
44
|
+
server: TestServer;
|
|
45
|
+
/** Transport factory — creates a linked client/server transport pair */
|
|
46
|
+
createTransportPair: () => {
|
|
47
|
+
client: SyncTransport;
|
|
48
|
+
serverTransport: _korajs_server.ServerTransport;
|
|
49
|
+
};
|
|
50
|
+
/** Optional directory for temp DB files */
|
|
51
|
+
tmpDir: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A virtual device in a test network.
|
|
55
|
+
* Each device has its own Store (with real SQLite), SyncEngine, and MergeEngine.
|
|
56
|
+
* Provides high-level methods for syncing, disconnecting, and inspecting state.
|
|
57
|
+
*/
|
|
58
|
+
declare class TestDevice {
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly store: Store;
|
|
61
|
+
readonly emitter: KoraEventEmitter & {
|
|
62
|
+
clear(): void;
|
|
63
|
+
};
|
|
64
|
+
private readonly schema;
|
|
65
|
+
private readonly server;
|
|
66
|
+
private readonly mergeEngine;
|
|
67
|
+
private readonly createTransportPair;
|
|
68
|
+
private readonly adapter;
|
|
69
|
+
private readonly dbPath;
|
|
70
|
+
private syncEngine;
|
|
71
|
+
private currentTransport;
|
|
72
|
+
private unsubscribeSync;
|
|
73
|
+
private closing;
|
|
74
|
+
constructor(options: TestDeviceOptions);
|
|
75
|
+
/**
|
|
76
|
+
* Open the store (must be called before sync or collection operations).
|
|
77
|
+
*/
|
|
78
|
+
open(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Connect to the test server and perform initial sync.
|
|
81
|
+
* If already connected, flushes any pending operations.
|
|
82
|
+
*/
|
|
83
|
+
sync(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Disconnect from the test server.
|
|
86
|
+
*/
|
|
87
|
+
disconnect(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Reconnect to the test server after a disconnect.
|
|
90
|
+
*/
|
|
91
|
+
reconnect(): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Get a collection accessor for performing CRUD operations.
|
|
94
|
+
*/
|
|
95
|
+
collection(name: string): CollectionAccessor;
|
|
96
|
+
/**
|
|
97
|
+
* Get all records from a collection (convenience method).
|
|
98
|
+
*/
|
|
99
|
+
getState(collectionName: string): Promise<Record<string, unknown>[]>;
|
|
100
|
+
/**
|
|
101
|
+
* Get the device's node ID.
|
|
102
|
+
*/
|
|
103
|
+
getNodeId(): string;
|
|
104
|
+
/**
|
|
105
|
+
* Get the device's version vector.
|
|
106
|
+
*/
|
|
107
|
+
getVersionVector(): VersionVector;
|
|
108
|
+
/**
|
|
109
|
+
* Check if the device is currently connected to the server.
|
|
110
|
+
*/
|
|
111
|
+
isConnected(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Close the device, releasing all resources.
|
|
114
|
+
*/
|
|
115
|
+
close(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Create a SyncStore wrapper that interposes merge resolution.
|
|
118
|
+
* Simplified version of MergeAwareSyncStore from the kora meta-package.
|
|
119
|
+
*/
|
|
120
|
+
private createMergeAwareSyncStore;
|
|
121
|
+
/**
|
|
122
|
+
* Wait for in-flight sync operations to settle.
|
|
123
|
+
* In-memory transports are near-synchronous, so a microtask flush suffices.
|
|
124
|
+
*/
|
|
125
|
+
private waitForSettled;
|
|
126
|
+
/**
|
|
127
|
+
* Wait for all pending outbound operations to be acknowledged.
|
|
128
|
+
*/
|
|
129
|
+
private waitForPendingOps;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Options for creating a test network.
|
|
134
|
+
*/
|
|
135
|
+
interface TestNetworkOptions {
|
|
136
|
+
/** Number of devices to create. Defaults to 2. */
|
|
137
|
+
devices?: number;
|
|
138
|
+
/** Custom device names. If not provided, uses 'device-0', 'device-1', etc. */
|
|
139
|
+
deviceNames?: string[];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A test network with a server and multiple devices.
|
|
143
|
+
*/
|
|
144
|
+
interface TestNetwork {
|
|
145
|
+
/** The test server */
|
|
146
|
+
server: TestServer;
|
|
147
|
+
/** All devices in the network */
|
|
148
|
+
devices: TestDevice[];
|
|
149
|
+
/** Temporary directory for DB files */
|
|
150
|
+
tmpDir: string;
|
|
151
|
+
/** Close all devices and the server, clean up temp files */
|
|
152
|
+
close(): Promise<void>;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Create a test network with a server and multiple virtual devices.
|
|
156
|
+
*
|
|
157
|
+
* Each device has its own local SQLite store and SyncEngine. Devices
|
|
158
|
+
* communicate with the server via in-memory transports.
|
|
159
|
+
*
|
|
160
|
+
* @param schema - The schema all devices share
|
|
161
|
+
* @param options - Network configuration
|
|
162
|
+
* @returns A test network with server and devices ready for use
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* const network = await createTestNetwork(schema, { devices: 2 })
|
|
167
|
+
* const [deviceA, deviceB] = network.devices
|
|
168
|
+
*
|
|
169
|
+
* await deviceA.collection('todos').insert({ title: 'Hello' })
|
|
170
|
+
* await deviceA.sync()
|
|
171
|
+
* await deviceB.sync()
|
|
172
|
+
*
|
|
173
|
+
* const todos = await deviceB.getState('todos')
|
|
174
|
+
* expect(todos).toHaveLength(1)
|
|
175
|
+
*
|
|
176
|
+
* await network.close()
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare function createTestNetwork(schema: SchemaDefinition, options?: TestNetworkOptions): Promise<TestNetwork>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Result of a convergence check.
|
|
183
|
+
*/
|
|
184
|
+
interface ConvergenceResult {
|
|
185
|
+
/** Whether all devices have converged to the same state */
|
|
186
|
+
converged: boolean;
|
|
187
|
+
/** Per-collection comparison details (only populated on failure) */
|
|
188
|
+
differences: CollectionDifference[];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Describes a difference in a collection between devices.
|
|
192
|
+
*/
|
|
193
|
+
interface CollectionDifference {
|
|
194
|
+
collection: string;
|
|
195
|
+
deviceA: string;
|
|
196
|
+
deviceB: string;
|
|
197
|
+
/** Records present in deviceA but not deviceB */
|
|
198
|
+
missingInB: string[];
|
|
199
|
+
/** Records present in deviceB but not deviceA */
|
|
200
|
+
missingInA: string[];
|
|
201
|
+
/** Records present in both but with different values */
|
|
202
|
+
fieldDifferences: FieldDifference[];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* A specific field-level difference between two devices.
|
|
206
|
+
*/
|
|
207
|
+
interface FieldDifference {
|
|
208
|
+
recordId: string;
|
|
209
|
+
field: string;
|
|
210
|
+
valueInA: unknown;
|
|
211
|
+
valueInB: unknown;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Assert that all devices have converged to identical collection states.
|
|
215
|
+
*
|
|
216
|
+
* Compares every collection across all device pairs. Throws an error
|
|
217
|
+
* with detailed diagnostics if any differences are found.
|
|
218
|
+
*
|
|
219
|
+
* @param devices - The devices to check for convergence
|
|
220
|
+
* @param schema - The schema (used to enumerate collections)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* await deviceA.sync()
|
|
225
|
+
* await deviceB.sync()
|
|
226
|
+
* await expectConverged([deviceA, deviceB], schema)
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
declare function expectConverged(devices: TestDevice[], schema: SchemaDefinition): Promise<void>;
|
|
230
|
+
/**
|
|
231
|
+
* Check whether all devices have converged without throwing.
|
|
232
|
+
*
|
|
233
|
+
* @param devices - The devices to check
|
|
234
|
+
* @param schema - The schema (for collection enumeration)
|
|
235
|
+
* @returns Convergence result with details
|
|
236
|
+
*/
|
|
237
|
+
declare function checkConvergence(devices: TestDevice[], schema: SchemaDefinition): Promise<ConvergenceResult>;
|
|
238
|
+
|
|
239
|
+
export { type CollectionDifference, type ConvergenceResult, type FieldDifference, TestDevice, type TestDeviceOptions, type TestNetwork, type TestNetworkOptions, TestServer, checkConvergence, createTestNetwork, expectConverged };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { SchemaDefinition, Operation, KoraEventEmitter, VersionVector } from '@korajs/core';
|
|
2
|
+
import * as _korajs_server from '@korajs/server';
|
|
3
|
+
import { MemoryServerStore, ServerTransport } from '@korajs/server';
|
|
4
|
+
import { Store, CollectionAccessor } from '@korajs/store';
|
|
5
|
+
import { SyncTransport } from '@korajs/sync';
|
|
6
|
+
export { ChaosConfig, ChaosTransport } from '@korajs/sync';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-memory test server wrapping KoraSyncServer with MemoryServerStore.
|
|
10
|
+
* Handles client connections via memory transports.
|
|
11
|
+
*/
|
|
12
|
+
declare class TestServer {
|
|
13
|
+
readonly store: MemoryServerStore;
|
|
14
|
+
private readonly syncServer;
|
|
15
|
+
constructor(schema: SchemaDefinition);
|
|
16
|
+
/**
|
|
17
|
+
* Register a client connection transport with the server.
|
|
18
|
+
* Returns the session ID assigned by the server.
|
|
19
|
+
*/
|
|
20
|
+
handleConnection(transport: ServerTransport): string;
|
|
21
|
+
/**
|
|
22
|
+
* Get all operations stored on the server.
|
|
23
|
+
*/
|
|
24
|
+
getAllOperations(): Operation[];
|
|
25
|
+
/**
|
|
26
|
+
* Get the number of connected clients.
|
|
27
|
+
*/
|
|
28
|
+
getConnectionCount(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Shut down the server and close all sessions.
|
|
31
|
+
*/
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Options for creating a TestDevice.
|
|
37
|
+
*/
|
|
38
|
+
interface TestDeviceOptions {
|
|
39
|
+
/** Unique device name (used for DB file naming) */
|
|
40
|
+
name: string;
|
|
41
|
+
/** Schema definition */
|
|
42
|
+
schema: SchemaDefinition;
|
|
43
|
+
/** Test server to connect to */
|
|
44
|
+
server: TestServer;
|
|
45
|
+
/** Transport factory — creates a linked client/server transport pair */
|
|
46
|
+
createTransportPair: () => {
|
|
47
|
+
client: SyncTransport;
|
|
48
|
+
serverTransport: _korajs_server.ServerTransport;
|
|
49
|
+
};
|
|
50
|
+
/** Optional directory for temp DB files */
|
|
51
|
+
tmpDir: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A virtual device in a test network.
|
|
55
|
+
* Each device has its own Store (with real SQLite), SyncEngine, and MergeEngine.
|
|
56
|
+
* Provides high-level methods for syncing, disconnecting, and inspecting state.
|
|
57
|
+
*/
|
|
58
|
+
declare class TestDevice {
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly store: Store;
|
|
61
|
+
readonly emitter: KoraEventEmitter & {
|
|
62
|
+
clear(): void;
|
|
63
|
+
};
|
|
64
|
+
private readonly schema;
|
|
65
|
+
private readonly server;
|
|
66
|
+
private readonly mergeEngine;
|
|
67
|
+
private readonly createTransportPair;
|
|
68
|
+
private readonly adapter;
|
|
69
|
+
private readonly dbPath;
|
|
70
|
+
private syncEngine;
|
|
71
|
+
private currentTransport;
|
|
72
|
+
private unsubscribeSync;
|
|
73
|
+
private closing;
|
|
74
|
+
constructor(options: TestDeviceOptions);
|
|
75
|
+
/**
|
|
76
|
+
* Open the store (must be called before sync or collection operations).
|
|
77
|
+
*/
|
|
78
|
+
open(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Connect to the test server and perform initial sync.
|
|
81
|
+
* If already connected, flushes any pending operations.
|
|
82
|
+
*/
|
|
83
|
+
sync(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Disconnect from the test server.
|
|
86
|
+
*/
|
|
87
|
+
disconnect(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Reconnect to the test server after a disconnect.
|
|
90
|
+
*/
|
|
91
|
+
reconnect(): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Get a collection accessor for performing CRUD operations.
|
|
94
|
+
*/
|
|
95
|
+
collection(name: string): CollectionAccessor;
|
|
96
|
+
/**
|
|
97
|
+
* Get all records from a collection (convenience method).
|
|
98
|
+
*/
|
|
99
|
+
getState(collectionName: string): Promise<Record<string, unknown>[]>;
|
|
100
|
+
/**
|
|
101
|
+
* Get the device's node ID.
|
|
102
|
+
*/
|
|
103
|
+
getNodeId(): string;
|
|
104
|
+
/**
|
|
105
|
+
* Get the device's version vector.
|
|
106
|
+
*/
|
|
107
|
+
getVersionVector(): VersionVector;
|
|
108
|
+
/**
|
|
109
|
+
* Check if the device is currently connected to the server.
|
|
110
|
+
*/
|
|
111
|
+
isConnected(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Close the device, releasing all resources.
|
|
114
|
+
*/
|
|
115
|
+
close(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Create a SyncStore wrapper that interposes merge resolution.
|
|
118
|
+
* Simplified version of MergeAwareSyncStore from the kora meta-package.
|
|
119
|
+
*/
|
|
120
|
+
private createMergeAwareSyncStore;
|
|
121
|
+
/**
|
|
122
|
+
* Wait for in-flight sync operations to settle.
|
|
123
|
+
* In-memory transports are near-synchronous, so a microtask flush suffices.
|
|
124
|
+
*/
|
|
125
|
+
private waitForSettled;
|
|
126
|
+
/**
|
|
127
|
+
* Wait for all pending outbound operations to be acknowledged.
|
|
128
|
+
*/
|
|
129
|
+
private waitForPendingOps;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Options for creating a test network.
|
|
134
|
+
*/
|
|
135
|
+
interface TestNetworkOptions {
|
|
136
|
+
/** Number of devices to create. Defaults to 2. */
|
|
137
|
+
devices?: number;
|
|
138
|
+
/** Custom device names. If not provided, uses 'device-0', 'device-1', etc. */
|
|
139
|
+
deviceNames?: string[];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A test network with a server and multiple devices.
|
|
143
|
+
*/
|
|
144
|
+
interface TestNetwork {
|
|
145
|
+
/** The test server */
|
|
146
|
+
server: TestServer;
|
|
147
|
+
/** All devices in the network */
|
|
148
|
+
devices: TestDevice[];
|
|
149
|
+
/** Temporary directory for DB files */
|
|
150
|
+
tmpDir: string;
|
|
151
|
+
/** Close all devices and the server, clean up temp files */
|
|
152
|
+
close(): Promise<void>;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Create a test network with a server and multiple virtual devices.
|
|
156
|
+
*
|
|
157
|
+
* Each device has its own local SQLite store and SyncEngine. Devices
|
|
158
|
+
* communicate with the server via in-memory transports.
|
|
159
|
+
*
|
|
160
|
+
* @param schema - The schema all devices share
|
|
161
|
+
* @param options - Network configuration
|
|
162
|
+
* @returns A test network with server and devices ready for use
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* const network = await createTestNetwork(schema, { devices: 2 })
|
|
167
|
+
* const [deviceA, deviceB] = network.devices
|
|
168
|
+
*
|
|
169
|
+
* await deviceA.collection('todos').insert({ title: 'Hello' })
|
|
170
|
+
* await deviceA.sync()
|
|
171
|
+
* await deviceB.sync()
|
|
172
|
+
*
|
|
173
|
+
* const todos = await deviceB.getState('todos')
|
|
174
|
+
* expect(todos).toHaveLength(1)
|
|
175
|
+
*
|
|
176
|
+
* await network.close()
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare function createTestNetwork(schema: SchemaDefinition, options?: TestNetworkOptions): Promise<TestNetwork>;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Result of a convergence check.
|
|
183
|
+
*/
|
|
184
|
+
interface ConvergenceResult {
|
|
185
|
+
/** Whether all devices have converged to the same state */
|
|
186
|
+
converged: boolean;
|
|
187
|
+
/** Per-collection comparison details (only populated on failure) */
|
|
188
|
+
differences: CollectionDifference[];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Describes a difference in a collection between devices.
|
|
192
|
+
*/
|
|
193
|
+
interface CollectionDifference {
|
|
194
|
+
collection: string;
|
|
195
|
+
deviceA: string;
|
|
196
|
+
deviceB: string;
|
|
197
|
+
/** Records present in deviceA but not deviceB */
|
|
198
|
+
missingInB: string[];
|
|
199
|
+
/** Records present in deviceB but not deviceA */
|
|
200
|
+
missingInA: string[];
|
|
201
|
+
/** Records present in both but with different values */
|
|
202
|
+
fieldDifferences: FieldDifference[];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* A specific field-level difference between two devices.
|
|
206
|
+
*/
|
|
207
|
+
interface FieldDifference {
|
|
208
|
+
recordId: string;
|
|
209
|
+
field: string;
|
|
210
|
+
valueInA: unknown;
|
|
211
|
+
valueInB: unknown;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Assert that all devices have converged to identical collection states.
|
|
215
|
+
*
|
|
216
|
+
* Compares every collection across all device pairs. Throws an error
|
|
217
|
+
* with detailed diagnostics if any differences are found.
|
|
218
|
+
*
|
|
219
|
+
* @param devices - The devices to check for convergence
|
|
220
|
+
* @param schema - The schema (used to enumerate collections)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* await deviceA.sync()
|
|
225
|
+
* await deviceB.sync()
|
|
226
|
+
* await expectConverged([deviceA, deviceB], schema)
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
declare function expectConverged(devices: TestDevice[], schema: SchemaDefinition): Promise<void>;
|
|
230
|
+
/**
|
|
231
|
+
* Check whether all devices have converged without throwing.
|
|
232
|
+
*
|
|
233
|
+
* @param devices - The devices to check
|
|
234
|
+
* @param schema - The schema (for collection enumeration)
|
|
235
|
+
* @returns Convergence result with details
|
|
236
|
+
*/
|
|
237
|
+
declare function checkConvergence(devices: TestDevice[], schema: SchemaDefinition): Promise<ConvergenceResult>;
|
|
238
|
+
|
|
239
|
+
export { type CollectionDifference, type ConvergenceResult, type FieldDifference, TestDevice, type TestDeviceOptions, type TestNetwork, type TestNetworkOptions, TestServer, checkConvergence, createTestNetwork, expectConverged };
|