@loadstrike/loadstrike-sdk 1.0.27101 → 1.0.29201

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 CHANGED
@@ -9,9 +9,9 @@ LoadStrike is a developer-first load testing SDK for Node.js applications, servi
9
9
  - Exercise HTTP and event-driven workflows across multiple steps.
10
10
  - Apply load simulations, thresholds, and custom metrics to real transactions.
11
11
  - Split a single load profile across weighted scenario mixes.
12
- - Generate local reports and, on Business and Enterprise, publish observability data to supported sinks.
12
+ - Generate local reports and, on Enterprise, publish observability data to supported sinks.
13
13
 
14
- Built-in transport coverage includes HTTP, Kafka, RabbitMQ, NATS, Redis Streams, Azure Event Hubs, Push Diffusion, and delegate-based custom streams. Local report output supports HTML, Markdown, TXT, and CSV, and Business and Enterprise can publish to InfluxDB, TimescaleDB, Grafana Loki, Datadog, Splunk HEC, and OpenTelemetry Collector.
14
+ Built-in transport coverage includes HTTP, Kafka, RabbitMQ, NATS, Redis Streams, Azure Event Hubs, Push Diffusion, and delegate-based custom streams. Local report output supports HTML, Markdown, TXT, and CSV, and Enterprise can publish to InfluxDB, TimescaleDB, Grafana Loki, Datadog, Splunk HEC, OpenTelemetry Collector, and the expanded built-in sink family.
15
15
 
16
16
  ## Requirements
17
17
 
@@ -56,7 +56,7 @@ const result = await LoadStrikeRunner
56
56
 
57
57
  ## Traffic Mixes
58
58
 
59
- Use `LoadStrikeTrafficMix` on Business and Enterprise plans when one total load profile should be distributed across multiple scenario lanes. For example, a 1000 requests-per-second profile with scenario weights of 60, 30, and 10 sends roughly 600 requests per second to the first scenario, 300 to the second, and 100 to the third.
59
+ Use `LoadStrikeTrafficMix` on Pro and Enterprise plans when one total load profile should be distributed across multiple scenario lanes. For example, a 1000 requests-per-second profile with scenario weights of 60, 30, and 10 sends roughly 600 requests per second to the first scenario, 300 to the second, and 100 to the third.
60
60
 
61
61
  Each lane is still a normal scenario with its own named steps, thresholds, reports, and portal results. Register the mix with `LoadStrikeRunner.registerTrafficMix(...)` or add it to a runner with `.addTrafficMix(...)`.
62
62
 
package/dist/cjs/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HttpOAuth2ClientCredentialsOptions = exports.WebSocketEndpointDefinition = exports.GrpcEndpointDefinition = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = exports.SqsEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaSaslOptions = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = exports.LOADSTRIKE_TRACE_ID_TRACKING_FIELD = exports.LOADSTRIKE_TRACE_ID_HEADER = exports.TrackingFieldSelector = exports.TrackingPayloadBuilder = exports.RedisCorrelationStore = exports.RedisCorrelationStoreOptions = exports.InMemoryCorrelationStore = exports.CrossPlatformTrackingRuntime = exports.CorrelationStoreConfiguration = exports.LoadStrikeThreshold = exports.LoadStrikeStep = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeMetric = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeTrafficMix = exports.LoadStrikeSimulation = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeRunner = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeResponse = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = exports.LoadStrikePluginDataTable = exports.LoadStrikePluginData = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibility = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeAutopilotReadiness = exports.LoadStrikeAutopilotResult = exports.LoadStrikeAutopilot = void 0;
4
- exports.TimescaleDbReportingSinkOptions = exports.TimescaleDbReportingSink = exports.SplunkReportingSinkOptions = exports.SplunkReportingSink = exports.PortalReportingSink = exports.OtelCollectorReportingSinkOptions = exports.OtelCollectorReportingSink = exports.InfluxDbReportingSinkOptions = exports.InfluxDbReportingSink = exports.GrafanaLokiReportingSinkOptions = exports.GrafanaLokiReportingSink = exports.DatadogReportingSinkOptions = exports.DatadogReportingSink = exports.HttpAuthOptions = void 0;
3
+ exports.SqsEndpointDefinition = exports.AzureEventHubsEndpointDefinition = exports.RedisStreamsEndpointDefinition = exports.NatsEndpointDefinition = exports.RabbitMqEndpointDefinition = exports.KafkaSaslOptions = exports.KafkaEndpointDefinition = exports.HttpEndpointDefinition = exports.TrafficEndpointDefinition = exports.LOADSTRIKE_TRACE_ID_TRACKING_FIELD = exports.LOADSTRIKE_TRACE_ID_HEADER = exports.TrackingFieldSelector = exports.TrackingPayloadBuilder = exports.RedisCorrelationStore = exports.RedisCorrelationStoreOptions = exports.InMemoryCorrelationStore = exports.CrossPlatformTrackingRuntime = exports.CorrelationStoreConfiguration = exports.LoadStrikeThreshold = exports.LoadStrikeStep = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeMetric = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeTrafficMix = exports.LoadStrikeSimulation = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeRunner = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeResponse = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = exports.LoadStrikePluginDataTable = exports.LoadStrikePluginData = exports.LoadStrikeBrowserWebVitalsCollector = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibilityScanner = exports.LoadStrikeAccessibilityCiGate = exports.LoadStrikeAccessibilityBaseline = exports.LoadStrikeAccessibilityAdapters = exports.LoadStrikeAccessibility = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeAutopilotReadiness = exports.LoadStrikeAutopilotResult = exports.LoadStrikeAutopilot = void 0;
4
+ exports.TimescaleDbReportingSinkOptions = exports.TimescaleDbReportingSink = exports.StatsDReportingSink = exports.SplunkReportingSinkOptions = exports.SplunkReportingSink = exports.PrometheusRemoteWriteReportingSink = exports.PortalReportingSink = exports.OpenSearchReportingSink = exports.OtelCollectorReportingSinkOptions = exports.OtelCollectorReportingSink = exports.NewRelicReportingSink = exports.NetdataStatsDReportingSink = exports.KafkaReportingSink = exports.JsonlFileReportingSink = exports.InfluxDbReportingSinkOptions = exports.InfluxDbReportingSink = exports.GenericWebhookReportingSink = exports.GrafanaLokiReportingSinkOptions = exports.GrafanaLokiReportingSink = exports.ElasticsearchReportingSink = exports.DynatraceReportingSink = exports.CloudWatchReportingSink = exports.DogStatsDReportingSink = exports.DatadogReportingSinkOptions = exports.DatadogReportingSink = exports.HttpAuthOptions = exports.HttpOAuth2ClientCredentialsOptions = exports.WebSocketReconnectPolicy = exports.WebSocketNativeClientOptions = exports.WebSocketMessageSpec = exports.WebSocketExpectedMessage = exports.WebSocketEndpointDefinition = exports.ProtocolMetricSnapshot = exports.GrpcStatusMapper = exports.GrpcNativeClientOptions = exports.GrpcMethodTypes = exports.GrpcEndpointDefinition = exports.PushDiffusionEndpointDefinition = exports.DelegateStreamEndpointDefinition = void 0;
5
5
  var autopilot_js_1 = require("./autopilot.js");
6
6
  Object.defineProperty(exports, "LoadStrikeAutopilot", { enumerable: true, get: function () { return autopilot_js_1.LoadStrikeAutopilot; } });
7
7
  Object.defineProperty(exports, "LoadStrikeAutopilotResult", { enumerable: true, get: function () { return autopilot_js_1.LoadStrikeAutopilotResult; } });
@@ -12,7 +12,12 @@ Object.defineProperty(exports, "CrossPlatformScenarioConfigurator", { enumerable
12
12
  Object.defineProperty(exports, "ScenarioTrackingExtensions", { enumerable: true, get: function () { return runtime_js_1.ScenarioTrackingExtensions; } });
13
13
  Object.defineProperty(exports, "LoadStrikeContext", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeContext; } });
14
14
  Object.defineProperty(exports, "LoadStrikeAccessibility", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibility; } });
15
+ Object.defineProperty(exports, "LoadStrikeAccessibilityAdapters", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityAdapters; } });
16
+ Object.defineProperty(exports, "LoadStrikeAccessibilityBaseline", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityBaseline; } });
17
+ Object.defineProperty(exports, "LoadStrikeAccessibilityCiGate", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityCiGate; } });
18
+ Object.defineProperty(exports, "LoadStrikeAccessibilityScanner", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeAccessibilityScanner; } });
15
19
  Object.defineProperty(exports, "LoadStrikeBrowserWebVitals", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeBrowserWebVitals; } });
20
+ Object.defineProperty(exports, "LoadStrikeBrowserWebVitalsCollector", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeBrowserWebVitalsCollector; } });
16
21
  Object.defineProperty(exports, "LoadStrikePluginData", { enumerable: true, get: function () { return runtime_js_1.LoadStrikePluginData; } });
17
22
  Object.defineProperty(exports, "LoadStrikePluginDataTable", { enumerable: true, get: function () { return runtime_js_1.LoadStrikePluginDataTable; } });
18
23
  Object.defineProperty(exports, "LoadStrikeNodeType", { enumerable: true, get: function () { return runtime_js_1.LoadStrikeNodeType; } });
@@ -55,20 +60,40 @@ Object.defineProperty(exports, "SqsEndpointDefinition", { enumerable: true, get:
55
60
  Object.defineProperty(exports, "DelegateStreamEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.DelegateStreamEndpointDefinition; } });
56
61
  Object.defineProperty(exports, "PushDiffusionEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.PushDiffusionEndpointDefinition; } });
57
62
  Object.defineProperty(exports, "GrpcEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.GrpcEndpointDefinition; } });
63
+ Object.defineProperty(exports, "GrpcMethodTypes", { enumerable: true, get: function () { return transports_js_1.GrpcMethodTypes; } });
64
+ Object.defineProperty(exports, "GrpcNativeClientOptions", { enumerable: true, get: function () { return transports_js_1.GrpcNativeClientOptions; } });
65
+ Object.defineProperty(exports, "GrpcStatusMapper", { enumerable: true, get: function () { return transports_js_1.GrpcStatusMapper; } });
66
+ Object.defineProperty(exports, "ProtocolMetricSnapshot", { enumerable: true, get: function () { return transports_js_1.ProtocolMetricSnapshot; } });
58
67
  Object.defineProperty(exports, "WebSocketEndpointDefinition", { enumerable: true, get: function () { return transports_js_1.WebSocketEndpointDefinition; } });
68
+ Object.defineProperty(exports, "WebSocketExpectedMessage", { enumerable: true, get: function () { return transports_js_1.WebSocketExpectedMessage; } });
69
+ Object.defineProperty(exports, "WebSocketMessageSpec", { enumerable: true, get: function () { return transports_js_1.WebSocketMessageSpec; } });
70
+ Object.defineProperty(exports, "WebSocketNativeClientOptions", { enumerable: true, get: function () { return transports_js_1.WebSocketNativeClientOptions; } });
71
+ Object.defineProperty(exports, "WebSocketReconnectPolicy", { enumerable: true, get: function () { return transports_js_1.WebSocketReconnectPolicy; } });
59
72
  Object.defineProperty(exports, "HttpOAuth2ClientCredentialsOptions", { enumerable: true, get: function () { return transports_js_1.HttpOAuth2ClientCredentialsOptions; } });
60
73
  Object.defineProperty(exports, "HttpAuthOptions", { enumerable: true, get: function () { return transports_js_1.HttpAuthOptions; } });
61
74
  var sinks_js_1 = require("./sinks.js");
62
75
  Object.defineProperty(exports, "DatadogReportingSink", { enumerable: true, get: function () { return sinks_js_1.DatadogReportingSink; } });
63
76
  Object.defineProperty(exports, "DatadogReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.DatadogReportingSinkOptions; } });
77
+ Object.defineProperty(exports, "DogStatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.DogStatsDReportingSink; } });
78
+ Object.defineProperty(exports, "CloudWatchReportingSink", { enumerable: true, get: function () { return sinks_js_1.CloudWatchReportingSink; } });
79
+ Object.defineProperty(exports, "DynatraceReportingSink", { enumerable: true, get: function () { return sinks_js_1.DynatraceReportingSink; } });
80
+ Object.defineProperty(exports, "ElasticsearchReportingSink", { enumerable: true, get: function () { return sinks_js_1.ElasticsearchReportingSink; } });
64
81
  Object.defineProperty(exports, "GrafanaLokiReportingSink", { enumerable: true, get: function () { return sinks_js_1.GrafanaLokiReportingSink; } });
65
82
  Object.defineProperty(exports, "GrafanaLokiReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.GrafanaLokiReportingSinkOptions; } });
83
+ Object.defineProperty(exports, "GenericWebhookReportingSink", { enumerable: true, get: function () { return sinks_js_1.GenericWebhookReportingSink; } });
66
84
  Object.defineProperty(exports, "InfluxDbReportingSink", { enumerable: true, get: function () { return sinks_js_1.InfluxDbReportingSink; } });
67
85
  Object.defineProperty(exports, "InfluxDbReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.InfluxDbReportingSinkOptions; } });
86
+ Object.defineProperty(exports, "JsonlFileReportingSink", { enumerable: true, get: function () { return sinks_js_1.JsonlFileReportingSink; } });
87
+ Object.defineProperty(exports, "KafkaReportingSink", { enumerable: true, get: function () { return sinks_js_1.KafkaReportingSink; } });
88
+ Object.defineProperty(exports, "NetdataStatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.NetdataStatsDReportingSink; } });
89
+ Object.defineProperty(exports, "NewRelicReportingSink", { enumerable: true, get: function () { return sinks_js_1.NewRelicReportingSink; } });
68
90
  Object.defineProperty(exports, "OtelCollectorReportingSink", { enumerable: true, get: function () { return sinks_js_1.OtelCollectorReportingSink; } });
69
91
  Object.defineProperty(exports, "OtelCollectorReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.OtelCollectorReportingSinkOptions; } });
92
+ Object.defineProperty(exports, "OpenSearchReportingSink", { enumerable: true, get: function () { return sinks_js_1.OpenSearchReportingSink; } });
70
93
  Object.defineProperty(exports, "PortalReportingSink", { enumerable: true, get: function () { return sinks_js_1.PortalReportingSink; } });
94
+ Object.defineProperty(exports, "PrometheusRemoteWriteReportingSink", { enumerable: true, get: function () { return sinks_js_1.PrometheusRemoteWriteReportingSink; } });
71
95
  Object.defineProperty(exports, "SplunkReportingSink", { enumerable: true, get: function () { return sinks_js_1.SplunkReportingSink; } });
72
96
  Object.defineProperty(exports, "SplunkReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.SplunkReportingSinkOptions; } });
97
+ Object.defineProperty(exports, "StatsDReportingSink", { enumerable: true, get: function () { return sinks_js_1.StatsDReportingSink; } });
73
98
  Object.defineProperty(exports, "TimescaleDbReportingSink", { enumerable: true, get: function () { return sinks_js_1.TimescaleDbReportingSink; } });
74
99
  Object.defineProperty(exports, "TimescaleDbReportingSinkOptions", { enumerable: true, get: function () { return sinks_js_1.TimescaleDbReportingSinkOptions; } });
package/dist/cjs/local.js CHANGED
@@ -207,7 +207,9 @@ class LoadStrikeLocalClient {
207
207
  NodeType: stringOrDefault(context.NodeType, nodeType),
208
208
  MachineName: machineName,
209
209
  EnvironmentClassification: environmentClassification,
210
- DeviceHash: computedDeviceHash
210
+ DeviceHash: computedDeviceHash,
211
+ Scenarios: buildLicenseScenarioMetadata(request),
212
+ ScenarioSourceAnalysis: buildScenarioSourceAnalysisMetadata(request)
211
213
  };
212
214
  const controller = new AbortController();
213
215
  const timer = setTimeout(() => controller.abort(), this.licenseValidationTimeoutMs);
@@ -1578,6 +1580,74 @@ function computeScenarioRequestCount(scenario) {
1578
1580
  }
1579
1581
  return Math.max(total, 0);
1580
1582
  }
1583
+ function buildLicenseScenarioMetadata(request) {
1584
+ const scenarios = Array.isArray(request.Scenarios) ? request.Scenarios : [];
1585
+ return scenarios.map((item) => {
1586
+ const scenario = asRecord(item);
1587
+ const scenarioName = stringOrDefault(scenario.ScenarioName ?? scenario.scenarioName ?? scenario.Name ?? scenario.name, "");
1588
+ return {
1589
+ Name: scenarioName,
1590
+ ScenarioName: scenarioName,
1591
+ Simulations: normalizeLicenseSimulations(scenario.LoadSimulations)
1592
+ };
1593
+ });
1594
+ }
1595
+ function normalizeLicenseSimulations(value) {
1596
+ const simulations = Array.isArray(value) ? value : [];
1597
+ return simulations.map((item) => {
1598
+ const simulation = asRecord(item);
1599
+ return {
1600
+ Kind: stringOrDefault(simulation.Kind ?? simulation.kind, ""),
1601
+ Rate: positiveOrUndefined(simulation.Rate ?? simulation.rate),
1602
+ MinRate: positiveOrUndefined(simulation.MinRate ?? simulation.minRate),
1603
+ MaxRate: positiveOrUndefined(simulation.MaxRate ?? simulation.maxRate),
1604
+ Copies: positiveOrUndefined(simulation.Copies ?? simulation.copies),
1605
+ Iterations: positiveOrUndefined(simulation.Iterations ?? simulation.iterations),
1606
+ IntervalSeconds: positiveNumberOrUndefined(simulation.IntervalSeconds ?? simulation.intervalSeconds),
1607
+ DurationSeconds: positiveNumberOrUndefined(simulation.DurationSeconds ?? simulation.durationSeconds ?? simulation.DuringSeconds ?? simulation.duringSeconds),
1608
+ Children: normalizeLicenseSimulations(simulation.Children ?? simulation.children)
1609
+ };
1610
+ });
1611
+ }
1612
+ function buildScenarioSourceAnalysisMetadata(request) {
1613
+ const scenarios = Array.isArray(request.Scenarios) ? request.Scenarios : [];
1614
+ return scenarios.map((item) => {
1615
+ const scenario = asRecord(item);
1616
+ const source = asRecord(scenario.ScenarioSourceAnalysis ?? scenario.scenarioSourceAnalysis ?? scenario.SourceAnalysis);
1617
+ const scenarioName = stringOrDefault(source.ScenarioName ?? source.scenarioName ?? scenario.Name ?? scenario.name, "");
1618
+ const scenarioBlockLineCount = Math.max(asInt(source.ScenarioBlockLineCount ?? source.scenarioBlockLineCount), 1);
1619
+ const localMethodLineCount = Math.max(asInt(source.LocalMethodLineCount
1620
+ ?? source.localMethodLineCount
1621
+ ?? source.TransitiveLocalMethodLineCount
1622
+ ?? source.transitiveLocalMethodLineCount), 0);
1623
+ const totalCountedLineCount = Math.max(asInt(source.TotalCountedLineCount ?? source.totalCountedLineCount), scenarioBlockLineCount + localMethodLineCount);
1624
+ const warningsValue = source.Warnings ?? source.warnings;
1625
+ const warnings = Array.isArray(warningsValue)
1626
+ ? warningsValue.map((warning) => stringOrDefault(warning, "")).filter((warning) => warning.length > 0)
1627
+ : ["Scenario source analysis was synthesized from scenario metadata."];
1628
+ return {
1629
+ ScenarioName: scenarioName,
1630
+ Language: stringOrDefault(source.Language ?? source.language, "TypeScript/JavaScript"),
1631
+ AnalyzerVersion: stringOrDefault(source.AnalyzerVersion ?? source.analyzerVersion, "function-source-v1"),
1632
+ ScenarioBlockLineCount: scenarioBlockLineCount,
1633
+ LocalMethodLineCount: localMethodLineCount,
1634
+ TotalCountedLineCount: totalCountedLineCount,
1635
+ IgnoredExternalCallCount: Math.max(asInt(source.IgnoredExternalCallCount
1636
+ ?? source.ignoredExternalCallCount
1637
+ ?? source.IgnoredLibraryCallCount
1638
+ ?? source.ignoredLibraryCallCount), 0),
1639
+ Warnings: warnings
1640
+ };
1641
+ });
1642
+ }
1643
+ function positiveOrUndefined(value) {
1644
+ const normalized = asInt(value);
1645
+ return normalized > 0 ? normalized : undefined;
1646
+ }
1647
+ function positiveNumberOrUndefined(value) {
1648
+ const normalized = asNumber(value);
1649
+ return normalized > 0 ? normalized : undefined;
1650
+ }
1581
1651
  function buildNodeStatsContract(context, createdUtc, completedUtc, values) {
1582
1652
  const durationMs = Math.max(completedUtc.getTime() - createdUtc.getTime(), 0);
1583
1653
  return {
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.__loadstrikeTestExports = exports.LoadStrikeRunner = exports.LoadStrikeTrafficMix = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibility = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeThreshold = exports.LoadStrikeMetric = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeSimulation = exports.LoadStrikeStep = exports.LoadStrikeResponse = exports.LoadStrikePluginData = exports.LoadStrikePluginDataTable = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = void 0;
6
+ exports.__loadstrikeTestExports = exports.LoadStrikeRunner = exports.LoadStrikeTrafficMix = exports.LoadStrikeScenarioShare = exports.LoadStrikeScenario = exports.LoadStrikeBrowserWebVitals = exports.LoadStrikeAccessibility = exports.LoadStrikeBrowserWebVitalsCollector = exports.LoadStrikeAccessibilityAdapters = exports.LoadStrikeAccessibilityScanner = exports.LoadStrikeAccessibilityCiGate = exports.LoadStrikeAccessibilityBaseline = exports.LoadStrikeContext = exports.ScenarioTrackingExtensions = exports.CrossPlatformScenarioConfigurator = exports.LoadStrikeThreshold = exports.LoadStrikeMetric = exports.LoadStrikeGauge = exports.LoadStrikeCounter = exports.LoadStrikeSimulation = exports.LoadStrikeStep = exports.LoadStrikeResponse = exports.LoadStrikePluginData = exports.LoadStrikePluginDataTable = exports.CrossPlatformTrackingConfiguration = exports.LoadStrikeOperationType = exports.LoadStrikeScenarioOperation = exports.LoadStrikeLogLevel = exports.LoadStrikeReportFormat = exports.LoadStrikeNodeType = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_crypto_1 = require("node:crypto");
9
9
  const node_os_1 = __importDefault(require("node:os"));
@@ -1624,6 +1624,174 @@ class LoadStrikeContext {
1624
1624
  exports.LoadStrikeContext = LoadStrikeContext;
1625
1625
  const ACCESSIBILITY_TESTING_FEATURE = "testing.accessibility";
1626
1626
  const BROWSER_WEB_VITALS_FEATURE = "testing.browser_web_vitals";
1627
+ class LoadStrikeAccessibilityBaseline {
1628
+ constructor(initial = {}) {
1629
+ const source = qualityRecord(initial);
1630
+ this.allowedRuleIds = qualityStringArray(qualityValue(source, "allowedRuleIds", "AllowedRuleIds"));
1631
+ this.AllowedRuleIds = this.allowedRuleIds;
1632
+ this.maxNewViolations = Math.max(0, qualityNumber(source, 0, "maxNewViolations", "MaxNewViolations"));
1633
+ this.MaxNewViolations = this.maxNewViolations;
1634
+ }
1635
+ compare(result) {
1636
+ const violations = Array.isArray(result?.violations) ? result.violations : [];
1637
+ const allowed = new Set(this.allowedRuleIds.map((value) => value.toLowerCase()));
1638
+ const newViolations = violations.filter((violation) => !allowed.has(String(violation.ruleId ?? "").toLowerCase()));
1639
+ const newRuleIds = Array.from(new Set(newViolations
1640
+ .map((violation) => String(violation.ruleId ?? "").trim())
1641
+ .filter(Boolean)));
1642
+ return {
1643
+ passed: newViolations.length <= this.maxNewViolations,
1644
+ Passed: newViolations.length <= this.maxNewViolations,
1645
+ newViolationCount: newViolations.length,
1646
+ NewViolationCount: newViolations.length,
1647
+ newRuleIds,
1648
+ NewRuleIds: newRuleIds
1649
+ };
1650
+ }
1651
+ Compare(result) {
1652
+ return this.compare(result);
1653
+ }
1654
+ }
1655
+ exports.LoadStrikeAccessibilityBaseline = LoadStrikeAccessibilityBaseline;
1656
+ class LoadStrikeAccessibilityCiGate {
1657
+ constructor(initial = {}) {
1658
+ const source = qualityRecord(initial);
1659
+ this.maxViolations = qualityOptionalNumber(source, "maxViolations", "MaxViolations");
1660
+ this.MaxViolations = this.maxViolations;
1661
+ this.maxCriticalViolations = qualityOptionalNumber(source, "maxCriticalViolations", "MaxCriticalViolations");
1662
+ this.MaxCriticalViolations = this.maxCriticalViolations;
1663
+ this.maxSeriousViolations = qualityOptionalNumber(source, "maxSeriousViolations", "MaxSeriousViolations");
1664
+ this.MaxSeriousViolations = this.maxSeriousViolations;
1665
+ const baseline = qualityValue(source, "baseline", "Baseline");
1666
+ this.baseline = baseline instanceof LoadStrikeAccessibilityBaseline
1667
+ ? baseline
1668
+ : (baseline && typeof baseline === "object" ? new LoadStrikeAccessibilityBaseline(baseline) : undefined);
1669
+ this.Baseline = this.baseline;
1670
+ }
1671
+ evaluate(result) {
1672
+ const normalized = attachAccessibilityCounts(result);
1673
+ const reasons = [];
1674
+ if (this.maxViolations != null && (normalized.totalViolations ?? 0) > this.maxViolations) {
1675
+ reasons.push(`total accessibility violations ${normalized.totalViolations} exceeded ${this.maxViolations}.`);
1676
+ }
1677
+ if (this.maxCriticalViolations != null && (normalized.criticalViolations ?? 0) > this.maxCriticalViolations) {
1678
+ reasons.push(`critical accessibility violations ${normalized.criticalViolations} exceeded ${this.maxCriticalViolations}.`);
1679
+ }
1680
+ if (this.maxSeriousViolations != null && (normalized.seriousViolations ?? 0) > this.maxSeriousViolations) {
1681
+ reasons.push(`serious accessibility violations ${normalized.seriousViolations} exceeded ${this.maxSeriousViolations}.`);
1682
+ }
1683
+ if (this.baseline) {
1684
+ const baseline = this.baseline.compare(normalized);
1685
+ if (!baseline.passed) {
1686
+ reasons.push(`baseline found ${baseline.newViolationCount} new accessibility violation(s).`);
1687
+ }
1688
+ }
1689
+ return {
1690
+ passed: reasons.length === 0,
1691
+ Passed: reasons.length === 0,
1692
+ reasons,
1693
+ Reasons: reasons
1694
+ };
1695
+ }
1696
+ Evaluate(result) {
1697
+ return this.evaluate(result);
1698
+ }
1699
+ }
1700
+ exports.LoadStrikeAccessibilityCiGate = LoadStrikeAccessibilityCiGate;
1701
+ class LoadStrikeAccessibilityScanner {
1702
+ static scanHtml(options, html) {
1703
+ validateAbsoluteUrl(options?.url, "Accessibility check URL");
1704
+ const source = String(html ?? "");
1705
+ const violations = [];
1706
+ if (!/<html\b[^>]*\blang\s*=\s*["'][^"']+["']/i.test(source)) {
1707
+ violations.push(createAccessibilityViolation("html-has-lang", "serious", "The html element should declare a non-empty language."));
1708
+ }
1709
+ if (/<title\b[^>]*>\s*<\/title>/i.test(source) || !/<title\b/i.test(source)) {
1710
+ violations.push(createAccessibilityViolation("document-title", "serious", "The page should provide a useful title."));
1711
+ }
1712
+ for (const match of source.matchAll(/<img\b(?![^>]*\balt\s*=)[^>]*>/gi)) {
1713
+ violations.push(createAccessibilityViolation("image-alt", "serious", "Images should provide alternate text.", match[0]));
1714
+ }
1715
+ for (const match of source.matchAll(/<button\b(?![^>]*\baria-label\s*=)[^>]*>\s*<\/button>/gi)) {
1716
+ violations.push(createAccessibilityViolation("button-name", "critical", "Buttons should have an accessible name.", match[0]));
1717
+ }
1718
+ for (const match of source.matchAll(/<input\b(?![^>]*\baria-label\s*=)[^>]*\bid\s*=\s*["']?([a-zA-Z0-9_-]+)["']?[^>]*>/gi)) {
1719
+ const id = match[1] ?? "";
1720
+ const labelRegex = new RegExp(`<label\\b[^>]*\\bfor\\s*=\\s*["']?${escapeRegExp(id)}["']?[^>]*>`, "i");
1721
+ if (!labelRegex.test(source)) {
1722
+ violations.push(createAccessibilityViolation("label", "critical", "Form fields should have labels.", match[0]));
1723
+ }
1724
+ }
1725
+ const focusOrder = [...source.matchAll(/<(a|button|input|select|textarea)\b[^>]*>/gi)]
1726
+ .map((match) => match[0]);
1727
+ const visibleFocusFailures = focusOrder.filter((element) => /outline\s*:\s*(none|0)\b/i.test(element)).length;
1728
+ const missingSkipLinkCount = /href\s*=\s*["']#(main|content)["']/i.test(source) ? 0 : 1;
1729
+ if (visibleFocusFailures > 0) {
1730
+ violations.push(createAccessibilityViolation("focus-visible", "serious", "Keyboard focus indicators should remain visible."));
1731
+ }
1732
+ if (missingSkipLinkCount > 0) {
1733
+ violations.push(createAccessibilityViolation("skip-link", "moderate", "Pages should provide a skip link to the main content."));
1734
+ }
1735
+ return attachAccessibilityCounts({
1736
+ url: options.url,
1737
+ violations,
1738
+ keyboardFocus: {
1739
+ tabbableElementCount: focusOrder.length,
1740
+ visibleFocusFailures,
1741
+ missingSkipLinkCount,
1742
+ focusOrder
1743
+ }
1744
+ });
1745
+ }
1746
+ static ScanHtml(options, html) {
1747
+ return LoadStrikeAccessibilityScanner.scanHtml(options, html);
1748
+ }
1749
+ }
1750
+ exports.LoadStrikeAccessibilityScanner = LoadStrikeAccessibilityScanner;
1751
+ class LoadStrikeAccessibilityAdapters {
1752
+ static async fromPlaywrightPageAsync(options, page) {
1753
+ const html = await readBrowserContent(page, ["ContentAsync", "contentAsync", "content"]);
1754
+ return LoadStrikeAccessibilityScanner.scanHtml(options, html);
1755
+ }
1756
+ static FromPlaywrightPageAsync(options, page) {
1757
+ return LoadStrikeAccessibilityAdapters.fromPlaywrightPageAsync(options, page);
1758
+ }
1759
+ static fromSeleniumDriver(options, driver) {
1760
+ const record = qualityRecord(driver);
1761
+ const html = String(qualityValue(record, "PageSource", "pageSource") ?? "");
1762
+ return LoadStrikeAccessibilityScanner.scanHtml(options, html);
1763
+ }
1764
+ static FromSeleniumDriver(options, driver) {
1765
+ return LoadStrikeAccessibilityAdapters.fromSeleniumDriver(options, driver);
1766
+ }
1767
+ }
1768
+ exports.LoadStrikeAccessibilityAdapters = LoadStrikeAccessibilityAdapters;
1769
+ class LoadStrikeBrowserWebVitalsCollector {
1770
+ static fromPerformanceSnapshot(options, snapshot) {
1771
+ validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
1772
+ return normalizeWebVitalsSnapshot(options.url, snapshot);
1773
+ }
1774
+ static FromPerformanceSnapshot(options, snapshot) {
1775
+ return LoadStrikeBrowserWebVitalsCollector.fromPerformanceSnapshot(options, snapshot);
1776
+ }
1777
+ static async fromPlaywrightPageAsync(options, page) {
1778
+ validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
1779
+ const snapshot = await invokeBrowserMethod(page, ["EvaluateAsync", "evaluate"], WEB_VITALS_SCRIPT);
1780
+ return normalizeWebVitalsSnapshot(options.url, snapshot);
1781
+ }
1782
+ static FromPlaywrightPageAsync(options, page) {
1783
+ return LoadStrikeBrowserWebVitalsCollector.fromPlaywrightPageAsync(options, page);
1784
+ }
1785
+ static fromSeleniumDriver(options, driver) {
1786
+ validateAbsoluteUrl(options?.url, "Browser Web Vitals URL");
1787
+ const snapshot = invokeBrowserMethodSync(driver, ["ExecuteScript", "executeScript"], WEB_VITALS_SCRIPT);
1788
+ return normalizeWebVitalsSnapshot(options.url, snapshot);
1789
+ }
1790
+ static FromSeleniumDriver(options, driver) {
1791
+ return LoadStrikeBrowserWebVitalsCollector.fromSeleniumDriver(options, driver);
1792
+ }
1793
+ }
1794
+ exports.LoadStrikeBrowserWebVitalsCollector = LoadStrikeBrowserWebVitalsCollector;
1627
1795
  class LoadStrikeAccessibility {
1628
1796
  static createScenario(name, options, check) {
1629
1797
  if (typeof name !== "string" || !name.trim()) {
@@ -1674,6 +1842,129 @@ class LoadStrikeBrowserWebVitals {
1674
1842
  }
1675
1843
  }
1676
1844
  exports.LoadStrikeBrowserWebVitals = LoadStrikeBrowserWebVitals;
1845
+ const WEB_VITALS_SCRIPT = `
1846
+ (() => {
1847
+ const navigation = performance.getEntriesByType("navigation")[0];
1848
+ const paint = performance.getEntriesByType("paint");
1849
+ const fcp = paint.find((entry) => entry.name === "first-contentful-paint");
1850
+ return {
1851
+ largestContentfulPaintMs: globalThis.__loadstrikeLcp ?? 0,
1852
+ interactionToNextPaintMs: globalThis.__loadstrikeInp ?? 0,
1853
+ cumulativeLayoutShift: globalThis.__loadstrikeCls ?? 0,
1854
+ firstContentfulPaintMs: fcp ? fcp.startTime : 0,
1855
+ timeToFirstByteMs: navigation ? navigation.responseStart : 0
1856
+ };
1857
+ })()
1858
+ `;
1859
+ function createAccessibilityViolation(ruleId, impact, description, target) {
1860
+ return {
1861
+ ruleId,
1862
+ impact,
1863
+ description,
1864
+ helpUrl: `https://www.w3.org/WAI/WCAG22/quickref/?versions=2.2#${ruleId}`,
1865
+ targets: target ? [target] : []
1866
+ };
1867
+ }
1868
+ function attachAccessibilityCounts(result) {
1869
+ const violations = Array.isArray(result?.violations) ? result.violations : [];
1870
+ return {
1871
+ ...result,
1872
+ violations,
1873
+ totalViolations: violations.length,
1874
+ criticalViolations: countAccessibilityImpact(violations, "critical"),
1875
+ seriousViolations: countAccessibilityImpact(violations, "serious"),
1876
+ moderateViolations: countAccessibilityImpact(violations, "moderate"),
1877
+ minorViolations: countAccessibilityImpact(violations, "minor")
1878
+ };
1879
+ }
1880
+ function qualityRecord(value) {
1881
+ return value && typeof value === "object" && !Array.isArray(value)
1882
+ ? value
1883
+ : {};
1884
+ }
1885
+ function qualityValue(record, ...keys) {
1886
+ for (const key of keys) {
1887
+ if (key in record) {
1888
+ return record[key];
1889
+ }
1890
+ const normalized = key.toLowerCase();
1891
+ const match = Object.entries(record).find(([entryKey]) => entryKey.toLowerCase() === normalized);
1892
+ if (match) {
1893
+ return match[1];
1894
+ }
1895
+ }
1896
+ return undefined;
1897
+ }
1898
+ function qualityStringArray(value) {
1899
+ if (!Array.isArray(value)) {
1900
+ return [];
1901
+ }
1902
+ return value.map((entry) => String(entry ?? "").trim()).filter(Boolean);
1903
+ }
1904
+ function qualityNumber(record, fallback, ...keys) {
1905
+ const value = qualityValue(record, ...keys);
1906
+ if (typeof value === "number" && Number.isFinite(value)) {
1907
+ return value;
1908
+ }
1909
+ if (typeof value === "string" && value.trim()) {
1910
+ const parsed = Number(value);
1911
+ if (Number.isFinite(parsed)) {
1912
+ return parsed;
1913
+ }
1914
+ }
1915
+ return fallback;
1916
+ }
1917
+ function qualityOptionalNumber(record, ...keys) {
1918
+ const value = qualityValue(record, ...keys);
1919
+ if (typeof value === "number" && Number.isFinite(value)) {
1920
+ return value;
1921
+ }
1922
+ if (typeof value === "string" && value.trim()) {
1923
+ const parsed = Number(value);
1924
+ if (Number.isFinite(parsed)) {
1925
+ return parsed;
1926
+ }
1927
+ }
1928
+ return undefined;
1929
+ }
1930
+ function escapeRegExp(value) {
1931
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1932
+ }
1933
+ async function readBrowserContent(target, methodNames) {
1934
+ const value = await invokeBrowserMethod(target, methodNames);
1935
+ return String(value ?? "");
1936
+ }
1937
+ async function invokeBrowserMethod(target, methodNames, ...args) {
1938
+ const record = qualityRecord(target);
1939
+ for (const name of methodNames) {
1940
+ const method = record[name];
1941
+ if (typeof method === "function") {
1942
+ return await method.apply(target, args);
1943
+ }
1944
+ }
1945
+ throw new Error(`Browser object does not expose ${methodNames.join(" or ")}.`);
1946
+ }
1947
+ function invokeBrowserMethodSync(target, methodNames, ...args) {
1948
+ const record = qualityRecord(target);
1949
+ for (const name of methodNames) {
1950
+ const method = record[name];
1951
+ if (typeof method === "function") {
1952
+ return method.apply(target, args);
1953
+ }
1954
+ }
1955
+ throw new Error(`Browser object does not expose ${methodNames.join(" or ")}.`);
1956
+ }
1957
+ function normalizeWebVitalsSnapshot(url, snapshot) {
1958
+ const source = qualityRecord(snapshot);
1959
+ return {
1960
+ url,
1961
+ largestContentfulPaintMs: qualityNumber(source, 0, "largestContentfulPaintMs", "LargestContentfulPaintMs", "LCP", "lcp"),
1962
+ interactionToNextPaintMs: qualityNumber(source, 0, "interactionToNextPaintMs", "InteractionToNextPaintMs", "INP", "inp"),
1963
+ cumulativeLayoutShift: qualityNumber(source, 0, "cumulativeLayoutShift", "CumulativeLayoutShift", "CLS", "cls"),
1964
+ firstContentfulPaintMs: qualityNumber(source, 0, "firstContentfulPaintMs", "FirstContentfulPaintMs", "FCP", "fcp"),
1965
+ timeToFirstByteMs: qualityNumber(source, 0, "timeToFirstByteMs", "TimeToFirstByteMs", "TTFB", "ttfb")
1966
+ };
1967
+ }
1677
1968
  function validateAbsoluteUrl(value, label) {
1678
1969
  if (typeof value !== "string" || !value.trim()) {
1679
1970
  throw new Error(`${label} must be provided.`);
@@ -1964,6 +2255,26 @@ class LoadStrikeScenario {
1964
2255
  __loadStrikeInternalLicenseFeatures() {
1965
2256
  return [...this.internalLicenseFeatures];
1966
2257
  }
2258
+ __loadStrikeScenarioSourceAnalysis() {
2259
+ const source = this.runHandler.toString();
2260
+ const lines = source
2261
+ .split(/\r?\n/)
2262
+ .map((line) => line.trim())
2263
+ .filter((line) => line.length > 0 && !line.startsWith("//"));
2264
+ const lineCount = Math.max(lines.length, 1);
2265
+ return {
2266
+ ScenarioName: this.name,
2267
+ Language: "TypeScript/JavaScript",
2268
+ AnalyzerVersion: "function-source-v1",
2269
+ ScenarioBlockLineCount: lineCount,
2270
+ LocalMethodLineCount: 0,
2271
+ TotalCountedLineCount: lineCount,
2272
+ IgnoredExternalCallCount: 0,
2273
+ Warnings: [
2274
+ "Function-source analysis counts the scenario handler source available at runtime; imported library implementation lines are ignored."
2275
+ ]
2276
+ };
2277
+ }
1967
2278
  __loadStrikeWithInternalLicenseFeatures(...features) {
1968
2279
  const merged = Array.from(new Set([...this.internalLicenseFeatures, ...normalizeStringArray(features)]));
1969
2280
  return new LoadStrikeScenario(this.name, this.runHandler, this.initHandler, this.cleanHandler, this.loadSimulations, this.thresholds, this.trackingConfiguration, this.maxFailCount, this.withoutWarmUpValue, this.warmUpDurationSeconds, this.weight, this.restartIterationOnFail, merged);
@@ -8061,7 +8372,8 @@ function buildLicenseValidationPayload(options, scenarios) {
8061
8372
  Weight: scenario.getWeight(),
8062
8373
  LoadSimulations: [...scenario.getSimulations()],
8063
8374
  Thresholds: [...scenario.getThresholds()],
8064
- Tracking: scenario.getTrackingConfiguration() ?? {}
8375
+ Tracking: scenario.getTrackingConfiguration() ?? {},
8376
+ ScenarioSourceAnalysis: scenario.__loadStrikeScenarioSourceAnalysis()
8065
8377
  };
8066
8378
  const internalLicenseFeatures = scenario.__loadStrikeInternalLicenseFeatures();
8067
8379
  if (internalLicenseFeatures.length > 0) {