@gatling.io/core 3.11.7 → 3.12.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.
Files changed (64) hide show
  1. package/jest.config.js +5 -0
  2. package/package.json +3 -3
  3. package/src/assertions.ts +305 -0
  4. package/src/body.ts +211 -0
  5. package/src/checks/builder.ts +14 -0
  6. package/src/checks/captureGroup.ts +22 -0
  7. package/src/checks/condition.ts +24 -0
  8. package/src/checks/final.ts +31 -0
  9. package/src/checks/find.ts +23 -0
  10. package/src/checks/index.ts +540 -0
  11. package/src/checks/jsonOfTypeFind.ts +81 -0
  12. package/src/checks/jsonOfTypeMultipleFind.ts +84 -0
  13. package/src/checks/multipleFind.ts +87 -0
  14. package/src/checks/validate.ts +336 -0
  15. package/src/closedInjection.ts +182 -0
  16. package/src/common.ts +3 -0
  17. package/src/feeders.ts +279 -0
  18. package/src/filters.ts +49 -0
  19. package/src/gatlingJvm/app.ts +5 -0
  20. package/src/gatlingJvm/byteArrays.ts +14 -0
  21. package/src/gatlingJvm/collections.ts +28 -0
  22. package/src/globalStore.ts +104 -0
  23. package/src/index.test.ts +543 -0
  24. package/src/index.ts +158 -0
  25. package/src/openInjection.ts +286 -0
  26. package/src/parameters.ts +38 -0
  27. package/src/population.ts +105 -0
  28. package/src/protocol.ts +5 -0
  29. package/src/scenario.ts +37 -0
  30. package/src/session.ts +182 -0
  31. package/src/structure/asLongAs.ts +121 -0
  32. package/src/structure/asLongAsDuring.ts +337 -0
  33. package/src/structure/choices.ts +41 -0
  34. package/src/structure/doIf.ts +140 -0
  35. package/src/structure/doIfOrElse.ts +160 -0
  36. package/src/structure/doSwitch.ts +46 -0
  37. package/src/structure/doSwitchOrElse.ts +61 -0
  38. package/src/structure/doWhile.ts +53 -0
  39. package/src/structure/doWhileDuring.ts +337 -0
  40. package/src/structure/during.ts +182 -0
  41. package/src/structure/errors.ts +266 -0
  42. package/src/structure/execs.ts +66 -0
  43. package/src/structure/feeds.ts +62 -0
  44. package/src/structure/forEach.ts +68 -0
  45. package/src/structure/forever.ts +25 -0
  46. package/src/structure/groups.ts +23 -0
  47. package/src/structure/index.ts +130 -0
  48. package/src/structure/jvmStructureBuilder.ts +52 -0
  49. package/src/structure/on.ts +20 -0
  50. package/src/structure/paces.ts +156 -0
  51. package/src/structure/pauses.ts +211 -0
  52. package/src/structure/randomSwitch.ts +34 -0
  53. package/src/structure/randomSwitchOrElse.ts +45 -0
  54. package/src/structure/rendezVous.ts +23 -0
  55. package/src/structure/repeat.ts +64 -0
  56. package/src/structure/roundRobinSwitch.ts +34 -0
  57. package/src/structure/uniformRandomSwitch.ts +34 -0
  58. package/src/throttling.ts +67 -0
  59. package/src/utils/duration.ts +28 -0
  60. package/target/structure/errors.d.ts +70 -10
  61. package/target/structure/errors.js +29 -8
  62. package/target/structure/index.d.ts +4 -2
  63. package/target/structure/index.js +5 -3
  64. package/tsconfig.json +18 -0
package/src/feeders.ts ADDED
@@ -0,0 +1,279 @@
1
+ import { CoreDsl as JvmCoreDsl } from "@gatling.io/jvm-types";
2
+ import JvmFeederBuilder = io.gatling.javaapi.core.FeederBuilder;
3
+ import JvmFeederBuilderFileBased = io.gatling.javaapi.core.FeederBuilder$FileBased;
4
+ import JvmFeederBuilderBatchable = io.gatling.javaapi.core.FeederBuilder$Batchable;
5
+
6
+ import { Wrapper } from "./common";
7
+
8
+ export interface FeederBuilder<T> extends Wrapper<JvmFeederBuilder<T>> {
9
+ /**
10
+ * Set a queue strategy. Records will be provided in the same order as defined in the underlying
11
+ * source. A given record will only be provided once. The run will be immediately stopped if the
12
+ * feeder runs out of records.
13
+ *
14
+ * @returns a new FeederBuilder
15
+ */
16
+ queue(): FeederBuilder<T>;
17
+
18
+ /**
19
+ * Set a random strategy. Records will be provided in a random order, unrelated to the order in
20
+ * the underlying source. A given record can be provided multiple times. Such feeder will never
21
+ * run out of records.
22
+ *
23
+ * @returns a new FeederBuilder
24
+ */
25
+ random(): FeederBuilder<T>;
26
+
27
+ /**
28
+ * Set a shuffle strategy. Records will be provided in a random order, unrelated to the order in
29
+ * the underlying source. A given record will only be provided once. The run will be immediately
30
+ * stopped if the feeder runs out of records.
31
+ *
32
+ * @returns a new FeederBuilder
33
+ */
34
+ shuffle(): FeederBuilder<T>;
35
+
36
+ /**
37
+ * Set a circular strategy. Records will be provided in the same order as defined in the
38
+ * underlying source. Once the last record of the underlying source is reached, the feeder will go
39
+ * back to the first record. A given record can be provided multiple times. Such feeder will never
40
+ * run out of records.
41
+ *
42
+ * @returns a new FeederBuilder
43
+ */
44
+ circular(): FeederBuilder<T>;
45
+
46
+ /**
47
+ * Provide a function to transform records as defined in the underlying source
48
+ *
49
+ * @param f - the transformation function
50
+ * @returns a new FeederBuilder
51
+ */
52
+ transform(f: (name: string, value: T) => unknown): FeederBuilder<unknown>;
53
+
54
+ // TODO
55
+ // /**
56
+ // * Read all the records of the underlying source.
57
+ // *
58
+ // * @return the whole data
59
+ // */
60
+ // @NonNull
61
+ // List<Map<String, Object>> readRecords();
62
+
63
+ /**
64
+ * Return the number of records more efficiantly than readRecords().size().
65
+ *
66
+ * @returns the number of recordss
67
+ */
68
+ recordsCount(): number;
69
+
70
+ /**
71
+ * Distribute data evenly amongst all the injectors of a Gatling Enterprise cluster. Only
72
+ * effective when the test is running with Gatling Enterprise, noop otherwise.
73
+ *
74
+ * @returns a new FeederBuilder
75
+ */
76
+ shard(): FeederBuilder<T>;
77
+ }
78
+
79
+ const wrapFeederBuilder = <T>(_underlying: JvmFeederBuilder<T>): FeederBuilder<T> => ({
80
+ _underlying,
81
+ queue: () => wrapFeederBuilder(_underlying.queue()),
82
+ random: () => wrapFeederBuilder(_underlying.random()),
83
+ shuffle: () => wrapFeederBuilder(_underlying.shuffle()),
84
+ circular: () => wrapFeederBuilder(_underlying.circular()),
85
+ transform: (f: (name: string, value: T) => unknown) => wrapFeederBuilder(_underlying.transform(f)),
86
+ recordsCount: () => _underlying.recordsCount(),
87
+ shard: () => wrapFeederBuilder(_underlying.shard())
88
+ });
89
+
90
+ export interface FileBasedFeederBuilder<T> extends FeederBuilder<T> {
91
+ /**
92
+ * Advice to unzip the underlying source because it's a zip or tar file
93
+ *
94
+ * @returns a new FileBased
95
+ */
96
+ unzip(): FileBasedFeederBuilder<T>;
97
+ }
98
+
99
+ export const wrapFileBasedFeederBuilder = <T>(
100
+ _underlying: JvmFeederBuilderFileBased<T>
101
+ ): FileBasedFeederBuilder<T> => ({
102
+ _underlying,
103
+ queue: () => wrapFileBasedFeederBuilder(_underlying.queue()),
104
+ random: () => wrapFileBasedFeederBuilder(_underlying.random()),
105
+ shuffle: () => wrapFileBasedFeederBuilder(_underlying.shuffle()),
106
+ circular: () => wrapFileBasedFeederBuilder(_underlying.circular()),
107
+ transform: (f: (name: string, value: T) => unknown) => wrapFeederBuilder(_underlying.transform(f)),
108
+ recordsCount: () => _underlying.recordsCount(),
109
+ shard: () => wrapFileBasedFeederBuilder(_underlying.shard()),
110
+ unzip: () => wrapFileBasedFeederBuilder(_underlying.unzip())
111
+ });
112
+
113
+ export interface BatchableFeederBuilder<T> extends FileBasedFeederBuilder<T> {
114
+ /**
115
+ * Force loading the whole data in memory from the underlying source at once. Faster runtime but
116
+ * slower boot time and higher heap usage.
117
+ *
118
+ * @returns a new Batchable
119
+ */
120
+ eager(): BatchableFeederBuilder<T>;
121
+
122
+ /**
123
+ * Force loading small chunks of data from the underlying source one by one. Slower runtime but
124
+ * faster boot time and lower memory consumption.
125
+ *
126
+ * @returns a new Batchable
127
+ */
128
+ batch(): BatchableFeederBuilder<T>;
129
+
130
+ /**
131
+ * Force loading small chunks of data from the underlying source one by one Slower runtime but
132
+ * faster boot time and lower memory consumption.
133
+ *
134
+ * @param lines - the number of buffered lines
135
+ * @returns a new Batchable
136
+ */
137
+ batch(lines: number): BatchableFeederBuilder<T>;
138
+ }
139
+
140
+ const wrapBatchableFeederBuilder = <T>(_underlying: JvmFeederBuilderBatchable<T>): BatchableFeederBuilder<T> => ({
141
+ _underlying,
142
+ queue: () => wrapBatchableFeederBuilder(_underlying.queue()),
143
+ random: () => wrapBatchableFeederBuilder(_underlying.random()),
144
+ shuffle: () => wrapBatchableFeederBuilder(_underlying.shuffle()),
145
+ circular: () => wrapBatchableFeederBuilder(_underlying.circular()),
146
+ transform: (f: (name: string, value: T) => unknown) => wrapFeederBuilder(_underlying.transform(f)),
147
+ recordsCount: () => _underlying.recordsCount(),
148
+ shard: () => wrapBatchableFeederBuilder(_underlying.shard()),
149
+ unzip: () => wrapBatchableFeederBuilder(_underlying.unzip()),
150
+ eager: () => wrapBatchableFeederBuilder(_underlying.eager()),
151
+ batch: (lines?: number) =>
152
+ wrapBatchableFeederBuilder(lines !== undefined ? _underlying.batch(lines) : _underlying.batch())
153
+ });
154
+
155
+ export interface CsvFunction {
156
+ /**
157
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder
158
+ *
159
+ * @param filePath - the path of the file, relative to the root of the resources folder
160
+ * @returns a new feeder
161
+ */
162
+ (filePath: string): BatchableFeederBuilder<string>;
163
+
164
+ /**
165
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder
166
+ *
167
+ * @param filePath - the path of the file, relative to the root of the resources folder
168
+ * @param quoteChar - the quote char to wrap values containing special characters
169
+ * @returns a new feeder
170
+ */
171
+ (filePath: string, quoteChar: string): BatchableFeederBuilder<string>;
172
+ }
173
+
174
+ export const csv: CsvFunction = (filePath: string, quoteChar?: string): BatchableFeederBuilder<string> =>
175
+ wrapBatchableFeederBuilder(quoteChar !== undefined ? JvmCoreDsl.csv(filePath, quoteChar) : JvmCoreDsl.csv(filePath));
176
+
177
+ export interface SsvFunction {
178
+ /**
179
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
180
+ * is a semi-colon
181
+ *
182
+ * @param filePath - the path of the file, relative to the root of the resources folder
183
+ * @returns a new feeder
184
+ */
185
+ (filePath: string): BatchableFeederBuilder<string>;
186
+
187
+ /**
188
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
189
+ * is a semi-colon
190
+ *
191
+ * @param filePath - the path of the file, relative to the root of the resources folder
192
+ * @param quoteChar - the quote char to wrap values containing special characters (must be a single character)
193
+ * @returns a new feeder
194
+ */
195
+ (filePath: string, quoteChar: string): BatchableFeederBuilder<string>;
196
+ }
197
+
198
+ export const ssv: SsvFunction = (filePath: string, quoteChar?: string) =>
199
+ wrapBatchableFeederBuilder(quoteChar !== undefined ? JvmCoreDsl.ssv(filePath, quoteChar) : JvmCoreDsl.ssv(filePath));
200
+
201
+ export interface TsvFunction {
202
+ /**
203
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
204
+ * is a tab
205
+ *
206
+ * @param filePath - the path of the file, relative to the root of the resources folder
207
+ * @returns a new feeder
208
+ */
209
+ (filePath: string): BatchableFeederBuilder<string>;
210
+
211
+ /**
212
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
213
+ * is a tab
214
+ *
215
+ * @param filePath - the path of the file, relative to the root of the resources folder
216
+ * @param quoteChar - the quote char to wrap values containing special characters (must be a single character)
217
+ * @returns a new feeder
218
+ */
219
+ (filePath: string, quoteChar: string): BatchableFeederBuilder<string>;
220
+ }
221
+
222
+ export const tsv: TsvFunction = (filePath: string, quoteChar?: string) =>
223
+ wrapBatchableFeederBuilder(quoteChar !== undefined ? JvmCoreDsl.tsv(filePath, quoteChar) : JvmCoreDsl.tsv(filePath));
224
+
225
+ export interface SeparatedValuesFunction {
226
+ /**
227
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
228
+ * is a tab
229
+ *
230
+ * @param filePath - the path of the file, relative to the root of the resources folder
231
+ * @param separator - the provided separator char (must be a single character)
232
+ * @returns a new feeder
233
+ */
234
+ (filePath: string, separator: string): BatchableFeederBuilder<string>;
235
+
236
+ /**
237
+ * Bootstrap a new {@link https://datatracker.ietf.org/doc/html/rfc4180 | CSV file} based feeder, where the separator
238
+ * is a tab
239
+ *
240
+ * @param filePath - the path of the file, relative to the root of the resources folder
241
+ * @param separator - the provided separator char (must be a single character)
242
+ * @param quoteChar - the quote char to wrap values containing special characters (must be a single character)
243
+ * @returns a new feeder
244
+ */
245
+ (filePath: string, separator: string, quoteChar: string): BatchableFeederBuilder<string>;
246
+ }
247
+
248
+ export const separatedValues: SeparatedValuesFunction = (filePath: string, separator: string, quoteChar?: string) =>
249
+ wrapBatchableFeederBuilder(
250
+ quoteChar !== undefined
251
+ ? JvmCoreDsl.separatedValues(filePath, separator, quoteChar)
252
+ : JvmCoreDsl.separatedValues(filePath, separator)
253
+ );
254
+
255
+ /**
256
+ * Bootstrap a new JSON file based feeder
257
+ *
258
+ * @param filePath - the path of the file, relative to the root of the resources folder
259
+ * @returns a new feeder
260
+ */
261
+ export const jsonFile = (filePath: string): FileBasedFeederBuilder<any> =>
262
+ wrapFileBasedFeederBuilder(JvmCoreDsl.jsonFile(filePath));
263
+
264
+ /**
265
+ * Bootstrap a new JSON API based feeder
266
+ *
267
+ * @param url - the url of the API
268
+ * @returns a new feeder
269
+ */
270
+ export const jsonUrl = (url: string): FeederBuilder<any> => wrapFeederBuilder(JvmCoreDsl.jsonUrl(url));
271
+
272
+ /**
273
+ * Bootstrap a new in-memory array of Maps based feeder
274
+ *
275
+ * @param data - the in-memory data
276
+ * @returns a new feeder
277
+ */
278
+ export const arrayFeeder = (data: Array<Record<string, unknown>>): FeederBuilder<unknown> =>
279
+ wrapFeederBuilder(JvmCoreDsl.arrayFeeder(data));
package/src/filters.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { CoreDsl as JvmCoreDsl } from "@gatling.io/jvm-types";
2
+ import JvmFilter = io.gatling.javaapi.core.Filter;
3
+ import JvmFilterAllowList = io.gatling.javaapi.core.Filter$AllowList;
4
+ import JvmFilterDenyList = io.gatling.javaapi.core.Filter$DenyList;
5
+
6
+ import { Wrapper } from "./common";
7
+
8
+ export interface Filter<T extends JvmFilter<unknown>> extends Wrapper<T> {
9
+ type: "allow" | "deny";
10
+ }
11
+
12
+ export interface AllowListFilter extends Filter<JvmFilterAllowList> {
13
+ type: "allow";
14
+ }
15
+
16
+ export interface DenyListFilter extends Filter<JvmFilterDenyList> {
17
+ type: "deny";
18
+ }
19
+
20
+ const wrapAllowListFilter = (_underlying: JvmFilterAllowList): AllowListFilter => ({
21
+ _underlying,
22
+ type: "allow"
23
+ });
24
+
25
+ const wrapDenyListFilter = (_underlying: JvmFilterDenyList): DenyListFilter => ({
26
+ _underlying,
27
+ type: "deny"
28
+ });
29
+
30
+ /**
31
+ * Create a new AllowList based on some <a
32
+ * href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html">Java regular
33
+ * expression patterns</a>. Typically used to filter HTTP resources.
34
+ *
35
+ * @param patterns some Java regex patterns
36
+ * @return a new AllowList
37
+ */
38
+ export const AllowList = (...patterns: string[]): AllowListFilter =>
39
+ wrapAllowListFilter(JvmCoreDsl.AllowList(patterns));
40
+
41
+ /**
42
+ * Create a new DenyList based on some <a
43
+ * href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html">Java regular
44
+ * expression patterns</a> Typically used to filter HTTP resources.
45
+ *
46
+ * @param patterns some Java regex patterns
47
+ * @return a new DenyList
48
+ */
49
+ export const DenyList = (...patterns: string[]): DenyListFilter => wrapDenyListFilter(JvmCoreDsl.DenyList(patterns));
@@ -0,0 +1,5 @@
1
+ import JvmPopulationBuilder = io.gatling.javaapi.core.PopulationBuilder;
2
+ import JvmSetUp = io.gatling.javaapi.core.Simulation$SetUp;
3
+
4
+ export type SetUpFunction = (populationBuilders: JvmPopulationBuilder[]) => JvmSetUp;
5
+ export type Simulation = (setUp: SetUpFunction) => void;
@@ -0,0 +1,14 @@
1
+ import JvmSession = io.gatling.javaapi.core.Session;
2
+
3
+ type JvmExpression<T> = (arg: JvmSession) => T;
4
+
5
+ interface ByteArrays {
6
+ asByteArray(v: number[]): number[];
7
+ asByteArrayFunction(f: JvmExpression<number[]>): JvmExpression<number[]>;
8
+ }
9
+
10
+ const ByteArrays = Java.type<ByteArrays>("io.gatling.js.callbacks.ByteArrays");
11
+
12
+ export const asByteArray = (v: number[]) => ByteArrays.asByteArray(v);
13
+
14
+ export const asByteArrayFunction = (f: JvmExpression<number[]>) => ByteArrays.asByteArrayFunction(f);
@@ -0,0 +1,28 @@
1
+ const ArrayList = Java.type<any>("java.util.ArrayList");
2
+ const HashMap = Java.type<any>("java.util.HashMap");
3
+
4
+ const asJavaList = (elements: unknown[]): unknown => {
5
+ const javaList = new ArrayList();
6
+ for (let i = 0; i < elements.length; i++) {
7
+ javaList.add(asJava(elements[i]));
8
+ }
9
+ return javaList;
10
+ };
11
+
12
+ const asJavaMap = (records: object): unknown => {
13
+ const javaMap = new HashMap();
14
+ Object.entries(records).forEach(([key, value]) => {
15
+ javaMap.put(key, asJava(value));
16
+ });
17
+ return javaMap;
18
+ };
19
+
20
+ export const asJava = (value: unknown): unknown => {
21
+ if (Array.isArray(value)) {
22
+ return asJavaList(value);
23
+ } else if (typeof value === "object" && value !== null) {
24
+ return asJavaMap(value);
25
+ } else {
26
+ return value;
27
+ }
28
+ };
@@ -0,0 +1,104 @@
1
+ const ConcurrentHashMap = Java.type<ConcurrentHashMapStatic>("java.util.concurrent.ConcurrentHashMap");
2
+
3
+ interface ConcurrentHashMapStatic {
4
+ new <K, V>(): ConcurrentHashMap<K, V>;
5
+ }
6
+
7
+ interface ConcurrentHashMap<K, V> {
8
+ put(key: K, value: V): V | null;
9
+ remove(key: K): V | null;
10
+ get(key: K): V | null;
11
+ getOrDefault(key: K, defaultValue: V): V;
12
+ containsKey(key: K): boolean;
13
+ compute(key: K, remappingFunction: (k: K, v: V | null) => V | null): V | null;
14
+ clear(): void;
15
+ }
16
+
17
+ const javaStore = new ConcurrentHashMap<string, any>();
18
+
19
+ export interface GlobalStore {
20
+ /**
21
+ * Maps the specified key to the specified value in the global store. Neither the key nor the value can be null or
22
+ * undefined.
23
+ *
24
+ * @param key - key with which the specified value is to be associated
25
+ * @param value - value to be associated with the specified key
26
+ * @returns the previous value associated with key, or `null` if there was no mapping for key
27
+ */
28
+ put<T>(key: string, value: T): T | undefined;
29
+
30
+ /**
31
+ * Attempts to compute a new value for the specified key and its currently mapped value (or `null` if there is no
32
+ * current value). The entire method invocation is performed atomically. The supplied function is invoked exactly once
33
+ * per invocation of this method. Some attempted update operations on this map by other threads may be blocked while
34
+ * computation is in progress, so the computation should be short and simple.
35
+ *
36
+ * The updateFunction function must not modify the global store during computation.
37
+ *
38
+ * @param key - key with which the specified value is to be associated
39
+ * @param updateFunction - the function to compute a new value to update the mapping; if it returns `null`, the
40
+ * mapping will be removed
41
+ * @returns the new value associated with the specified key, or `null` if none
42
+ */
43
+ update<T>(key: string, updateFunction: (oldValue: T | undefined) => T | undefined): T | undefined;
44
+
45
+ /**
46
+ * Returns the value to which the specified key is mapped, or `null` if the global store contains no mapping for the
47
+ * key.
48
+ *
49
+ * @param key - the key whose associated value is to be returned
50
+ * @returns the mapping for the key, if present; else `null`
51
+ */
52
+ get<T>(key: string): T | undefined;
53
+
54
+ /**
55
+ * Returns the value to which the specified key is mapped, or the given default value if the global store contains no
56
+ * mapping for the key.
57
+ *
58
+ * @param key - the key whose associated value is to be returned
59
+ * @param defaultValue - the value to return if the global store contains no mapping for the given key
60
+ * @returns the mapping for the key, if present; else the default value
61
+ */
62
+ getOrDefault<T>(key: string, defaultValue: T): T;
63
+
64
+ /**
65
+ * Tests if the key is present in the global store.
66
+ *
67
+ * @param key - possible key
68
+ * @returns `true` if and only if the key is present in the global store; `false` otherwise
69
+ */
70
+ containsKey(key: string): boolean;
71
+
72
+ /**
73
+ * Removes the mapping for a key from the global store if it is present.
74
+ *
75
+ * @param key - key whose mapping is to be removed from the map
76
+ * @returns the previous value associated with `key`, or `null` if there was no mapping for `key`.
77
+ */
78
+ remove<T>(key: string): T;
79
+
80
+ /**
81
+ * Removes all of the mappings from the global store.
82
+ */
83
+ clear(): void;
84
+ }
85
+
86
+ /**
87
+ * A global store which can be used to share data between different virtual users.
88
+ */
89
+ export const GlobalStore: GlobalStore = {
90
+ put: (key, value) => nullToUndefined(javaStore.put(key, value)),
91
+ update: (key, updateFunction) =>
92
+ nullToUndefined(
93
+ javaStore.compute(key, (_, oldValue) => undefinedToNull(updateFunction(nullToUndefined(oldValue))))
94
+ ),
95
+ get: (key) => nullToUndefined(javaStore.get(key)),
96
+ getOrDefault: (key, defaultValue) => javaStore.getOrDefault(key, defaultValue),
97
+ containsKey: (key) => javaStore.containsKey(key),
98
+ remove: (key) => nullToUndefined(javaStore.remove(key)),
99
+ clear: () => javaStore.clear()
100
+ };
101
+
102
+ const nullToUndefined = <T>(x: T | null): T | undefined => (x === null ? undefined : x);
103
+
104
+ const undefinedToNull = <T>(x: T | undefined): T | null => (x === undefined ? null : x);