mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 10:49:49 +08:00
feat: implement post-response script handling and update environment variables
This commit is contained in:
@@ -329,6 +329,68 @@ class CollectionStateNotifier
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handlePostResponseScript(
|
||||
RequestModel requestModel,
|
||||
EnvironmentModel? originalEnvironmentModel,
|
||||
) async {
|
||||
final scriptResult = await executePostResponseScript(
|
||||
currentRequestModel: requestModel,
|
||||
activeEnvironment: originalEnvironmentModel?.toJson() ?? {},
|
||||
);
|
||||
|
||||
requestModel =
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
ref.read(environmentsStateNotifierProvider.notifier).updateEnvironment(
|
||||
originalEnvironmentModel.id,
|
||||
name: originalEnvironmentModel.name,
|
||||
values: 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendRequest() async {
|
||||
final requestId = ref.read(selectedIdStateProvider);
|
||||
ref.read(codePaneVisibleStateProvider.notifier).state = false;
|
||||
@@ -405,6 +467,7 @@ class CollectionStateNotifier
|
||||
httpRequestModel: substitutedHttpRequestModel,
|
||||
httpResponseModel: httpResponseModel,
|
||||
);
|
||||
handlePostResponseScript(newRequestModel, originalEnvironmentModel);
|
||||
ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'dart:developer';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
import 'package:apidash_core/models/http_request_model.dart';
|
||||
import 'package:apidash_core/models/http_response_model.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_js/flutter_js.dart';
|
||||
|
||||
@@ -133,7 +134,6 @@ Future<
|
||||
})(); // Immediately invoke the function
|
||||
""";
|
||||
|
||||
|
||||
// TODO: Do something better to avoid null check here.
|
||||
HttpRequestModel resultingRequest = httpRequest!;
|
||||
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
|
||||
@@ -177,6 +177,101 @@ Future<
|
||||
);
|
||||
}
|
||||
|
||||
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) ---
|
||||
$setupScript
|
||||
|
||||
// --- 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);
|
||||
log(resultMap['response'].toString());
|
||||
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(
|
||||
|
||||
@@ -12,12 +12,13 @@ import '../consts.dart';
|
||||
part 'http_response_model.freezed.dart';
|
||||
part 'http_response_model.g.dart';
|
||||
|
||||
class Uint8ListConverter implements JsonConverter<Uint8List?, List<int>?> {
|
||||
class Uint8ListConverter implements JsonConverter<Uint8List?, List<dynamic>?> {
|
||||
const Uint8ListConverter();
|
||||
|
||||
@override
|
||||
Uint8List? fromJson(List<int>? json) {
|
||||
return json == null ? null : Uint8List.fromList(json);
|
||||
Uint8List? fromJson(List<dynamic>? json) {
|
||||
if (json == null) return null;
|
||||
return Uint8List.fromList(json.cast<int>());
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user