@loadstrike/loadstrike-sdk 1.0.30201 → 1.0.30401
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/README.md +24 -0
- package/dist/cjs/cluster.js +2417 -7
- package/dist/cjs/index.js +13 -2
- package/dist/cjs/iteration-observations.js +711 -0
- package/dist/cjs/load-engine-v2.js +966 -0
- package/dist/cjs/local.js +73 -20
- package/dist/cjs/reporting.js +122 -12
- package/dist/cjs/runtime.js +2368 -129
- package/dist/cjs/sinks.js +471 -17
- package/dist/cjs/transports.js +84 -146
- package/dist/esm/cluster.js +2386 -7
- package/dist/esm/index.js +1 -0
- package/dist/esm/iteration-observations.js +698 -0
- package/dist/esm/load-engine-v2.js +942 -0
- package/dist/esm/local.js +73 -20
- package/dist/esm/reporting.js +122 -12
- package/dist/esm/runtime.js +2369 -130
- package/dist/esm/sinks.js +471 -17
- package/dist/esm/transports.js +84 -146
- package/dist/types/cluster.d.ts +379 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/types/iteration-observations.d.ts +225 -0
- package/dist/types/load-engine-v2.d.ts +147 -0
- package/dist/types/runtime.d.ts +214 -8
- package/dist/types/sinks.d.ts +67 -0
- package/dist/types/transports.d.ts +2 -8
- package/package.json +3 -4
package/dist/cjs/transports.js
CHANGED
|
@@ -638,9 +638,13 @@ class WebSocketEndpointDefinitionModel extends TrafficEndpointDefinitionModel {
|
|
|
638
638
|
parsed = new URL(url);
|
|
639
639
|
}
|
|
640
640
|
catch {
|
|
641
|
+
// Diagnostic text only; no connection is opened here.
|
|
642
|
+
// nosemgrep: vulnerability-tools.semgrep-rules.javascript.lang.security.detect-insecure-websocket
|
|
641
643
|
throw new Error("Url must be an absolute ws:// or wss:// URI.");
|
|
642
644
|
}
|
|
643
645
|
if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
646
|
+
// Diagnostic text only; no connection is opened here.
|
|
647
|
+
// nosemgrep: vulnerability-tools.semgrep-rules.javascript.lang.security.detect-insecure-websocket
|
|
644
648
|
throw new Error("Url must be an absolute ws:// or wss:// URI.");
|
|
645
649
|
}
|
|
646
650
|
if (this.ConnectTimeoutSeconds <= 0) {
|
|
@@ -1275,11 +1279,13 @@ function validateHttpAuthOptionsModel(target) {
|
|
|
1275
1279
|
}
|
|
1276
1280
|
function validateKafkaSaslOptionsModel(target) {
|
|
1277
1281
|
switch (normalizeToken(target.Mechanism)) {
|
|
1278
|
-
case "oauthbearer":
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
+
case "oauthbearer": {
|
|
1283
|
+
const additionalSettings = target.AdditionalSettings;
|
|
1284
|
+
validateKafkaOAuthBearerCredentials(String(target.AccessToken ?? "").trim() || String(target.OAuthBearerToken ?? "").trim(), String(target.OAuthBearerTokenEndpointUrl ?? "").trim()
|
|
1285
|
+
|| String(target.TokenEndpoint ?? "").trim()
|
|
1286
|
+
|| optionString(additionalSettings, "TokenEndpoint", "tokenEndpoint"), optionString(additionalSettings, "ClientId", "clientId"), optionString(additionalSettings, "ClientSecret", "clientSecret"));
|
|
1282
1287
|
return;
|
|
1288
|
+
}
|
|
1283
1289
|
default:
|
|
1284
1290
|
if (!String(target.Username ?? "").trim()) {
|
|
1285
1291
|
throw new Error("Username must be provided for SASL authentication.");
|
|
@@ -1828,21 +1834,12 @@ class KafkaEndpointAdapter extends CallbackAdapter {
|
|
|
1828
1834
|
if (!this.consumerStartPromise) {
|
|
1829
1835
|
this.consumerStartPromise = (async () => {
|
|
1830
1836
|
const options = this.endpoint.kafka ?? {};
|
|
1831
|
-
const useConfluentClient = shouldUseConfluentKafkaClient(this.endpoint);
|
|
1832
1837
|
const kafka = await createKafkaClient(this.endpoint);
|
|
1833
1838
|
const consumer = kafka.consumer(buildKafkaConsumerOptions(this.endpoint));
|
|
1834
1839
|
await consumer.connect();
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
});
|
|
1839
|
-
}
|
|
1840
|
-
else {
|
|
1841
|
-
await consumer.subscribe({
|
|
1842
|
-
topic: optionString(options, "Topic", "topic"),
|
|
1843
|
-
fromBeginning: optionBoolean(options, true, "StartFromEarliest", "startFromEarliest")
|
|
1844
|
-
});
|
|
1845
|
-
}
|
|
1840
|
+
await consumer.subscribe({
|
|
1841
|
+
topics: [optionString(options, "Topic", "topic")]
|
|
1842
|
+
});
|
|
1846
1843
|
await consumer.run({
|
|
1847
1844
|
eachMessage: async ({ message }) => {
|
|
1848
1845
|
this.queue.push(createBrokerPayload(fromKafkaHeaders(message.headers), bufferToUint8Array(message.value), this.endpoint, headerValue(message.headers, "content-type")));
|
|
@@ -3178,9 +3175,13 @@ function validateWebSocketEndpoint(endpoint, mode) {
|
|
|
3178
3175
|
parsed = new URL(url);
|
|
3179
3176
|
}
|
|
3180
3177
|
catch {
|
|
3178
|
+
// Diagnostic text only; no connection is opened here.
|
|
3179
|
+
// nosemgrep: vulnerability-tools.semgrep-rules.javascript.lang.security.detect-insecure-websocket
|
|
3181
3180
|
throw new Error("Url must be an absolute ws:// or wss:// URI.");
|
|
3182
3181
|
}
|
|
3183
3182
|
if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
3183
|
+
// Diagnostic text only; no connection is opened here.
|
|
3184
|
+
// nosemgrep: vulnerability-tools.semgrep-rules.javascript.lang.security.detect-insecure-websocket
|
|
3184
3185
|
throw new Error("Url must be an absolute ws:// or wss:// URI.");
|
|
3185
3186
|
}
|
|
3186
3187
|
const connectMs = optionNumber(options, "ConnectTimeoutMs", "connectTimeoutMs");
|
|
@@ -3256,7 +3257,8 @@ function validateKafkaEndpoint(endpoint, mode, hasModeDelegate) {
|
|
|
3256
3257
|
function validateKafkaSaslOptions(options) {
|
|
3257
3258
|
const mechanism = optionString(options, "Mechanism", "mechanism") || "Plain";
|
|
3258
3259
|
if (mechanism.toLowerCase() === "oauthbearer") {
|
|
3259
|
-
|
|
3260
|
+
const additionalSettings = asRecordOrEmpty(pickProtocolValue(options, "AdditionalSettings", "additionalSettings"));
|
|
3261
|
+
validateKafkaOAuthBearerCredentials(optionString(options, "AccessToken", "accessToken", "OAuthBearerToken", "oauthBearerToken"), optionString(options, "OAuthBearerTokenEndpointUrl", "oauthBearerTokenEndpointUrl", "TokenEndpoint", "tokenEndpoint") || optionString(additionalSettings, "TokenEndpoint", "tokenEndpoint"), optionString(additionalSettings, "ClientId", "clientId"), optionString(additionalSettings, "ClientSecret", "clientSecret"));
|
|
3260
3262
|
return;
|
|
3261
3263
|
}
|
|
3262
3264
|
requireNonEmptyString(optionString(options, "Username", "username"), "Username must be provided for SASL authentication.");
|
|
@@ -4249,74 +4251,31 @@ function pickProtocolValue(options, ...keys) {
|
|
|
4249
4251
|
}
|
|
4250
4252
|
return undefined;
|
|
4251
4253
|
}
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
.split(",")
|
|
4257
|
-
.map((value) => value.trim())
|
|
4258
|
-
.filter((value) => value.length > 0);
|
|
4259
|
-
const clientOptions = {
|
|
4260
|
-
clientId: `${endpoint.name}-${(0, node_crypto_1.randomUUID)().slice(0, 8)}`,
|
|
4261
|
-
brokers: bootstrapServers,
|
|
4262
|
-
ssl: securityProtocol === "ssl" || securityProtocol === "saslssl"
|
|
4263
|
-
};
|
|
4264
|
-
if (securityProtocol === "saslplaintext" || securityProtocol === "saslssl") {
|
|
4265
|
-
const saslOptions = asRecordOrEmpty(pickProtocolValue(options, "Sasl", "sasl"));
|
|
4266
|
-
const mechanism = (optionString(saslOptions, "Mechanism", "mechanism") || "Plain").toLowerCase();
|
|
4267
|
-
if (mechanism === "oauthbearer") {
|
|
4268
|
-
clientOptions.sasl = {
|
|
4269
|
-
mechanism: "oauthbearer",
|
|
4270
|
-
oauthBearerProvider: async () => ({
|
|
4271
|
-
value: await resolveKafkaOAuthBearerToken(saslOptions)
|
|
4272
|
-
})
|
|
4273
|
-
};
|
|
4274
|
-
}
|
|
4275
|
-
else {
|
|
4276
|
-
clientOptions.sasl = {
|
|
4277
|
-
mechanism: mapKafkaSaslMechanism(mechanism),
|
|
4278
|
-
username: optionString(saslOptions, "Username", "username"),
|
|
4279
|
-
password: optionString(saslOptions, "Password", "password")
|
|
4280
|
-
};
|
|
4281
|
-
}
|
|
4254
|
+
let kafkaClientFactoryForTests = null;
|
|
4255
|
+
async function createKafkaClient(endpoint) {
|
|
4256
|
+
if (kafkaClientFactoryForTests) {
|
|
4257
|
+
return await kafkaClientFactoryForTests(endpoint);
|
|
4282
4258
|
}
|
|
4283
|
-
|
|
4259
|
+
const { KafkaJS } = await Promise.resolve().then(() => __importStar(require("@confluentinc/kafka-javascript")));
|
|
4260
|
+
return new KafkaJS.Kafka(buildConfluentKafkaClientOptions(endpoint));
|
|
4284
4261
|
}
|
|
4285
|
-
|
|
4286
|
-
if (
|
|
4287
|
-
|
|
4288
|
-
|
|
4262
|
+
function validateKafkaOAuthBearerCredentials(directToken, tokenEndpoint, clientId, clientSecret) {
|
|
4263
|
+
if (directToken.trim()) {
|
|
4264
|
+
return;
|
|
4265
|
+
}
|
|
4266
|
+
if (!tokenEndpoint.trim() || !clientId.trim() || !clientSecret.trim()) {
|
|
4267
|
+
throw new Error("Kafka OAuthBearer requires a direct access token or token endpoint with client credentials.");
|
|
4289
4268
|
}
|
|
4290
|
-
const { Kafka } = await Promise.resolve().then(() => __importStar(require("kafkajs")));
|
|
4291
|
-
return new Kafka(buildKafkaClientOptions(endpoint));
|
|
4292
4269
|
}
|
|
4293
4270
|
function buildKafkaConsumerOptions(endpoint) {
|
|
4294
4271
|
const options = endpoint.kafka ?? {};
|
|
4295
4272
|
const groupId = optionString(options, "ConsumerGroupId", "consumerGroupId");
|
|
4296
4273
|
const fromBeginning = optionBoolean(options, true, "StartFromEarliest", "startFromEarliest");
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
};
|
|
4303
|
-
}
|
|
4304
|
-
return { groupId };
|
|
4305
|
-
}
|
|
4306
|
-
function shouldUseConfluentKafkaClient(endpoint) {
|
|
4307
|
-
const options = endpoint.kafka ?? {};
|
|
4308
|
-
const securityProtocol = (optionString(options, "SecurityProtocol", "securityProtocol") || "Plaintext").toLowerCase();
|
|
4309
|
-
if (securityProtocol !== "saslplaintext" && securityProtocol !== "saslssl") {
|
|
4310
|
-
return Object.keys(toStringRecord(pickProtocolValue(options, "ConfluentSettings", "confluentSettings"))).length > 0;
|
|
4311
|
-
}
|
|
4312
|
-
const saslOptions = asRecordOrEmpty(pickProtocolValue(options, "Sasl", "sasl"));
|
|
4313
|
-
const mechanism = (optionString(saslOptions, "Mechanism", "mechanism") || "Plain").toLowerCase();
|
|
4314
|
-
const confluentSettings = toStringRecord(pickProtocolValue(options, "ConfluentSettings", "confluentSettings"));
|
|
4315
|
-
const additionalSettings = toStringRecord(pickProtocolValue(saslOptions, "AdditionalSettings", "additionalSettings"));
|
|
4316
|
-
const hasDirectOAuthToken = mechanism === "oauthbearer" && Boolean(optionString(saslOptions, "AccessToken", "accessToken", "OAuthBearerToken", "oauthBearerToken"));
|
|
4317
|
-
return mechanism === "gssapi"
|
|
4318
|
-
|| Object.keys(confluentSettings).length > 0
|
|
4319
|
-
|| (Object.keys(additionalSettings).length > 0 && !hasDirectOAuthToken);
|
|
4274
|
+
return {
|
|
4275
|
+
"group.id": groupId,
|
|
4276
|
+
"auto.offset.reset": fromBeginning ? "earliest" : "latest",
|
|
4277
|
+
"enable.auto.commit": true
|
|
4278
|
+
};
|
|
4320
4279
|
}
|
|
4321
4280
|
function buildConfluentKafkaClientOptions(endpoint) {
|
|
4322
4281
|
const options = endpoint.kafka ?? {};
|
|
@@ -4332,30 +4291,41 @@ function buildConfluentKafkaClientOptions(endpoint) {
|
|
|
4332
4291
|
const additionalSettings = toStringRecord(pickProtocolValue(saslOptions, "AdditionalSettings", "additionalSettings"));
|
|
4333
4292
|
base["sasl.mechanism"] = mapConfluentKafkaSaslMechanism(mechanism);
|
|
4334
4293
|
if (mechanism.toLowerCase() === "oauthbearer") {
|
|
4294
|
+
const directToken = optionString(saslOptions, "AccessToken", "accessToken", "OAuthBearerToken", "oauthBearerToken");
|
|
4335
4295
|
const tokenEndpoint = optionString(saslOptions, "OAuthBearerTokenEndpointUrl", "oauthBearerTokenEndpointUrl", "TokenEndpoint", "tokenEndpoint") || optionString(additionalSettings, "TokenEndpoint", "tokenEndpoint");
|
|
4336
|
-
if (tokenEndpoint) {
|
|
4337
|
-
base["sasl.oauthbearer.method"] = "oidc";
|
|
4338
|
-
base["sasl.oauthbearer.token.endpoint.url"] = tokenEndpoint;
|
|
4339
|
-
}
|
|
4340
4296
|
const clientId = optionString(additionalSettings, "ClientId", "clientId");
|
|
4341
|
-
if (clientId) {
|
|
4342
|
-
base["sasl.oauthbearer.client.id"] = clientId;
|
|
4343
|
-
}
|
|
4344
4297
|
const clientSecret = optionString(additionalSettings, "ClientSecret", "clientSecret");
|
|
4345
|
-
if (clientSecret) {
|
|
4346
|
-
base["sasl.oauthbearer.client.secret"] = clientSecret;
|
|
4347
|
-
}
|
|
4348
4298
|
const scope = optionString(additionalSettings, "Scope", "scope");
|
|
4349
|
-
if (scope) {
|
|
4350
|
-
base["sasl.oauthbearer.scope"] = scope;
|
|
4351
|
-
}
|
|
4352
4299
|
const grantType = optionString(additionalSettings, "GrantType", "grantType");
|
|
4353
|
-
if (grantType) {
|
|
4354
|
-
base["sasl.oauthbearer.grant.type"] = grantType;
|
|
4355
|
-
}
|
|
4356
4300
|
const extensions = optionString(additionalSettings, "Extensions", "extensions");
|
|
4357
|
-
if (
|
|
4358
|
-
|
|
4301
|
+
if (directToken) {
|
|
4302
|
+
const principal = optionString(additionalSettings, "Principal", "principal")
|
|
4303
|
+
|| optionString(saslOptions, "Username", "username")
|
|
4304
|
+
|| "loadstrike";
|
|
4305
|
+
base.oauthbearer_token_refresh_cb = async () => ({
|
|
4306
|
+
tokenValue: directToken,
|
|
4307
|
+
lifetime: Date.now() + 60 * 60 * 1000,
|
|
4308
|
+
principal,
|
|
4309
|
+
extensions: parseKafkaOAuthExtensions(extensions)
|
|
4310
|
+
});
|
|
4311
|
+
}
|
|
4312
|
+
else {
|
|
4313
|
+
if (!tokenEndpoint || !clientId || !clientSecret) {
|
|
4314
|
+
throw new Error("Kafka OAuthBearer requires a direct access token or token endpoint with client credentials.");
|
|
4315
|
+
}
|
|
4316
|
+
base["sasl.oauthbearer.method"] = "oidc";
|
|
4317
|
+
base["sasl.oauthbearer.token.endpoint.url"] = tokenEndpoint;
|
|
4318
|
+
base["sasl.oauthbearer.client.id"] = clientId;
|
|
4319
|
+
base["sasl.oauthbearer.client.secret"] = clientSecret;
|
|
4320
|
+
if (scope) {
|
|
4321
|
+
base["sasl.oauthbearer.scope"] = scope;
|
|
4322
|
+
}
|
|
4323
|
+
if (grantType) {
|
|
4324
|
+
base["sasl.oauthbearer.grant.type"] = grantType;
|
|
4325
|
+
}
|
|
4326
|
+
if (extensions) {
|
|
4327
|
+
base["sasl.oauthbearer.extensions"] = extensions;
|
|
4328
|
+
}
|
|
4359
4329
|
}
|
|
4360
4330
|
}
|
|
4361
4331
|
else {
|
|
@@ -4374,7 +4344,9 @@ function buildConfluentKafkaClientOptions(endpoint) {
|
|
|
4374
4344
|
|| key === "Extensions"
|
|
4375
4345
|
|| key === "extensions"
|
|
4376
4346
|
|| key === "TokenEndpoint"
|
|
4377
|
-
|| key === "tokenEndpoint"
|
|
4347
|
+
|| key === "tokenEndpoint"
|
|
4348
|
+
|| key === "Principal"
|
|
4349
|
+
|| key === "principal") {
|
|
4378
4350
|
continue;
|
|
4379
4351
|
}
|
|
4380
4352
|
base[key] = value;
|
|
@@ -4385,53 +4357,20 @@ function buildConfluentKafkaClientOptions(endpoint) {
|
|
|
4385
4357
|
}
|
|
4386
4358
|
return base;
|
|
4387
4359
|
}
|
|
4388
|
-
|
|
4389
|
-
const
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
const form = new URLSearchParams();
|
|
4401
|
-
form.set("grant_type", "client_credentials");
|
|
4402
|
-
form.set("client_id", clientId);
|
|
4403
|
-
form.set("client_secret", clientSecret);
|
|
4404
|
-
const scope = optionString(additional, "Scope", "scope");
|
|
4405
|
-
if (scope) {
|
|
4406
|
-
form.set("scope", scope);
|
|
4407
|
-
}
|
|
4408
|
-
const response = await fetch(tokenEndpoint, {
|
|
4409
|
-
method: "POST",
|
|
4410
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
4411
|
-
body: form.toString()
|
|
4412
|
-
});
|
|
4413
|
-
if (!response.ok) {
|
|
4414
|
-
throw new Error(`Kafka OAuthBearer token request failed with status ${response.status}.`);
|
|
4415
|
-
}
|
|
4416
|
-
const payload = parseMaybeJson(await response.text());
|
|
4417
|
-
if (!isRecord(payload) || !payload.access_token) {
|
|
4418
|
-
throw new Error("Kafka OAuthBearer token response did not contain access_token.");
|
|
4419
|
-
}
|
|
4420
|
-
return String(payload.access_token);
|
|
4421
|
-
}
|
|
4422
|
-
function mapKafkaSaslMechanism(mechanism) {
|
|
4423
|
-
switch (mechanism) {
|
|
4424
|
-
case "plain":
|
|
4425
|
-
return "plain";
|
|
4426
|
-
case "scramsha256":
|
|
4427
|
-
case "scram-sha-256":
|
|
4428
|
-
return "scram-sha-256";
|
|
4429
|
-
case "scramsha512":
|
|
4430
|
-
case "scram-sha-512":
|
|
4431
|
-
return "scram-sha-512";
|
|
4432
|
-
default:
|
|
4433
|
-
throw new Error(`Unsupported Kafka SASL mechanism: ${mechanism}.`);
|
|
4360
|
+
function parseKafkaOAuthExtensions(value) {
|
|
4361
|
+
const parsed = {};
|
|
4362
|
+
for (const entry of value.split(",")) {
|
|
4363
|
+
const separatorIndex = entry.indexOf("=");
|
|
4364
|
+
if (separatorIndex <= 0) {
|
|
4365
|
+
continue;
|
|
4366
|
+
}
|
|
4367
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
4368
|
+
if (!key) {
|
|
4369
|
+
continue;
|
|
4370
|
+
}
|
|
4371
|
+
parsed[key] = entry.slice(separatorIndex + 1).trim();
|
|
4434
4372
|
}
|
|
4373
|
+
return parsed;
|
|
4435
4374
|
}
|
|
4436
4375
|
function mapConfluentKafkaSecurityProtocol(protocol) {
|
|
4437
4376
|
switch (protocol.toLowerCase()) {
|
|
@@ -4715,7 +4654,6 @@ exports.__loadstrikeTestExports = {
|
|
|
4715
4654
|
applyHttpAuthHeaders,
|
|
4716
4655
|
buildHttpRequestBody,
|
|
4717
4656
|
buildConfluentKafkaClientOptions,
|
|
4718
|
-
buildKafkaClientOptions,
|
|
4719
4657
|
canonicalizeHttpResponseSource,
|
|
4720
4658
|
createDelegateRequestEndpointView,
|
|
4721
4659
|
createNatsHeaders,
|
|
@@ -4731,7 +4669,6 @@ exports.__loadstrikeTestExports = {
|
|
|
4731
4669
|
injectTrackingValue,
|
|
4732
4670
|
mapConfluentKafkaSaslMechanism,
|
|
4733
4671
|
mapConfluentKafkaSecurityProtocol,
|
|
4734
|
-
mapKafkaSaslMechanism,
|
|
4735
4672
|
parseBodyObject,
|
|
4736
4673
|
partitionFromKey,
|
|
4737
4674
|
payloadBodyAsUtf8,
|
|
@@ -4739,10 +4676,8 @@ exports.__loadstrikeTestExports = {
|
|
|
4739
4676
|
protocolBus: protocolBus,
|
|
4740
4677
|
readFirstRedisStreamEntry,
|
|
4741
4678
|
resolveConnectionMetadata,
|
|
4742
|
-
resolveKafkaOAuthBearerToken,
|
|
4743
4679
|
serializePayloadBody,
|
|
4744
4680
|
setJsonBodyValue,
|
|
4745
|
-
shouldUseConfluentKafkaClient,
|
|
4746
4681
|
toHeaderRecord,
|
|
4747
4682
|
toKafkaHeadersWithContentType,
|
|
4748
4683
|
toSqsMessageAttributes,
|
|
@@ -4750,6 +4685,9 @@ exports.__loadstrikeTestExports = {
|
|
|
4750
4685
|
setSqsClientFactoryForTests: (factory) => {
|
|
4751
4686
|
sqsClientFactoryForTests = factory;
|
|
4752
4687
|
},
|
|
4688
|
+
setKafkaClientFactoryForTests: (factory) => {
|
|
4689
|
+
kafkaClientFactoryForTests = factory;
|
|
4690
|
+
},
|
|
4753
4691
|
validateHttpEndpoint,
|
|
4754
4692
|
validateTrackingSelectorPath
|
|
4755
4693
|
};
|