feat: implement js runtime provider and remove old script service

This commit is contained in:
Udhay-Adithya
2025-09-09 17:30:16 +05:30
parent cea7bce839
commit 9d47d0b2a5
7 changed files with 386 additions and 408 deletions

View File

@@ -19,7 +19,6 @@ void main() async {
var settingsModel = await getSettingsFromSharedPrefs();
var onboardingStatus = await getOnboardingStatusFromSharedPrefs();
initializeJsRuntime();
final initStatus = await initApp(
kIsDesktop,
settingsModel: settingsModel,

View File

@@ -7,7 +7,6 @@ import 'providers.dart';
import '../models/models.dart';
import '../services/services.dart';
import '../utils/utils.dart';
import '../models/terminal_models.dart';
final selectedIdStateProvider = StateProvider<String?>((ref) => null);
@@ -321,7 +320,9 @@ class CollectionStateNotifier
RequestModel executionRequestModel = requestModel!.copyWith();
if (!requestModel.preRequestScript.isNullOrEmpty()) {
executionRequestModel = await handlePreRequestScript(
executionRequestModel = await ref
.read(jsRuntimeNotifierProvider.notifier)
.handlePreRequestScript(
executionRequestModel,
originalEnvironmentModel,
(envModel, updatedValues) {
@@ -525,7 +526,9 @@ class CollectionStateNotifier
.addHistoryRequest(historyModel!);
if (!requestModel.postRequestScript.isNullOrEmpty()) {
newRequestModel = await handlePostResponseScript(
newRequestModel = await ref
.read(jsRuntimeNotifierProvider.notifier)
.handlePostResponseScript(
newRequestModel,
originalEnvironmentModel,
(envModel, updatedValues) {

View File

@@ -0,0 +1,379 @@
// ignore_for_file: avoid_print
import 'dart:convert';
import 'dart:developer';
import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/services.dart';
import 'package:flutter_js/flutter_js.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/models.dart';
import '../utils/utils.dart';
import '../providers/terminal_providers.dart';
class JsRuntimeState {
const JsRuntimeState({
this.initialized = false,
this.lastError,
this.executedScriptCount = 0,
});
final bool initialized;
final String? lastError;
final int executedScriptCount;
JsRuntimeState copyWith({
bool? initialized,
String? lastError,
int? executedScriptCount,
}) =>
JsRuntimeState(
initialized: initialized ?? this.initialized,
lastError: lastError ?? this.lastError,
executedScriptCount: executedScriptCount ?? this.executedScriptCount,
);
}
final jsRuntimeNotifierProvider =
StateNotifierProvider<JsRuntimeNotifier, JsRuntimeState>((ref) {
final notifier = JsRuntimeNotifier(ref);
notifier._initialize();
return notifier;
});
class JsRuntimeNotifier extends StateNotifier<JsRuntimeState> {
JsRuntimeNotifier(this.ref) : super(const JsRuntimeState());
final Ref ref;
late final JavascriptRuntime _runtime;
void _initialize() {
if (state.initialized) return;
_runtime = getJavascriptRuntime();
_setupJsBridge();
state = state.copyWith(initialized: true);
}
@override
void dispose() {
// Guard: runtime may already be disposed by underlying provider disposal
try {
if (state.initialized) {
_runtime.dispose();
}
} catch (_) {
// swallow disposal errors
}
super.dispose();
}
JsEvalResult evaluate(String code) {
// If disposed, prevent usage
if (!mounted) {
throw StateError('JsRuntimeNotifier used after dispose');
}
try {
final res = _runtime.evaluate(code);
state = state.copyWith(
executedScriptCount: state.executedScriptCount + 1,
lastError: res.isError ? res.stringResult : state.lastError,
);
log(res.stringResult);
return res;
} on PlatformException catch (e) {
final msg = 'Platform ERROR: ${e.details}';
state = state.copyWith(lastError: msg);
log(msg);
rethrow;
}
}
Future<
({
HttpRequestModel updatedRequest,
Map<String, dynamic> updatedEnvironment
})> executePreRequestScript({
required RequestModel currentRequestModel,
required Map<String, dynamic> activeEnvironment,
}) async {
if ((currentRequestModel.preRequestScript ?? '').trim().isEmpty) {
return (
updatedRequest: currentRequestModel.httpRequestModel!,
updatedEnvironment: activeEnvironment,
);
}
final httpRequest = currentRequestModel.httpRequestModel;
final userScript = currentRequestModel.preRequestScript;
final requestJson = jsonEncode(httpRequest?.toJson());
final environmentJson = jsonEncode(activeEnvironment);
final dataInjection = '''
var injectedRequestJson = ${jsEscapeString(requestJson)};
var injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
var injectedResponseJson = null; // Not needed for pre-request
''';
final fullScript = '''
(function() {
$dataInjection
$kJSSetupScript
$userScript
return JSON.stringify({ request: request, environment: environment });
})();
''';
HttpRequestModel resultingRequest = httpRequest!;
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
try {
final res = _runtime.evaluate(fullScript);
state = state.copyWith(
executedScriptCount: state.executedScriptCount + 1,
lastError: res.isError ? res.stringResult : state.lastError,
);
if (res.isError) {
print('Pre-request script execution error: ${res.stringResult}');
} else if (res.stringResult.isNotEmpty) {
final decoded = jsonDecode(res.stringResult);
if (decoded is Map<String, dynamic>) {
if (decoded['request'] is Map) {
try {
resultingRequest = HttpRequestModel.fromJson(
Map<String, Object?>.from(decoded['request'] as Map),
);
} catch (e) {
print('Error deserializing modified request from script: $e');
}
}
if (decoded['environment'] is Map) {
resultingEnvironment =
Map<String, dynamic>.from(decoded['environment'] as Map);
}
}
}
} catch (e) {
final msg = 'Dart-level error during pre-request script execution: $e';
state = state.copyWith(lastError: msg);
print(msg);
}
return (
updatedRequest: resultingRequest,
updatedEnvironment: resultingEnvironment,
);
}
Future<
({
HttpResponseModel updatedResponse,
Map<String, dynamic> updatedEnvironment
})> executePostResponseScript({
required RequestModel currentRequestModel,
required Map<String, dynamic> activeEnvironment,
}) async {
if ((currentRequestModel.postRequestScript ?? '').trim().isEmpty) {
return (
updatedResponse: currentRequestModel.httpResponseModel!,
updatedEnvironment: activeEnvironment,
);
}
final httpRequest = currentRequestModel.httpRequestModel; // for future use
final httpResponse = currentRequestModel.httpResponseModel;
final userScript = currentRequestModel.postRequestScript;
final requestJson = jsonEncode(httpRequest?.toJson());
final responseJson = jsonEncode(httpResponse?.toJson());
final environmentJson = jsonEncode(activeEnvironment);
final dataInjection = '''
var injectedRequestJson = ${jsEscapeString(requestJson)};
var injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
var injectedResponseJson = ${jsEscapeString(responseJson)};
''';
final fullScript = '''
(function() {
$dataInjection
$kJSSetupScript
$userScript
return JSON.stringify({ response: response, environment: environment });
})();
''';
HttpResponseModel resultingResponse = httpResponse!;
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
try {
final res = _runtime.evaluate(fullScript);
state = state.copyWith(
executedScriptCount: state.executedScriptCount + 1,
lastError: res.isError ? res.stringResult : state.lastError,
);
if (res.isError) {
print('Post-response script execution error: ${res.stringResult}');
} else if (res.stringResult.isNotEmpty) {
final decoded = jsonDecode(res.stringResult);
if (decoded is Map<String, dynamic>) {
if (decoded['response'] is Map) {
try {
resultingResponse = HttpResponseModel.fromJson(
Map<String, Object?>.from(decoded['response'] as Map),
);
} catch (e) {
print('Error deserializing modified response from script: $e');
}
}
if (decoded['environment'] is Map) {
resultingEnvironment =
Map<String, dynamic>.from(decoded['environment'] as Map);
}
}
}
} catch (e) {
final msg = 'Dart-level error during post-response script execution: $e';
state = state.copyWith(lastError: msg);
print(msg);
}
return (
updatedResponse: resultingResponse,
updatedEnvironment: resultingEnvironment,
);
}
// High-level helpers (migrated from pre_post_script_utils) -----------------
Future<RequestModel> handlePreRequestScript(
RequestModel requestModel,
EnvironmentModel? originalEnvironmentModel,
void Function(EnvironmentModel, List<EnvironmentVariableModel>)? updateEnv,
) async {
final scriptResult = await executePreRequestScript(
currentRequestModel: requestModel,
activeEnvironment: originalEnvironmentModel?.toJson() ?? {},
);
final newRequestModel =
requestModel.copyWith(httpRequestModel: scriptResult.updatedRequest);
if (originalEnvironmentModel != null) {
final updatedEnvironmentMap = scriptResult.updatedEnvironment;
final List<EnvironmentVariableModel> newValues = [];
final Map<String, dynamic> mutableUpdatedEnv =
Map.from(updatedEnvironmentMap);
for (final originalVariable in originalEnvironmentModel.values) {
if (mutableUpdatedEnv.containsKey(originalVariable.key)) {
final dynamic newValue = mutableUpdatedEnv[originalVariable.key];
newValues.add(
originalVariable.copyWith(
value: newValue == null ? '' : newValue.toString(),
enabled: true,
),
);
mutableUpdatedEnv.remove(originalVariable.key);
}
}
for (final entry in mutableUpdatedEnv.entries) {
final dynamic newValue = entry.value;
newValues.add(
EnvironmentVariableModel(
key: entry.key,
value: newValue == null ? '' : newValue.toString(),
enabled: true,
type: EnvironmentVariableType.variable,
),
);
}
updateEnv?.call(originalEnvironmentModel, newValues);
} else {
if (scriptResult.updatedEnvironment.isNotEmpty) {
print(
'Warning: Pre-request script updated environment variables, but no active environment was selected to save them to.');
return requestModel;
}
return newRequestModel;
}
return newRequestModel;
}
Future<RequestModel> handlePostResponseScript(
RequestModel requestModel,
EnvironmentModel? originalEnvironmentModel,
void Function(EnvironmentModel, List<EnvironmentVariableModel>)? updateEnv,
) async {
final scriptResult = await executePostResponseScript(
currentRequestModel: requestModel,
activeEnvironment: originalEnvironmentModel?.toJson() ?? {'values': []},
);
final newRequestModel =
requestModel.copyWith(httpResponseModel: scriptResult.updatedResponse);
if (originalEnvironmentModel != null) {
final updatedEnvironmentMap = scriptResult.updatedEnvironment;
final List<EnvironmentVariableModel> newValues = [];
final Map<String, dynamic> mutableUpdatedEnv =
Map.from(updatedEnvironmentMap);
for (final originalVariable in originalEnvironmentModel.values) {
if (mutableUpdatedEnv.containsKey(originalVariable.key)) {
final dynamic newValue = mutableUpdatedEnv[originalVariable.key];
newValues.add(
originalVariable.copyWith(
value: newValue == null ? '' : newValue.toString(),
enabled: true,
),
);
mutableUpdatedEnv.remove(originalVariable.key);
}
}
for (final entry in mutableUpdatedEnv.entries) {
final dynamic newValue = entry.value;
newValues.add(
EnvironmentVariableModel(
key: entry.key,
value: newValue == null ? '' : newValue.toString(),
enabled: true,
type: EnvironmentVariableType.variable,
),
);
}
updateEnv?.call(originalEnvironmentModel, newValues);
} else {
if (scriptResult.updatedEnvironment.isNotEmpty) {
print(
'Warning: Post-response script updated environment variables, but no active environment was selected to save them to.');
}
return requestModel;
}
return newRequestModel;
}
void _setupJsBridge() {
_runtime.onMessage('consoleLog', (args) => _handleConsole('log', args));
_runtime.onMessage('consoleWarn', (args) => _handleConsole('warn', args));
_runtime.onMessage('consoleError', (args) => _handleConsole('error', args));
_runtime.onMessage('fatalError', (args) => _handleFatal(args));
}
void _handleConsole(String level, dynamic args) {
try {
final term = ref.read(terminalStateProvider.notifier);
final List<String> argList = (args is List)
? args.map((e) => e.toString()).toList()
: [args.toString()];
term.logJs(level: level, args: argList);
} catch (e) {
print('[JS ${level.toUpperCase()} HANDLER ERROR]: $args, Error: $e');
}
}
void _handleFatal(dynamic args) {
try {
final term = ref.read(terminalStateProvider.notifier);
if (args is Map<String, dynamic>) {
final message = args['message']?.toString() ?? 'Unknown fatal error';
final error = args['error']?.toString();
final stack = args['stack']?.toString();
term.logJs(
level: 'fatal',
args: [if (error != null) error, message],
stack: stack,
);
} else {
term.logJs(level: 'fatal', args: ['Malformed fatal payload', '$args']);
}
} catch (e) {
print('[JS FATAL ERROR decoding error]: $args, Error: $e');
}
}
}
// Helper to properly escape strings for JS embedding
String jsEscapeString(String s) => jsonEncode(s);

View File

@@ -5,3 +5,4 @@ export 'history_providers.dart';
export 'terminal_providers.dart';
export 'settings_providers.dart';
export 'ui_providers.dart';
export 'js_runtime_notifier.dart';

View File

@@ -1,275 +0,0 @@
// ignore_for_file: avoid_print
import 'dart:convert';
import 'dart:developer';
import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/services.dart';
import 'package:flutter_js/flutter_js.dart';
import '../models/models.dart';
import '../utils/utils.dart';
late JavascriptRuntime jsRuntime;
void initializeJsRuntime() {
jsRuntime = getJavascriptRuntime();
setupJsBridge();
}
void disposeJsRuntime() {
jsRuntime.dispose();
}
void evaluate(String code) {
try {
JsEvalResult jsResult = jsRuntime.evaluate(code);
log(jsResult.stringResult);
} on PlatformException catch (e) {
log('ERROR: ${e.details}');
}
}
// TODO: These log statements can be printed in a custom api dash terminal.
void setupJsBridge() {
jsRuntime.onMessage('consoleLog', (args) {
try {
if (args is List) {
print('[JS LOG]: ${args.map((e) => e.toString()).join(' ')}');
} else {
print('[JS LOG]: $args');
}
} catch (e) {
print('[JS LOG ERROR]: $args, Error: $e');
}
});
jsRuntime.onMessage('consoleWarn', (args) {
try {
if (args is List) {
print('[JS WARN]: ${args.map((e) => e.toString()).join(' ')}');
} else {
print('[JS WARN]: $args');
}
} catch (e) {
print('[JS WARN ERROR]: $args, Error: $e');
}
});
jsRuntime.onMessage('consoleError', (args) {
try {
if (args is List) {
print('[JS ERROR]: ${args.map((e) => e.toString()).join(' ')}');
} else {
print('[JS ERROR]: $args');
}
} catch (e) {
print('[JS ERROR ERROR]: $args, Error: $e');
}
});
jsRuntime.onMessage('fatalError', (args) {
try {
// 'fatalError' message is constructed as a JSON object in setupScript
if (args is Map<String, dynamic>) {
print('[JS FATAL ERROR]: ${args['message']}');
if (args['error'] != null) print(' Error: ${args['error']}');
if (args['stack'] != null) print(' Stack: ${args['stack']}');
} else {
print('[JS FATAL ERROR decoding error]: $args, Expected a Map.');
}
} catch (e) {
print('[JS FATAL ERROR decoding error]: $args, Error: $e');
}
});
}
Future<
({
HttpRequestModel updatedRequest,
Map<String, dynamic> updatedEnvironment
})> executePreRequestScript({
required RequestModel currentRequestModel,
required Map<String, dynamic> activeEnvironment,
}) async {
if ((currentRequestModel.preRequestScript ?? "").trim().isEmpty) {
// No script, return original data
// return (
// updatedRequest: currentRequestModel.httpRequestModel,
// updatedEnvironment: activeEnvironment
// );
}
final httpRequest = currentRequestModel.httpRequestModel;
final userScript = currentRequestModel.preRequestScript;
// Prepare Data
final requestJson = jsonEncode(httpRequest?.toJson());
final environmentJson = jsonEncode(activeEnvironment);
// Inject data as JS variables
// Escape strings properly if embedding directly
final dataInjection = """
var injectedRequestJson = ${jsEscapeString(requestJson)};
var injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
var injectedResponseJson = null; // Not needed for pre-request
""";
// Concatenate & Add Return
final fullScript = """
(function() {
// --- Data Injection (now constants within the IIFE scope) ---
$dataInjection
// --- Setup Script (will declare variables within the IIFE scope) ---
$kJSSetupScript
// --- User Script (will execute within the IIFE scope)---
$userScript
// --- Return Result (accesses variables from the IIFE scope) ---
// Ensure 'request' and 'environment' are accessible here
return JSON.stringify({ request: request, environment: environment });
})(); // Immediately invoke the function
""";
// TODO: Do something better to avoid null check here.
HttpRequestModel resultingRequest = httpRequest!;
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
try {
// Execute
final JsEvalResult result = jsRuntime.evaluate(fullScript);
// Process Results
if (result.isError) {
print("Pre-request script execution error: ${result.stringResult}");
//TODO: Handle error - log this error in the logs console
} else if (result.stringResult.isNotEmpty) {
final resultMap = jsonDecode(result.stringResult);
if (resultMap is Map<String, dynamic>) {
// Deserialize Request
if (resultMap.containsKey('request') && resultMap['request'] is Map) {
try {
resultingRequest = HttpRequestModel.fromJson(
Map<String, Object?>.from(resultMap['request']));
} catch (e) {
print("Error deserializing modified request from script: $e");
//TODO: Handle error - log this error in the logs console
}
}
// Get Environment Modifications
if (resultMap.containsKey('environment') &&
resultMap['environment'] is Map) {
resultingEnvironment =
Map<String, dynamic>.from(resultMap['environment']);
}
}
}
} catch (e) {
print("Dart-level error during pre-request script execution: $e");
}
return (
updatedRequest: resultingRequest,
updatedEnvironment: resultingEnvironment
);
}
Future<
({
HttpResponseModel updatedResponse,
Map<String, dynamic> updatedEnvironment
})> executePostResponseScript({
required RequestModel currentRequestModel,
required Map<String, dynamic> activeEnvironment,
}) async {
if ((currentRequestModel.postRequestScript ?? "").trim().isEmpty) {
// No script, return original data
// return (
// updatedRequest: currentRequestModel.httpRequestModel,
// updatedEnvironment: activeEnvironment
// );
}
final httpRequest = currentRequestModel.httpRequestModel;
final httpResponse = currentRequestModel.httpResponseModel;
final userScript = currentRequestModel.postRequestScript;
// Prepare Data
final requestJson = jsonEncode(httpRequest?.toJson());
final responseJson = jsonEncode(httpResponse?.toJson());
final environmentJson = jsonEncode(activeEnvironment);
// Inject data as JS variables
// Escape strings properly if embedding directly
final dataInjection = """
var injectedRequestJson = ${jsEscapeString(requestJson)};
var injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
var injectedResponseJson = ${jsEscapeString(responseJson)};
""";
// Concatenate & Add Return
final fullScript = """
(function() {
// --- Data Injection (now constants within the IIFE scope) ---
$dataInjection
// --- Setup Script (will declare variables within the IIFE scope) ---
$kJSSetupScript
// --- User Script (will execute within the IIFE scope)---
$userScript
// --- Return Result (accesses variables from the IIFE scope) ---
return JSON.stringify({ response: response, environment: environment });
})(); // Immediately invoke the function
""";
// TODO: Do something better to avoid null check here.
// HttpRequestModel resultingRequest = httpRequest!;
HttpResponseModel resultingResponse = httpResponse!;
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
try {
// Execute
final JsEvalResult result = jsRuntime.evaluate(fullScript);
// Process Results
if (result.isError) {
print("Post-Response script execution error: ${result.stringResult}");
// TODO: Handle error - maybe show in UI, keep original request/env
} else if (result.stringResult.isNotEmpty) {
final resultMap = jsonDecode(result.stringResult);
if (resultMap is Map<String, dynamic>) {
// Deserialize Request
if (resultMap.containsKey('response') && resultMap['response'] is Map) {
try {
resultingResponse = HttpResponseModel.fromJson(
Map<String, Object?>.from(resultMap['response']));
} catch (e) {
print("Error deserializing modified response from script: $e");
//TODO: Handle error - maybe keep original response?
}
}
// Get Environment Modifications
if (resultMap.containsKey('environment') &&
resultMap['environment'] is Map) {
resultingEnvironment =
Map<String, dynamic>.from(resultMap['environment']);
}
}
}
} catch (e) {
print("Dart-level error during post-response script execution: $e");
}
return (
updatedResponse: resultingResponse,
updatedEnvironment: resultingEnvironment
);
}
// Helper to properly escape strings for JS embedding
String jsEscapeString(String s) {
return jsonEncode(
s); // jsonEncode handles escaping correctly for JS string literals
}

View File

@@ -1,128 +0,0 @@
import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/foundation.dart';
import '../models/models.dart';
import '../services/services.dart';
Future<RequestModel> handlePreRequestScript(
RequestModel requestModel,
EnvironmentModel? originalEnvironmentModel,
void Function(EnvironmentModel, List<EnvironmentVariableModel>)? updateEnv,
) async {
final scriptResult = await executePreRequestScript(
currentRequestModel: requestModel,
activeEnvironment: originalEnvironmentModel?.toJson() ?? {},
);
final newRequestModel =
requestModel.copyWith(httpRequestModel: scriptResult.updatedRequest);
if (originalEnvironmentModel != null) {
final updatedEnvironmentMap = scriptResult.updatedEnvironment;
final List<EnvironmentVariableModel> newValues = [];
final Map<String, dynamic> mutableUpdatedEnv =
Map.from(updatedEnvironmentMap);
for (final originalVariable in originalEnvironmentModel.values) {
if (mutableUpdatedEnv.containsKey(originalVariable.key)) {
final dynamic newValue = mutableUpdatedEnv[originalVariable.key];
newValues.add(
originalVariable.copyWith(
value: newValue == null ? '' : newValue.toString(),
enabled: true,
),
);
mutableUpdatedEnv.remove(originalVariable.key);
} else {
// Variable was removed by the script (unset/clear), don't add it to newValues.
// Alternatively, you could keep it but set enabled = false:
// newValues.add(originalVariable.copyWith(enabled: false));
}
}
for (final entry in mutableUpdatedEnv.entries) {
final dynamic newValue = entry.value;
newValues.add(
EnvironmentVariableModel(
key: entry.key,
value: newValue == null ? '' : newValue.toString(),
enabled: true,
type: EnvironmentVariableType.variable,
),
);
}
updateEnv?.call(originalEnvironmentModel, newValues);
} else {
debugPrint(
"Skipped environment update as originalEnvironmentModel was null.");
if (scriptResult.updatedEnvironment.isNotEmpty) {
debugPrint(
"Warning: Pre-request script updated environment variables, but no active environment was selected to save them to.");
return requestModel;
}
return newRequestModel;
}
return newRequestModel;
}
Future<RequestModel> handlePostResponseScript(
RequestModel requestModel,
EnvironmentModel? originalEnvironmentModel,
void Function(EnvironmentModel, List<EnvironmentVariableModel>)? updateEnv,
) async {
final scriptResult = await executePostResponseScript(
currentRequestModel: requestModel,
activeEnvironment: originalEnvironmentModel?.toJson() ?? {"values": []},
);
final newRequestModel =
requestModel.copyWith(httpResponseModel: scriptResult.updatedResponse);
if (originalEnvironmentModel != null) {
final updatedEnvironmentMap = scriptResult.updatedEnvironment;
final List<EnvironmentVariableModel> newValues = [];
final Map<String, dynamic> mutableUpdatedEnv =
Map.from(updatedEnvironmentMap);
for (final originalVariable in originalEnvironmentModel.values) {
if (mutableUpdatedEnv.containsKey(originalVariable.key)) {
final dynamic newValue = mutableUpdatedEnv[originalVariable.key];
newValues.add(
originalVariable.copyWith(
value: newValue == null ? '' : newValue.toString(),
enabled: true,
),
);
mutableUpdatedEnv.remove(originalVariable.key);
} else {
// Variable was removed by the script (unset/clear), don't add it to newValues.
// Alternatively, you could keep it but set enabled = false:
// newValues.add(originalVariable.copyWith(enabled: false));
}
}
for (final entry in mutableUpdatedEnv.entries) {
final dynamic newValue = entry.value;
newValues.add(
EnvironmentVariableModel(
key: entry.key,
value: newValue == null ? '' : newValue.toString(),
enabled: true,
type: EnvironmentVariableType.variable,
),
);
}
updateEnv?.call(originalEnvironmentModel, newValues);
} else {
debugPrint(
"Skipped environment update as originalEnvironmentModel was null.");
if (scriptResult.updatedEnvironment.isNotEmpty) {
debugPrint(
"Warning: Post-response script updated environment variables, but no active environment was selected to save them to.");
}
return requestModel;
}
return newRequestModel;
}

View File

@@ -6,7 +6,6 @@ export 'header_utils.dart';
export 'history_utils.dart';
export 'http_utils.dart';
export 'js_utils.dart';
export 'pre_post_script_utils.dart';
export 'save_utils.dart';
export 'ui_utils.dart';
export 'window_utils.dart';