@loadstrike/loadstrike-sdk 1.0.22801 → 1.0.23001
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 +1 -1
- package/dist/cjs/autopilot.js +56 -2
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/local.js +153 -155
- package/dist/cjs/runtime.js +1 -0
- package/dist/cjs/transports.js +295 -1
- package/dist/esm/autopilot.js +55 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/local.js +153 -155
- package/dist/esm/runtime.js +1 -0
- package/dist/esm/transports.js +294 -0
- package/dist/types/autopilot-contracts.d.ts +2 -0
- package/dist/types/autopilot.d.ts +5 -2
- package/dist/types/contracts.d.ts +13 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/transports.d.ts +97 -2
- package/package.json +2 -7
package/dist/cjs/transports.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.__loadstrikeTestExports = exports.EndpointAdapterFactory = exports.KafkaSaslOptions = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = exports.LOADSTRIKE_TRACE_ID_TRACKING_FIELD = exports.LOADSTRIKE_TRACE_ID_HEADER = void 0;
|
|
36
|
+
exports.__loadstrikeTestExports = exports.EndpointAdapterFactory = exports.KafkaSaslOptions = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = exports.SqsEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = exports.LOADSTRIKE_TRACE_ID_TRACKING_FIELD = exports.LOADSTRIKE_TRACE_ID_HEADER = void 0;
|
|
37
37
|
const node_crypto_1 = require("node:crypto");
|
|
38
38
|
const correlation_js_1 = require("./correlation.js");
|
|
39
39
|
exports.LOADSTRIKE_TRACE_ID_HEADER = "loadstrike-trace-id";
|
|
@@ -254,6 +254,35 @@ class AzureEventHubsEndpointDefinitionModel extends TrafficEndpointDefinitionMod
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
+
class SqsEndpointDefinitionModel extends TrafficEndpointDefinitionModel {
|
|
258
|
+
constructor(initial) {
|
|
259
|
+
super(initial);
|
|
260
|
+
this.Kind = "Sqs";
|
|
261
|
+
this.QueueUrl = "";
|
|
262
|
+
this.Region = "";
|
|
263
|
+
this.WaitTimeSeconds = 1;
|
|
264
|
+
this.MaxNumberOfMessages = 1;
|
|
265
|
+
this.DeleteAfterConsume = true;
|
|
266
|
+
initializeSqsEndpointDefinitionModel(this, initial);
|
|
267
|
+
}
|
|
268
|
+
Validate() {
|
|
269
|
+
super.Validate();
|
|
270
|
+
requireNonEmptyString(this.QueueUrl, "QueueUrl must be provided for AWS SQS endpoint.");
|
|
271
|
+
requireNonEmptyString(this.Region, "Region must be provided for AWS SQS endpoint.");
|
|
272
|
+
if (String(this.AccessKeyId ?? "").trim() && !String(this.SecretAccessKey ?? "").trim()) {
|
|
273
|
+
throw new Error("SecretAccessKey must be provided when AccessKeyId is configured for AWS SQS endpoint.");
|
|
274
|
+
}
|
|
275
|
+
if (this.WaitTimeSeconds < 0 || this.WaitTimeSeconds > 20) {
|
|
276
|
+
throw new RangeError("WaitTimeSeconds must be between 0 and 20 for AWS SQS endpoint.");
|
|
277
|
+
}
|
|
278
|
+
if (this.MaxNumberOfMessages <= 0 || this.MaxNumberOfMessages > 10) {
|
|
279
|
+
throw new RangeError("MaxNumberOfMessages must be between 1 and 10 for AWS SQS endpoint.");
|
|
280
|
+
}
|
|
281
|
+
if (this.VisibilityTimeoutSeconds != null && this.VisibilityTimeoutSeconds < 0) {
|
|
282
|
+
throw new RangeError("VisibilityTimeoutSeconds must be zero or greater when configured.");
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
257
286
|
class DelegateStreamEndpointDefinitionModel extends TrafficEndpointDefinitionModel {
|
|
258
287
|
constructor(initial) {
|
|
259
288
|
super(initial);
|
|
@@ -299,6 +328,7 @@ exports.RabbitMqEndpointDefinition = RabbitMqEndpointDefinitionModel;
|
|
|
299
328
|
exports.NatsEndpointDefinition = NatsEndpointDefinitionModel;
|
|
300
329
|
exports.RedisStreamsEndpointDefinition = RedisStreamsEndpointDefinitionModel;
|
|
301
330
|
exports.AzureEventHubsEndpointDefinition = AzureEventHubsEndpointDefinitionModel;
|
|
331
|
+
exports.SqsEndpointDefinition = SqsEndpointDefinitionModel;
|
|
302
332
|
exports.DelegateStreamEndpointDefinition = DelegateStreamEndpointDefinitionModel;
|
|
303
333
|
exports.PushDiffusionEndpointDefinition = PushDiffusionEndpointDefinitionModel;
|
|
304
334
|
exports.HttpOAuth2ClientCredentialsOptions = HttpOAuth2ClientCredentialsOptionsModel;
|
|
@@ -662,6 +692,44 @@ function initializeAzureEventHubsEndpointDefinitionModel(target, initial) {
|
|
|
662
692
|
target.PartitionCount = pickOptionalEndpointNumber(raw, "PartitionCount", "partitionCount");
|
|
663
693
|
}
|
|
664
694
|
}
|
|
695
|
+
function initializeSqsEndpointDefinitionModel(target, initial) {
|
|
696
|
+
const raw = asRecordOrEmpty(initial);
|
|
697
|
+
const queueUrl = pickOptionalEndpointString(raw, "QueueUrl", "queueUrl");
|
|
698
|
+
if (queueUrl) {
|
|
699
|
+
target.QueueUrl = queueUrl;
|
|
700
|
+
}
|
|
701
|
+
const region = pickOptionalEndpointString(raw, "Region", "region");
|
|
702
|
+
if (region) {
|
|
703
|
+
target.Region = region;
|
|
704
|
+
}
|
|
705
|
+
if (hasAnyEndpointField(raw, ["ServiceUrl", "serviceUrl"])) {
|
|
706
|
+
target.ServiceUrl = pickOptionalEndpointString(raw, "ServiceUrl", "serviceUrl");
|
|
707
|
+
}
|
|
708
|
+
if (hasAnyEndpointField(raw, ["AccessKeyId", "accessKeyId"])) {
|
|
709
|
+
target.AccessKeyId = pickOptionalEndpointString(raw, "AccessKeyId", "accessKeyId");
|
|
710
|
+
}
|
|
711
|
+
if (hasAnyEndpointField(raw, ["SecretAccessKey", "secretAccessKey"])) {
|
|
712
|
+
target.SecretAccessKey = pickOptionalEndpointStringAllowEmpty(raw, "SecretAccessKey", "secretAccessKey");
|
|
713
|
+
}
|
|
714
|
+
if (hasAnyEndpointField(raw, ["SessionToken", "sessionToken"])) {
|
|
715
|
+
target.SessionToken = pickOptionalEndpointString(raw, "SessionToken", "sessionToken");
|
|
716
|
+
}
|
|
717
|
+
const waitTimeSeconds = pickOptionalEndpointNumber(raw, "WaitTimeSeconds", "waitTimeSeconds");
|
|
718
|
+
if (waitTimeSeconds != null) {
|
|
719
|
+
target.WaitTimeSeconds = waitTimeSeconds;
|
|
720
|
+
}
|
|
721
|
+
const maxNumberOfMessages = pickOptionalEndpointNumber(raw, "MaxNumberOfMessages", "maxNumberOfMessages");
|
|
722
|
+
if (maxNumberOfMessages != null) {
|
|
723
|
+
target.MaxNumberOfMessages = maxNumberOfMessages;
|
|
724
|
+
}
|
|
725
|
+
if (hasAnyEndpointField(raw, ["VisibilityTimeoutSeconds", "visibilityTimeoutSeconds"])) {
|
|
726
|
+
target.VisibilityTimeoutSeconds = pickOptionalEndpointNumber(raw, "VisibilityTimeoutSeconds", "visibilityTimeoutSeconds");
|
|
727
|
+
}
|
|
728
|
+
const deleteAfterConsume = pickEndpointBoolean(raw, "DeleteAfterConsume", "deleteAfterConsume");
|
|
729
|
+
if (deleteAfterConsume != null) {
|
|
730
|
+
target.DeleteAfterConsume = deleteAfterConsume;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
665
733
|
function initializeDelegateStreamEndpointDefinitionModel(target, initial) {
|
|
666
734
|
const raw = asRecordOrEmpty(initial);
|
|
667
735
|
const produce = pickEndpointFunction(raw, "Produce", "produce");
|
|
@@ -798,6 +866,7 @@ const protocolBus = new class InMemoryProtocolBus {
|
|
|
798
866
|
this.redisCounters = new Map();
|
|
799
867
|
this.eventHubs = new Map();
|
|
800
868
|
this.eventHubOffsets = new Map();
|
|
869
|
+
this.sqsQueues = new Map();
|
|
801
870
|
this.pushTopics = new Map();
|
|
802
871
|
this.pushOffsets = new Map();
|
|
803
872
|
}
|
|
@@ -812,6 +881,7 @@ const protocolBus = new class InMemoryProtocolBus {
|
|
|
812
881
|
this.redisCounters.clear();
|
|
813
882
|
this.eventHubs.clear();
|
|
814
883
|
this.eventHubOffsets.clear();
|
|
884
|
+
this.sqsQueues.clear();
|
|
815
885
|
this.pushTopics.clear();
|
|
816
886
|
this.pushOffsets.clear();
|
|
817
887
|
}
|
|
@@ -976,6 +1046,25 @@ const protocolBus = new class InMemoryProtocolBus {
|
|
|
976
1046
|
this.eventHubOffsets.set(cursorKey, rows.length);
|
|
977
1047
|
return null;
|
|
978
1048
|
}
|
|
1049
|
+
produceSqs(endpoint, payload) {
|
|
1050
|
+
const options = endpoint.sqs ?? {};
|
|
1051
|
+
const queueUrl = optionString(options, "QueueUrl", "queueUrl") || endpoint.name;
|
|
1052
|
+
const queue = this.sqsQueues.get(queueUrl) ?? [];
|
|
1053
|
+
queue.push({ payload: clonePayload(payload), timestampMs: Date.now() });
|
|
1054
|
+
this.sqsQueues.set(queueUrl, queue);
|
|
1055
|
+
return clonePayload(payload);
|
|
1056
|
+
}
|
|
1057
|
+
consumeSqs(endpoint) {
|
|
1058
|
+
const options = endpoint.sqs ?? {};
|
|
1059
|
+
const queueUrl = optionString(options, "QueueUrl", "queueUrl") || endpoint.name;
|
|
1060
|
+
const queue = this.sqsQueues.get(queueUrl) ?? [];
|
|
1061
|
+
if (!queue.length) {
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
const next = queue.shift() ?? null;
|
|
1065
|
+
this.sqsQueues.set(queueUrl, queue);
|
|
1066
|
+
return next ? clonePayload(next.payload) : null;
|
|
1067
|
+
}
|
|
979
1068
|
producePush(endpoint, payload) {
|
|
980
1069
|
const options = endpoint.pushDiffusion ?? {};
|
|
981
1070
|
const topic = optionString(options, "TopicPath", "topicPath")
|
|
@@ -1717,6 +1806,104 @@ class AzureEventHubsEndpointAdapter extends CallbackAdapter {
|
|
|
1717
1806
|
await this.subscriptionPromise;
|
|
1718
1807
|
}
|
|
1719
1808
|
}
|
|
1809
|
+
let sqsClientFactoryForTests = null;
|
|
1810
|
+
class SqsEndpointAdapter extends CallbackAdapter {
|
|
1811
|
+
constructor() {
|
|
1812
|
+
super(...arguments);
|
|
1813
|
+
this.clientPromise = null;
|
|
1814
|
+
}
|
|
1815
|
+
async produce(payload) {
|
|
1816
|
+
if (resolveProduceDelegate(this.endpoint)) {
|
|
1817
|
+
return super.produce(payload);
|
|
1818
|
+
}
|
|
1819
|
+
if (this.endpoint.mode !== "Produce") {
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
const client = await this.getClient();
|
|
1823
|
+
const options = this.endpoint.sqs ?? {};
|
|
1824
|
+
const resolved = prepareProducedPayload(this.endpoint, payload);
|
|
1825
|
+
const wire = toWirePayload(resolved, this.endpoint);
|
|
1826
|
+
const { SendMessageCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
|
|
1827
|
+
await client.send(new SendMessageCommand({
|
|
1828
|
+
QueueUrl: optionString(options, "QueueUrl", "queueUrl"),
|
|
1829
|
+
MessageBody: payloadBodyAsUtf8(wire.body),
|
|
1830
|
+
MessageAttributes: toSqsMessageAttributes(wire.headers, wire.contentType)
|
|
1831
|
+
}));
|
|
1832
|
+
return clonePayload(resolved);
|
|
1833
|
+
}
|
|
1834
|
+
async consume() {
|
|
1835
|
+
if (resolveConsumeDelegate(this.endpoint)) {
|
|
1836
|
+
return super.consume();
|
|
1837
|
+
}
|
|
1838
|
+
if (this.endpoint.mode !== "Consume") {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
const client = await this.getClient();
|
|
1842
|
+
const options = this.endpoint.sqs ?? {};
|
|
1843
|
+
const { ReceiveMessageCommand, DeleteMessageCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
|
|
1844
|
+
const input = {
|
|
1845
|
+
QueueUrl: optionString(options, "QueueUrl", "queueUrl"),
|
|
1846
|
+
MaxNumberOfMessages: hasOptionValue(options, "MaxNumberOfMessages", "maxNumberOfMessages")
|
|
1847
|
+
? optionNumber(options, "MaxNumberOfMessages", "maxNumberOfMessages")
|
|
1848
|
+
: 1,
|
|
1849
|
+
WaitTimeSeconds: hasOptionValue(options, "WaitTimeSeconds", "waitTimeSeconds")
|
|
1850
|
+
? optionNumber(options, "WaitTimeSeconds", "waitTimeSeconds")
|
|
1851
|
+
: 1,
|
|
1852
|
+
MessageAttributeNames: ["All"]
|
|
1853
|
+
};
|
|
1854
|
+
const visibilityTimeout = optionNumber(options, "VisibilityTimeoutSeconds", "visibilityTimeoutSeconds");
|
|
1855
|
+
if (visibilityTimeout > 0) {
|
|
1856
|
+
input.VisibilityTimeout = visibilityTimeout;
|
|
1857
|
+
}
|
|
1858
|
+
const response = await client.send(new ReceiveMessageCommand(input));
|
|
1859
|
+
const message = response.Messages?.[0];
|
|
1860
|
+
if (!message) {
|
|
1861
|
+
return null;
|
|
1862
|
+
}
|
|
1863
|
+
const { headers, contentType } = fromSqsMessageAttributes(message.MessageAttributes);
|
|
1864
|
+
const payload = createBrokerPayload(headers, Buffer.from(message.Body ?? "", "utf8"), this.endpoint, contentType);
|
|
1865
|
+
if (optionBoolean(options, true, "DeleteAfterConsume", "deleteAfterConsume") && message.ReceiptHandle) {
|
|
1866
|
+
await client.send(new DeleteMessageCommand({
|
|
1867
|
+
QueueUrl: optionString(options, "QueueUrl", "queueUrl"),
|
|
1868
|
+
ReceiptHandle: message.ReceiptHandle
|
|
1869
|
+
}));
|
|
1870
|
+
}
|
|
1871
|
+
return payload;
|
|
1872
|
+
}
|
|
1873
|
+
async dispose() {
|
|
1874
|
+
const client = await this.clientPromise?.catch(() => null);
|
|
1875
|
+
client?.destroy?.();
|
|
1876
|
+
}
|
|
1877
|
+
async getClient() {
|
|
1878
|
+
if (!this.clientPromise) {
|
|
1879
|
+
this.clientPromise = (async () => {
|
|
1880
|
+
if (sqsClientFactoryForTests) {
|
|
1881
|
+
return await sqsClientFactoryForTests(this.endpoint);
|
|
1882
|
+
}
|
|
1883
|
+
const { SQSClient } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
|
|
1884
|
+
const options = this.endpoint.sqs ?? {};
|
|
1885
|
+
const accessKeyId = optionString(options, "AccessKeyId", "accessKeyId");
|
|
1886
|
+
const secretAccessKey = optionString(options, "SecretAccessKey", "secretAccessKey");
|
|
1887
|
+
const config = {
|
|
1888
|
+
region: optionString(options, "Region", "region")
|
|
1889
|
+
};
|
|
1890
|
+
const serviceUrl = optionString(options, "ServiceUrl", "serviceUrl");
|
|
1891
|
+
if (serviceUrl) {
|
|
1892
|
+
config.endpoint = serviceUrl;
|
|
1893
|
+
}
|
|
1894
|
+
if (accessKeyId) {
|
|
1895
|
+
config.credentials = {
|
|
1896
|
+
accessKeyId,
|
|
1897
|
+
secretAccessKey,
|
|
1898
|
+
sessionToken: optionString(options, "SessionToken", "sessionToken") || undefined
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
return new SQSClient(config);
|
|
1902
|
+
})();
|
|
1903
|
+
}
|
|
1904
|
+
return this.clientPromise;
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1720
1907
|
class PushDiffusionEndpointAdapter extends CallbackAdapter {
|
|
1721
1908
|
async produce(payload) {
|
|
1722
1909
|
return super.produce(payload);
|
|
@@ -1747,6 +1934,8 @@ class EndpointAdapterFactory {
|
|
|
1747
1934
|
return new RedisStreamsEndpointAdapter(normalized);
|
|
1748
1935
|
case "AzureEventHubs":
|
|
1749
1936
|
return new AzureEventHubsEndpointAdapter(normalized);
|
|
1937
|
+
case "Sqs":
|
|
1938
|
+
return new SqsEndpointAdapter(normalized);
|
|
1750
1939
|
case "PushDiffusion":
|
|
1751
1940
|
return new PushDiffusionEndpointAdapter(normalized);
|
|
1752
1941
|
case "DelegateStream":
|
|
@@ -1875,6 +2064,28 @@ const AZURE_EVENT_HUBS_ENDPOINT_FLAT_KEYS = [
|
|
|
1875
2064
|
"StartFromEarliest",
|
|
1876
2065
|
"startFromEarliest"
|
|
1877
2066
|
];
|
|
2067
|
+
const SQS_ENDPOINT_FLAT_KEYS = [
|
|
2068
|
+
"QueueUrl",
|
|
2069
|
+
"queueUrl",
|
|
2070
|
+
"Region",
|
|
2071
|
+
"region",
|
|
2072
|
+
"ServiceUrl",
|
|
2073
|
+
"serviceUrl",
|
|
2074
|
+
"AccessKeyId",
|
|
2075
|
+
"accessKeyId",
|
|
2076
|
+
"SecretAccessKey",
|
|
2077
|
+
"secretAccessKey",
|
|
2078
|
+
"SessionToken",
|
|
2079
|
+
"sessionToken",
|
|
2080
|
+
"WaitTimeSeconds",
|
|
2081
|
+
"waitTimeSeconds",
|
|
2082
|
+
"MaxNumberOfMessages",
|
|
2083
|
+
"maxNumberOfMessages",
|
|
2084
|
+
"VisibilityTimeoutSeconds",
|
|
2085
|
+
"visibilityTimeoutSeconds",
|
|
2086
|
+
"DeleteAfterConsume",
|
|
2087
|
+
"deleteAfterConsume"
|
|
2088
|
+
];
|
|
1878
2089
|
const PUSH_DIFFUSION_ENDPOINT_FLAT_KEYS = [
|
|
1879
2090
|
"ServerUrl",
|
|
1880
2091
|
"serverUrl",
|
|
@@ -1935,6 +2146,7 @@ function normalizeEndpointDefinition(endpoint) {
|
|
|
1935
2146
|
nats: normalizeProtocolOptions(pickEndpointTransportRecord(raw, kind, "Nats", ["nats", "Nats"], NATS_ENDPOINT_FLAT_KEYS)),
|
|
1936
2147
|
redisStreams: normalizeProtocolOptions(pickEndpointTransportRecord(raw, kind, "RedisStreams", ["redisStreams", "RedisStreams"], REDIS_STREAMS_ENDPOINT_FLAT_KEYS)),
|
|
1937
2148
|
azureEventHubs: normalizeProtocolOptions(pickEndpointTransportRecord(raw, kind, "AzureEventHubs", ["azureEventHubs", "AzureEventHubs"], AZURE_EVENT_HUBS_ENDPOINT_FLAT_KEYS)),
|
|
2149
|
+
sqs: normalizeProtocolOptions(pickEndpointTransportRecord(raw, kind, "Sqs", ["sqs", "Sqs"], SQS_ENDPOINT_FLAT_KEYS)),
|
|
1938
2150
|
pushDiffusion: normalizeProtocolOptions(pickEndpointTransportRecord(raw, kind, "PushDiffusion", ["pushDiffusion", "PushDiffusion"], PUSH_DIFFUSION_ENDPOINT_FLAT_KEYS)),
|
|
1939
2151
|
delegate: normalizeDelegateEndpointOptions(pickEndpointTransportRecord(raw, kind, "DelegateStream", ["delegate", "Delegate", "DelegateStream"], DELEGATE_STREAM_ENDPOINT_FLAT_KEYS))
|
|
1940
2152
|
};
|
|
@@ -1992,6 +2204,22 @@ function resolveEndpointKind(raw) {
|
|
|
1992
2204
|
])) {
|
|
1993
2205
|
return "AzureEventHubs";
|
|
1994
2206
|
}
|
|
2207
|
+
if (Object.keys(pickEndpointRecord(raw, "sqs", "Sqs")).length || hasAnyEndpointField(raw, [
|
|
2208
|
+
"QueueUrl",
|
|
2209
|
+
"queueUrl",
|
|
2210
|
+
"ServiceUrl",
|
|
2211
|
+
"serviceUrl",
|
|
2212
|
+
"WaitTimeSeconds",
|
|
2213
|
+
"waitTimeSeconds",
|
|
2214
|
+
"MaxNumberOfMessages",
|
|
2215
|
+
"maxNumberOfMessages",
|
|
2216
|
+
"VisibilityTimeoutSeconds",
|
|
2217
|
+
"visibilityTimeoutSeconds",
|
|
2218
|
+
"DeleteAfterConsume",
|
|
2219
|
+
"deleteAfterConsume"
|
|
2220
|
+
])) {
|
|
2221
|
+
return "Sqs";
|
|
2222
|
+
}
|
|
1995
2223
|
if (Object.keys(pickEndpointRecord(raw, "pushDiffusion", "PushDiffusion")).length || hasAnyEndpointField(raw, [
|
|
1996
2224
|
"TopicPath",
|
|
1997
2225
|
"topicPath",
|
|
@@ -2273,6 +2501,9 @@ function validateEndpointDefinition(endpoint) {
|
|
|
2273
2501
|
case "AzureEventHubs":
|
|
2274
2502
|
validateAzureEventHubsEndpoint(endpoint, mode, hasModeDelegate);
|
|
2275
2503
|
return;
|
|
2504
|
+
case "Sqs":
|
|
2505
|
+
validateSqsEndpoint(endpoint, mode, hasModeDelegate);
|
|
2506
|
+
return;
|
|
2276
2507
|
case "PushDiffusion":
|
|
2277
2508
|
validatePushDiffusionEndpoint(endpoint, mode);
|
|
2278
2509
|
return;
|
|
@@ -2494,6 +2725,32 @@ function validateAzureEventHubsEndpoint(endpoint, mode, hasModeDelegate) {
|
|
|
2494
2725
|
throw new RangeError("PartitionCount must be zero or greater when configured.");
|
|
2495
2726
|
}
|
|
2496
2727
|
}
|
|
2728
|
+
function validateSqsEndpoint(endpoint, mode, hasModeDelegate) {
|
|
2729
|
+
const options = endpoint.sqs;
|
|
2730
|
+
if ((!options || typeof options !== "object") && !hasModeDelegate) {
|
|
2731
|
+
throw new Error(`Sqs endpoint in ${mode} mode requires sqs options or delegate callback.`);
|
|
2732
|
+
}
|
|
2733
|
+
if (!options || typeof options !== "object") {
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
requireNonEmptyString(optionString(options, "QueueUrl", "queueUrl"), "QueueUrl must be provided for AWS SQS endpoint.");
|
|
2737
|
+
requireNonEmptyString(optionString(options, "Region", "region"), "Region must be provided for AWS SQS endpoint.");
|
|
2738
|
+
if (optionString(options, "AccessKeyId", "accessKeyId") && !optionString(options, "SecretAccessKey", "secretAccessKey")) {
|
|
2739
|
+
throw new Error("SecretAccessKey must be provided when AccessKeyId is configured for AWS SQS endpoint.");
|
|
2740
|
+
}
|
|
2741
|
+
const waitTimeSeconds = optionNumber(options, "WaitTimeSeconds", "waitTimeSeconds");
|
|
2742
|
+
if (waitTimeSeconds < 0 || waitTimeSeconds > 20) {
|
|
2743
|
+
throw new RangeError("WaitTimeSeconds must be between 0 and 20 for AWS SQS endpoint.");
|
|
2744
|
+
}
|
|
2745
|
+
const maxNumberOfMessages = optionNumber(options, "MaxNumberOfMessages", "maxNumberOfMessages") || 1;
|
|
2746
|
+
if (maxNumberOfMessages <= 0 || maxNumberOfMessages > 10) {
|
|
2747
|
+
throw new RangeError("MaxNumberOfMessages must be between 1 and 10 for AWS SQS endpoint.");
|
|
2748
|
+
}
|
|
2749
|
+
const visibilityTimeoutSeconds = optionNumber(options, "VisibilityTimeoutSeconds", "visibilityTimeoutSeconds");
|
|
2750
|
+
if (visibilityTimeoutSeconds < 0) {
|
|
2751
|
+
throw new RangeError("VisibilityTimeoutSeconds must be zero or greater when configured.");
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2497
2754
|
function validatePushDiffusionEndpoint(endpoint, mode) {
|
|
2498
2755
|
const options = endpoint.pushDiffusion;
|
|
2499
2756
|
if (!options || typeof options !== "object") {
|
|
@@ -2858,6 +3115,12 @@ function optionNumber(options, ...keys) {
|
|
|
2858
3115
|
}
|
|
2859
3116
|
return 0;
|
|
2860
3117
|
}
|
|
3118
|
+
function hasOptionValue(options, ...keys) {
|
|
3119
|
+
return keys.some((key) => {
|
|
3120
|
+
const value = options[key];
|
|
3121
|
+
return value !== undefined && value !== null && (!(typeof value === "string") || value.trim() !== "");
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
2861
3124
|
function optionBoolean(options, fallback, ...keys) {
|
|
2862
3125
|
for (const key of keys) {
|
|
2863
3126
|
const value = options[key];
|
|
@@ -3741,6 +4004,29 @@ function createRedisStreamPayload(fields, endpoint) {
|
|
|
3741
4004
|
}
|
|
3742
4005
|
return createBrokerPayload(headers, body, endpoint, contentType);
|
|
3743
4006
|
}
|
|
4007
|
+
function toSqsMessageAttributes(headers, contentType) {
|
|
4008
|
+
const attributes = {};
|
|
4009
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
4010
|
+
attributes[key] = { DataType: "String", StringValue: String(value ?? "") };
|
|
4011
|
+
}
|
|
4012
|
+
if (contentType) {
|
|
4013
|
+
attributes["content-type"] = { DataType: "String", StringValue: contentType };
|
|
4014
|
+
}
|
|
4015
|
+
return attributes;
|
|
4016
|
+
}
|
|
4017
|
+
function fromSqsMessageAttributes(attributes) {
|
|
4018
|
+
const headers = {};
|
|
4019
|
+
let contentType;
|
|
4020
|
+
for (const [key, value] of Object.entries(attributes ?? {})) {
|
|
4021
|
+
const text = String(value?.StringValue ?? "");
|
|
4022
|
+
if (key.toLowerCase() === "content-type") {
|
|
4023
|
+
contentType = text;
|
|
4024
|
+
continue;
|
|
4025
|
+
}
|
|
4026
|
+
headers[key] = text;
|
|
4027
|
+
}
|
|
4028
|
+
return { headers, contentType };
|
|
4029
|
+
}
|
|
3744
4030
|
function payloadBodyAsUtf8(body) {
|
|
3745
4031
|
if (body instanceof Uint8Array) {
|
|
3746
4032
|
return new TextDecoder().decode(body);
|
|
@@ -3775,6 +4061,9 @@ exports.__loadstrikeTestExports = {
|
|
|
3775
4061
|
RedisStreamsEndpointAdapter,
|
|
3776
4062
|
RedisStreamsEndpointDefinition: exports.RedisStreamsEndpointDefinition,
|
|
3777
4063
|
RedisStreamsEndpointDefinitionModel,
|
|
4064
|
+
SqsEndpointAdapter,
|
|
4065
|
+
SqsEndpointDefinition: exports.SqsEndpointDefinition,
|
|
4066
|
+
SqsEndpointDefinitionModel,
|
|
3778
4067
|
bufferToUint8Array,
|
|
3779
4068
|
applyHttpAuthHeaders,
|
|
3780
4069
|
buildHttpRequestBody,
|
|
@@ -3809,6 +4098,11 @@ exports.__loadstrikeTestExports = {
|
|
|
3809
4098
|
shouldUseConfluentKafkaClient,
|
|
3810
4099
|
toHeaderRecord,
|
|
3811
4100
|
toKafkaHeadersWithContentType,
|
|
4101
|
+
toSqsMessageAttributes,
|
|
4102
|
+
fromSqsMessageAttributes,
|
|
4103
|
+
setSqsClientFactoryForTests: (factory) => {
|
|
4104
|
+
sqsClientFactoryForTests = factory;
|
|
4105
|
+
},
|
|
3812
4106
|
validateHttpEndpoint,
|
|
3813
4107
|
validateTrackingSelectorPath
|
|
3814
4108
|
};
|
package/dist/esm/autopilot.js
CHANGED
|
@@ -12,11 +12,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
12
12
|
var _LoadStrikeAutopilotResult_httpRequest;
|
|
13
13
|
import fs from "node:fs";
|
|
14
14
|
import { LoadStrikeResponse, LoadStrikeScenario, LoadStrikeSimulation, LoadStrikeThreshold } from "./runtime.js";
|
|
15
|
+
import { LoadStrikeLocalClient } from "./local.js";
|
|
15
16
|
import { LoadStrikeAutopilotReadiness } from "./autopilot-contracts.js";
|
|
16
17
|
const REDACTED = "[REDACTED]";
|
|
17
18
|
const ENV_MARKER_PREFIX = "${LOADSTRIKE_ENV:";
|
|
18
19
|
const ENV_MARKER_SUFFIX = "}";
|
|
19
20
|
const TRACE_TO_TEST_AUTOPILOT_FEATURE = "autopilot.trace_to_test";
|
|
21
|
+
let autopilotLicenseValidationBypassForTests = false;
|
|
20
22
|
const SECRET_KEYS = new Set([
|
|
21
23
|
"authorization",
|
|
22
24
|
"proxy_authorization",
|
|
@@ -88,9 +90,10 @@ export class LoadStrikeAutopilotResult {
|
|
|
88
90
|
}
|
|
89
91
|
_LoadStrikeAutopilotResult_httpRequest = new WeakMap();
|
|
90
92
|
export class LoadStrikeAutopilot {
|
|
91
|
-
static generate(request) {
|
|
93
|
+
static async generate(request) {
|
|
92
94
|
const artifact = loadAutopilotArtifact(request);
|
|
93
95
|
const options = request.Options ?? {};
|
|
96
|
+
await validateGenerationEntitlement(options);
|
|
94
97
|
const result = inferAutopilotResult(artifact, options);
|
|
95
98
|
if (options.IncludePreviewReport) {
|
|
96
99
|
result.PreviewReport = buildPreviewReport(result);
|
|
@@ -101,6 +104,57 @@ export class LoadStrikeAutopilot {
|
|
|
101
104
|
return LoadStrikeAutopilot.generate(request);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
107
|
+
export const __private = {
|
|
108
|
+
setAutopilotLicenseValidationBypassForTests(value) {
|
|
109
|
+
autopilotLicenseValidationBypassForTests = value;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
async function validateGenerationEntitlement(options) {
|
|
113
|
+
if (autopilotLicenseValidationBypassForTests) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const licensePayload = {
|
|
117
|
+
Context: {
|
|
118
|
+
RunnerKey: options.RunnerKey ?? "",
|
|
119
|
+
LicenseValidationTimeoutSeconds: options.LicenseValidationTimeoutSeconds,
|
|
120
|
+
TestSuite: "loadstrike-autopilot",
|
|
121
|
+
TestName: options.ScenarioName?.trim() || "autopilot-generation"
|
|
122
|
+
},
|
|
123
|
+
Scenarios: [
|
|
124
|
+
{
|
|
125
|
+
Name: "autopilot-generation",
|
|
126
|
+
InternalLicenseFeatures: [TRACE_TO_TEST_AUTOPILOT_FEATURE]
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
RunArgs: []
|
|
130
|
+
};
|
|
131
|
+
const client = new LoadStrikeLocalClient({
|
|
132
|
+
licenseValidationTimeoutMs: normalizeLicenseValidationTimeoutMs(options.LicenseValidationTimeoutSeconds)
|
|
133
|
+
});
|
|
134
|
+
let session;
|
|
135
|
+
try {
|
|
136
|
+
session = await client.acquireLicenseLease(licensePayload);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
140
|
+
if (message.toLowerCase().includes("runner key is required")) {
|
|
141
|
+
throw new Error("Runner key is required for Trace-To-Test Autopilot generation. " +
|
|
142
|
+
"Set Options.RunnerKey before calling LoadStrikeAutopilot.generate(...).");
|
|
143
|
+
}
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
if (session) {
|
|
148
|
+
await client.releaseLicenseLease(session, licensePayload);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function normalizeLicenseValidationTimeoutMs(value) {
|
|
153
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return Math.trunc(value * 1000);
|
|
157
|
+
}
|
|
104
158
|
function loadAutopilotArtifact(request) {
|
|
105
159
|
if (!request || typeof request.Kind !== "string" || !request.Kind.trim()) {
|
|
106
160
|
throw new Error("Autopilot kind must be provided.");
|
package/dist/esm/index.js
CHANGED
|
@@ -2,5 +2,5 @@ export { LoadStrikeAutopilot, LoadStrikeAutopilotResult } from "./autopilot.js";
|
|
|
2
2
|
export { LoadStrikeAutopilotReadiness } from "./autopilot-contracts.js";
|
|
3
3
|
export { CrossPlatformScenarioConfigurator, ScenarioTrackingExtensions, LoadStrikeContext, LoadStrikePluginData, LoadStrikePluginDataTable, LoadStrikeNodeType, LoadStrikeReportFormat, LoadStrikeResponse, LoadStrikeLogLevel, LoadStrikeScenarioOperation, LoadStrikeOperationType, LoadStrikeRunner, LoadStrikeScenario, LoadStrikeSimulation, CrossPlatformTrackingConfiguration, LoadStrikeMetric, LoadStrikeCounter, LoadStrikeGauge, LoadStrikeStep, LoadStrikeThreshold } from "./runtime.js";
|
|
4
4
|
export { CorrelationStoreConfiguration, CrossPlatformTrackingRuntime, InMemoryCorrelationStore, RedisCorrelationStoreOptions, RedisCorrelationStore, TrackingPayloadBuilder, TrackingFieldSelector } from "./correlation.js";
|
|
5
|
-
export {
|
|
5
|
+
export { LOADSTRIKE_TRACE_ID_HEADER, LOADSTRIKE_TRACE_ID_TRACKING_FIELD, TrafficEndpointDefinition, HttpEndpointDefinition, KafkaEndpointDefinition, KafkaSaslOptions, RabbitMqEndpointDefinition, NatsEndpointDefinition, RedisStreamsEndpointDefinition, AzureEventHubsEndpointDefinition, SqsEndpointDefinition, DelegateStreamEndpointDefinition, PushDiffusionEndpointDefinition, HttpOAuth2ClientCredentialsOptions, HttpAuthOptions } from "./transports.js";
|
|
6
6
|
export { DatadogReportingSink, DatadogReportingSinkOptions, GrafanaLokiReportingSink, GrafanaLokiReportingSinkOptions, InfluxDbReportingSink, InfluxDbReportingSinkOptions, OtelCollectorReportingSink, OtelCollectorReportingSinkOptions, SplunkReportingSink, SplunkReportingSinkOptions, TimescaleDbReportingSink, TimescaleDbReportingSinkOptions } from "./sinks.js";
|