diff --git a/lib/main.dart b/lib/main.dart index 9be1fb49..510c28b0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,6 @@ void main() async { var settingsModel = await getSettingsFromSharedPrefs(); var onboardingStatus = await getOnboardingStatusFromSharedPrefs(); - initializeJsRuntime(); final initStatus = await initApp( kIsDesktop, settingsModel: settingsModel, diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 98d6bd4d..39d58828 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -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((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) { diff --git a/lib/providers/js_runtime_notifier.dart b/lib/providers/js_runtime_notifier.dart new file mode 100644 index 00000000..06e15730 --- /dev/null +++ b/lib/providers/js_runtime_notifier.dart @@ -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((ref) { + final notifier = JsRuntimeNotifier(ref); + notifier._initialize(); + return notifier; +}); + +class JsRuntimeNotifier extends StateNotifier { + 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 updatedEnvironment + })> executePreRequestScript({ + required RequestModel currentRequestModel, + required Map 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 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) { + if (decoded['request'] is Map) { + try { + resultingRequest = HttpRequestModel.fromJson( + Map.from(decoded['request'] as Map), + ); + } catch (e) { + print('Error deserializing modified request from script: $e'); + } + } + if (decoded['environment'] is Map) { + resultingEnvironment = + Map.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 updatedEnvironment + })> executePostResponseScript({ + required RequestModel currentRequestModel, + required Map 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 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) { + if (decoded['response'] is Map) { + try { + resultingResponse = HttpResponseModel.fromJson( + Map.from(decoded['response'] as Map), + ); + } catch (e) { + print('Error deserializing modified response from script: $e'); + } + } + if (decoded['environment'] is Map) { + resultingEnvironment = + Map.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 handlePreRequestScript( + RequestModel requestModel, + EnvironmentModel? originalEnvironmentModel, + void Function(EnvironmentModel, List)? 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 newValues = []; + final Map 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 handlePostResponseScript( + RequestModel requestModel, + EnvironmentModel? originalEnvironmentModel, + void Function(EnvironmentModel, List)? 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 newValues = []; + final Map 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 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) { + 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); diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart index cf1b9426..6510f90d 100644 --- a/lib/providers/providers.dart +++ b/lib/providers/providers.dart @@ -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'; diff --git a/lib/services/flutter_js_service.dart b/lib/services/flutter_js_service.dart deleted file mode 100644 index 991d0a1f..00000000 --- a/lib/services/flutter_js_service.dart +++ /dev/null @@ -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) { - 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 updatedEnvironment - })> executePreRequestScript({ - required RequestModel currentRequestModel, - required Map 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 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) { - // Deserialize Request - if (resultMap.containsKey('request') && resultMap['request'] is Map) { - try { - resultingRequest = HttpRequestModel.fromJson( - Map.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.from(resultMap['environment']); - } - } - } - } catch (e) { - print("Dart-level error during pre-request script execution: $e"); - } - - return ( - updatedRequest: resultingRequest, - updatedEnvironment: resultingEnvironment - ); -} - -Future< - ({ - HttpResponseModel updatedResponse, - Map updatedEnvironment - })> executePostResponseScript({ - required RequestModel currentRequestModel, - required Map 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 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) { - // Deserialize Request - if (resultMap.containsKey('response') && resultMap['response'] is Map) { - try { - resultingResponse = HttpResponseModel.fromJson( - Map.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.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 -} diff --git a/lib/utils/pre_post_script_utils.dart b/lib/utils/pre_post_script_utils.dart deleted file mode 100644 index d83e1623..00000000 --- a/lib/utils/pre_post_script_utils.dart +++ /dev/null @@ -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 handlePreRequestScript( - RequestModel requestModel, - EnvironmentModel? originalEnvironmentModel, - void Function(EnvironmentModel, List)? 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 newValues = []; - final Map 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 handlePostResponseScript( - RequestModel requestModel, - EnvironmentModel? originalEnvironmentModel, - void Function(EnvironmentModel, List)? 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 newValues = []; - final Map 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; -} diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 4ab96e6d..72b57468 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -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';