Skip to content

Initial implementation for openapi requests imports (#121) #816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ enum CodegenLanguage {
enum ImportFormat {
curl("cURL"),
postman("Postman Collection v2.1"),
insomnia("Insomnia v4");
insomnia("Insomnia v4"),
openapi("OpenAPI v3.1");

const ImportFormat(this.label);
final String label;
Expand Down
1 change: 1 addition & 0 deletions lib/importer/importer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Importer {
.toList(),
ImportFormat.postman => PostmanIO().getHttpRequestModelList(content),
ImportFormat.insomnia => InsomniaIO().getHttpRequestModelList(content),
ImportFormat.openapi => OpenApiIO().getHttpRequestModelList(content),
};
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/apidash_core/lib/import_export/import_export.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'curl_io.dart';
export 'postman_io.dart';
export 'insomnia_io.dart';
export 'openapi_io.dart';
146 changes: 146 additions & 0 deletions packages/apidash_core/lib/import_export/openapi_io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import 'package:openapi_spec/openapi_spec.dart';
import '../consts.dart';
import '../models/models.dart';
import '../utils/utils.dart';
import 'package:seed/seed.dart';

class OpenApiIO {
(String?, HttpRequestModel) oasOperationToHttpRequestModel(String url, Operation? operation, String methodName, OpenApi oas) {
HTTPVerb method = HTTPVerb.values.byName((methodName));
List<Parameter> parameters = operation?.parameters ?? <Parameter>[];
List<NameValueModel> params = <NameValueModel>[];
List<bool> isParamEnabledList = <bool>[];
Map<String, Response>? res = operation?.responses ?? oas.components?.responses;
List<bool> isHeaderEnabledList = <bool>[];
List<NameValueModel> headers = <NameValueModel>[];
RequestBody? requestBody = operation?.requestBody;
Map<String, MediaType>? content = requestBody?.content;
ContentType bodyContentType = ContentType.json;
List<FormDataModel> formData = <FormDataModel>[];
String body = "";


// parameters
// FIX: https://github.com/tazatechnology/openapi_spec/issues/76
for (var param in parameters) {
var name = param.name ?? "";
var value = param.example ?? "";
var activeQuery = param.deprecated ?? true;
params.add(NameValueModel(name: name, value: value));
isParamEnabledList.add(activeQuery);
}

// headers
// FIX: https://github.com/tazatechnology/openapi_spec/issues/76
res?.map((status, response) {
return MapEntry(
response.headers?.map((headerName, headerValue) {
isHeaderEnabledList.add(headerValue != null ? true : false);
headers.add(NameValueModel(name: headerName, value: headerValue));
return const MapEntry(null, null);
}),
null
);
});


// RequestBody TODO:
content?.map((contentTypeStr, mediaType) {
if (mediaType.schema?.ref != null) {
var schemaas = oas.components?.schemas;
var referencedSchemaDefinition = schemaas?[mediaType.schema?.ref];
var properties = referencedSchemaDefinition?.toJson()['properties'];
var bodyContent = properties.map((field, inputDetails) {
// bodyContentType = getContentTypeFromContentTypeStr(contentTypeStr) ?? kDefaultContentType;
// FIX: https://github.com/foss42/apidash/issues/771
// TODO: reqBody content defines references to json && xml && formdata; suggestion - implement a bodyContentGenerator();
// Note: body could be a NameValueModel so json && xml && formdata can be shown on APIDASH
bodyContentType = kDefaultContentType;
return MapEntry(field, inputDetails['example']);
});
body = bodyContent.toString();
} else if (mediaType.examples != null) {
mediaType.examples?.map((str, value) {
body = value.value.toString();
bodyContentType = getContentTypeFromContentTypeStr(contentTypeStr) ?? kDefaultContentType;
// TODO: more than one example in openapi spec
return const MapEntry(null, null);
});
} else {
body = "";
}

// FIX:
if (bodyContentType == ContentType.formdata) {
var name = mediaType.schema?.title ?? "";
FormDataType formDataType;
try {
formDataType = FormDataType.values.byName(mediaType.schema?.runtimeType.toString() ?? "");
} catch (e) {
formDataType = FormDataType.text;
}
var value = switch (formDataType) {
FormDataType.text => mediaType.schema.toString() ?? "",
FormDataType.file => mediaType.schema.toString() ?? ""
};
formData.add(FormDataModel(
name: name,
value: value,
type: formDataType
));
}
return const MapEntry(null, null);
});

return (operation?.id, HttpRequestModel(
method: method,
url: url,
params: params,
isParamEnabledList: isParamEnabledList,
isHeaderEnabledList: isHeaderEnabledList,
headers: headers,
body: body,
bodyContentType: bodyContentType,
formData: formData
));
}

List<(String?, HttpRequestModel)>? getHttpRequestModelList(String content) {
content = content.trim();
try {

const format = OpenApiFormat.yaml;
final oas = OpenApi.fromString(source: content, format: format);
final oasPaths = oas.paths ?? oas.components?.pathItems;
List<(String?, HttpRequestModel)> httpRequestModelList = [];

// Note: Schemas could be defined directly in the reqbody or in the components or maybe both
// when schema is defined only in the components a reference to the scheme present in the components is provided
oasPaths?.map((url, pathItem) {
if (pathItem.get != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.get, "get", oas));
}
if (pathItem.post != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.post, "post", oas));
}
if (pathItem.put != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.put, "put", oas));
}
if (pathItem.delete != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.delete, "delete", oas));
}
if (pathItem.patch != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.patch, "patch", oas));
}
if (pathItem.head != null) {
httpRequestModelList.add(oasOperationToHttpRequestModel(url, pathItem.head, "head", oas));
}
return const MapEntry(null, null);
});
return httpRequestModelList;
} catch (e) {
print("$e");
return null;
}
}
}
3 changes: 3 additions & 0 deletions packages/apidash_core/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ dependencies:
path: ../postman
seed: ^0.0.3
xml: ^6.3.0
# currently checkedout tags/v0.7.24
openapi_spec:
path: ../openapi_spec

dev_dependencies:
flutter_test:
Expand Down
10 changes: 6 additions & 4 deletions packages/apidash_core/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# melos_managed_dependency_overrides: curl_parser,insomnia_collection,postman,seed
dependency_overrides:
curl_parser:
path: ../curl_parser
path: ..\\curl_parser
insomnia_collection:
path: ../insomnia_collection
path: ..\\insomnia_collection
postman:
path: ../postman
path: ..\\postman
seed:
path: ../seed
path: ..\\seed
openapi_spec:
path: ..\\openapi_spec
1 change: 1 addition & 0 deletions packages/openapi_spec
Submodule openapi_spec added at ee3209
31 changes: 31 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.0"
cli_completion:
dependency: transitive
description:
name: cli_completion
sha256: "158deec74a75cdc69bce061645fea08f94190dd6833f988f517c2dfcb45e9117"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
cli_launcher:
dependency: transitive
description:
Expand Down Expand Up @@ -937,6 +945,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.3.0"
mason_logger:
dependency: transitive
description:
name: mason_logger
sha256: "1fdf5c76870eb6fc3611ed6fbae1973a3794abe581ea5e22e68af2f73c688b93"
url: "https://pub.dev"
source: hosted
version: "0.2.16"
matcher:
dependency: transitive
description:
Expand Down Expand Up @@ -1048,6 +1064,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.2+1"
openapi_spec:
dependency: transitive
description:
path: "packages/openapi_spec"
relative: true
source: path
version: "0.7.24"
package_config:
dependency: transitive
description:
Expand Down Expand Up @@ -1263,6 +1286,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.2"
recase:
dependency: transitive
description:
name: recase
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
url: "https://pub.dev"
source: hosted
version: "4.1.0"
riverpod:
dependency: "direct main"
description:
Expand Down