feat: env variable substitutions

This commit is contained in:
DenserMeerkat
2024-06-16 22:14:27 +05:30
parent 41a7f2ccf9
commit ebe576a118
7 changed files with 108 additions and 8 deletions

View File

@ -4,7 +4,8 @@ import 'package:apidash/consts.dart';
import 'providers.dart'; import 'providers.dart';
import '../models/models.dart'; import '../models/models.dart';
import '../services/services.dart' show hiveHandler, HiveHandler, request; import '../services/services.dart' show hiveHandler, HiveHandler, request;
import '../utils/utils.dart' show getNewUuid, collectionToHAR; import '../utils/utils.dart'
show getNewUuid, collectionToHAR, substituteHttpRequestModel;
final selectedIdStateProvider = StateProvider<String?>((ref) => null); final selectedIdStateProvider = StateProvider<String?>((ref) => null);
@ -205,6 +206,9 @@ class CollectionStateNotifier
return; return;
} }
HttpRequestModel substitutedHttpRequestModel =
getSubstitutedHttpRequestModel(requestModel.httpRequestModel!);
// set current model's isWorking to true and update state // set current model's isWorking to true and update state
var map = {...state!}; var map = {...state!};
map[id] = requestModel.copyWith( map[id] = requestModel.copyWith(
@ -214,7 +218,7 @@ class CollectionStateNotifier
state = map; state = map;
(http.Response?, Duration?, String?)? responseRec = await request( (http.Response?, Duration?, String?)? responseRec = await request(
requestModel.httpRequestModel!, substitutedHttpRequestModel,
defaultUriScheme: defaultUriScheme, defaultUriScheme: defaultUriScheme,
); );
late final RequestModel newRequestModel; late final RequestModel newRequestModel;
@ -311,4 +315,16 @@ class CollectionStateNotifier
// "data": state!.map((e) => e.toJson(includeResponse: false)).toList() // "data": state!.map((e) => e.toJson(includeResponse: false)).toList()
// }; // };
} }
HttpRequestModel getSubstitutedHttpRequestModel(
HttpRequestModel httpRequestModel) {
var envMap = ref.read(availableEnvironmentVariablesStateProvider);
var activeEnvId = ref.read(activeEnvironmentIdStateProvider);
return substituteHttpRequestModel(
httpRequestModel,
envMap,
activeEnvId,
);
}
} }

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/models.dart' show SettingsModel; import '../models/models.dart';
import 'environment_provider.dart';
import '../services/services.dart' show hiveHandler, HiveHandler; import '../services/services.dart' show hiveHandler, HiveHandler;
import '../consts.dart'; import '../consts.dart';
@ -10,6 +11,26 @@ final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) =>
final activeEnvironmentIdStateProvider = StateProvider<String?>((ref) => final activeEnvironmentIdStateProvider = StateProvider<String?>((ref) =>
ref.watch(settingsProvider.select((value) => value.activeEnvironmentId))); ref.watch(settingsProvider.select((value) => value.activeEnvironmentId)));
final availableEnvironmentVariablesStateProvider =
StateProvider<Map<String, List<EnvironmentVariableModel>>>((ref) {
Map<String, List<EnvironmentVariableModel>> result = {};
final environments = ref.watch(environmentsStateNotifierProvider);
final activeEnviormentId = ref.watch(activeEnvironmentIdStateProvider);
if (activeEnviormentId != null) {
result[activeEnviormentId] = environments?[activeEnviormentId]
?.values
.where((element) => element.enabled)
.toList() ??
[];
}
result[kGlobalEnvironmentId] = environments?[kGlobalEnvironmentId]
?.values
.where((element) => element.enabled)
.toList() ??
[];
return result;
});
final StateNotifierProvider<ThemeStateNotifier, SettingsModel> final StateNotifierProvider<ThemeStateNotifier, SettingsModel>
settingsProvider = settingsProvider =
StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler)); StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler));

View File

@ -85,6 +85,7 @@ class EnvironmentDropdown extends ConsumerWidget {
environments: environmentsList, environments: environmentsList,
onChanged: (value) { onChanged: (value) {
ref.read(activeEnvironmentIdStateProvider.notifier).state = value?.id; ref.read(activeEnvironmentIdStateProvider.notifier).state = value?.id;
ref.read(hasUnsavedChangesProvider.notifier).state = true;
}, },
), ),
); );

View File

@ -89,8 +89,10 @@ class EditEnvironmentSecretsState
? null ? null
: (value) { : (value) {
if (value != null) { if (value != null) {
setState(() {
secretRows[index] = secretRows[index] =
secretRows[index].copyWith(enabled: value); secretRows[index].copyWith(enabled: value);
});
} }
_onFieldChange(selectedId!); _onFieldChange(selectedId!);
}, },

View File

@ -89,8 +89,10 @@ class EditEnvironmentVariablesState
? null ? null
: (value) { : (value) {
if (value != null) { if (value != null) {
setState(() {
variableRows[index] = variableRows[index] =
variableRows[index].copyWith(enabled: value); variableRows[index].copyWith(enabled: value);
});
} }
_onFieldChange(selectedId!); _onFieldChange(selectedId!);
}, },

View File

@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart'; import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/widgets/widgets.dart';
import 'package:apidash/codegen/codegen.dart'; import 'package:apidash/codegen/codegen.dart';
import 'package:apidash/utils/utils.dart';
import 'package:apidash/consts.dart'; import 'package:apidash/consts.dart';
final Codegen codegen = Codegen(); final Codegen codegen = Codegen();
@ -19,8 +20,15 @@ class CodePane extends ConsumerWidget {
final defaultUriScheme = final defaultUriScheme =
ref.watch(settingsProvider.select((value) => value.defaultUriScheme)); ref.watch(settingsProvider.select((value) => value.defaultUriScheme));
var envMap = ref.watch(availableEnvironmentVariablesStateProvider);
var activeEnvId = ref.watch(activeEnvironmentIdStateProvider);
final substitutedRequestModel = selectedRequestModel?.copyWith(
httpRequestModel: substituteHttpRequestModel(
selectedRequestModel.httpRequestModel!, envMap, activeEnvId));
final code = codegen.getCode( final code = codegen.getCode(
codegenLanguage, selectedRequestModel!, defaultUriScheme); codegenLanguage, substitutedRequestModel!, defaultUriScheme);
if (code == null) { if (code == null) {
return const ErrorMessage( return const ErrorMessage(
message: "An error was encountered while generating code. $kRaiseIssue", message: "An error was encountered while generating code. $kRaiseIssue",

View File

@ -35,3 +35,53 @@ List<EnvironmentVariableModel> getEnvironmentSecrets(
(removeEmptyModels ? element != kEnvironmentSecretEmptyModel : true)) (removeEmptyModels ? element != kEnvironmentSecretEmptyModel : true))
.toList(); .toList();
} }
String? substituteVariables(
String? input,
Map<String?, List<EnvironmentVariableModel>> envMap,
String? activeEnvironmentId) {
if (input == null) return null;
final Map<String, String> combinedMap = {};
final activeEnv = envMap[activeEnvironmentId] ?? [];
final globalEnv = envMap[kGlobalEnvironmentId] ?? [];
for (var variable in globalEnv) {
combinedMap[variable.key] = variable.value;
}
for (var variable in activeEnv) {
combinedMap[variable.key] = variable.value;
}
final regex = RegExp(r'{{(.*?)}}');
String result = input.replaceAllMapped(regex, (match) {
final key = match.group(1)?.trim() ?? '';
return combinedMap[key] ?? '';
});
return result;
}
HttpRequestModel substituteHttpRequestModel(
HttpRequestModel httpRequestModel,
Map<String?, List<EnvironmentVariableModel>> envMap,
String? activeEnvironmentId) {
var newRequestModel = httpRequestModel.copyWith(
url: substituteVariables(
httpRequestModel.url,
envMap,
activeEnvironmentId,
)!,
headers: httpRequestModel.headers?.map((header) {
return header.copyWith(
value: substituteVariables(header.value, envMap, activeEnvironmentId),
);
}).toList(),
params: httpRequestModel.params?.map((param) {
return param.copyWith(
value: substituteVariables(param.value, envMap, activeEnvironmentId),
);
}).toList(),
);
return newRequestModel;
}