diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a14cc4b8..840878bf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,50 +80,11 @@ In case you have already setup Flutter, make sure to switch to `stable` branch a ### How to run API Dash locally? -1. Fork the project. -2. Create a clone of the forked project on your computer to run it locally. -3. Based on your desktop environment, enable Windows, macOS or Linux for the project. Select the same target device. -4. Run the project by executing the following command: - -``` -flutter run -``` +Check out [here](https://github.com/foss42/apidash/blob/main/doc/dev_guide/setup_run.md) ### How to run tests? -To run tests execute the following command: - -``` -flutter test --coverage -``` - -To generate coverage report as html execute: - -``` -genhtml coverage/lcov.info -o coverage/html -``` - -**Note**: On macOS you need to have `lcov` installed on your system (`brew install lcov`) to run the above command. - -To view the coverage report in the browser for further analysis, execute: - -``` -open coverage/html/index.html -``` - -#### Testing a single file - -To run tests specified in a single file, execute the following command: - -``` -flutter test .dart -``` - -Example: - -``` -flutter test test/widgets/codegen_previewer_test.dart -``` +Check out [here](https://github.com/foss42/apidash/blob/main/doc/dev_guide/testing.md) ### How to add a new package to pubspec.yaml? @@ -131,39 +92,4 @@ Instead of copy pasting from pub.dev, it is recommended that you use `flutter pu ## Platform-specific Additional Instructions -### macOS - -Add below keys to `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`. - -``` - com.apple.security.network.server - - com.apple.security.network.client - - com.apple.security.files.downloads.read-write - - com.apple.security.files.user-selected.read-write - -``` - -If not added, you can encounter a network connection error similar to the following while running your Flutter app on macOS: - -``` -ClientException with SocketException: Connection failed (OS Error: Operation not permitted, errno = 1) -``` - -You can read more [here](https://docs.flutter.dev/platform-integration/macos/building#setting-up-entitlements) - -### Android (Work in Progress) - -Add the `multiDexEnabled true` line to the `defaultConfig` section at `android/app/build.gradle file` - -``` -android { - ... - defaultConfig { - ... - multiDexEnabled true - } -} -``` \ No newline at end of file +Check out [here](https://github.com/foss42/apidash/blob/main/doc/dev_guide/platform_specific_instructions.md) diff --git a/INSTALLATION.md b/INSTALLATION.md index 5673a691..3081ef2e 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -85,3 +85,32 @@ sudo yum localinstall ./apidash-.rpm ``` Launch API Dash via `apidash` command or by clicking on the API Dash app icon. + +### Arch-based Linux Distributions (Manjaro, Arch Linux, etc.) + +Download the `.deb` file from the [latest release](https://github.com/foss42/apidash/releases/latest) corresponding to your CPU architecture (x86_64/amd64 or arm64/aarch64). + +First we have to convert the .deb file to .tar.xz file using the following commands. + +1. Install debtap using the following command. + ``` + yay -S debtap + ``` + +2. Initialize `debtap` using the following command. + ``` + sudo debtap -u + ``` + +3. Convert the .deb file to .tar.xz file using the following command. + ``` + sudo debtap /path/to/apidash-.deb + ``` +4. Once converted, install the resulting .tar.xz file using the following command. + ``` + sudo pacman -U apidash-.tar.xz + ``` + +Note: Replace `/path/to/apidash-.deb` with the path to the downloaded .deb file. + +Launch API Dash via `apidash` command or by clicking on the API Dash app icon. diff --git a/README.md b/README.md index 5c57ebe9..4b57ca63 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ API Dash is a beautiful open-source cross-platform API Client that can help you easily create & customize your API requests, visually inspect responses ([full list of supported mime-types](https://github.com/foss42/apidash?tab=readme-ov-file#mime-types-supported-by-api-dash-response-previewer)) and generate API integration code ([full list](https://github.com/foss42/apidash?tab=readme-ov-file#code-generators)) on the go. -![Image](https://github.com/foss42/apidash/assets/615622/984b3c95-a6a1-48a5-a6ba-5a1e95802b5d) +![API Dash](screenshots/apidash.png) ## Download @@ -23,6 +23,13 @@ API Dash can be downloaded from the links below: + + iOS/iPad + App Store + + + Link + macOS .dmg @@ -130,6 +137,7 @@ API Dash currently supports API integration code generation for the following la | Kotlin | `okhttp3` | | | Ruby | `faraday` | | | Ruby | `net/http` | | +| Rust | `hyper` | | | Rust | `reqwest` | | | Rust | `ureq` | | | Rust | `Actix Client` | | @@ -226,6 +234,10 @@ Just click on the [Issue tab](https://github.com/foss42/apidash/issues) to raise Please find the Roadmap for API Dash [here](https://github.com/foss42/apidash/blob/main/ROADMAP.md). +## Documentation + +All docs are currently available in the [doc](https://github.com/foss42/apidash/blob/main/doc/) folder. + ## Contribute to API Dash You can contribute to API Dash in any or all of the following ways: diff --git a/ROADMAP.md b/ROADMAP.md index a38951b6..1c1f6c31 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,5 +10,5 @@ - [ ] API Workflow Builder (https://github.com/foss42/apidash/issues/120) - [x] Integration Testing (https://github.com/foss42/apidash/issues/119) - [ ] Remaining Code Generators (https://github.com/foss42/apidash/discussions/80) -- [ ] Embedded WebView in Response Previewer +- [ ] Embedded WebView in Response Previewer (https://github.com/foss42/apidash/issues/155) - [ ] Figuring out how to build for various Linux packaging formats (https://github.com/foss42/apidash/discussions/240) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..39d7e0a7 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,5 @@ +# API Dash Docs + +- [User Guide](https://github.com/foss42/apidash/tree/main/doc/user_guide) +- [Developer Guide](https://github.com/foss42/apidash/tree/main/doc/dev_guide) +- [GSoC Project Docs](https://github.com/foss42/apidash/tree/main/doc/gsoc) diff --git a/doc/dev_guide/platform_specific_instructions.md b/doc/dev_guide/platform_specific_instructions.md new file mode 100644 index 00000000..6e7aae98 --- /dev/null +++ b/doc/dev_guide/platform_specific_instructions.md @@ -0,0 +1,38 @@ +# Platform-specific Additional Instructions + +## macOS + +Add below keys to `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`. + +``` + com.apple.security.network.server + + com.apple.security.network.client + + com.apple.security.files.downloads.read-write + + com.apple.security.files.user-selected.read-write + +``` + +If not added, you can encounter a network connection error similar to the following while running your Flutter app on macOS: + +``` +ClientException with SocketException: Connection failed (OS Error: Operation not permitted, errno = 1) +``` + +You can read more [here](https://docs.flutter.dev/platform-integration/macos/building#setting-up-entitlements) + +## Android (Work in Progress) + +Add the `multiDexEnabled true` line to the `defaultConfig` section at `android/app/build.gradle file` + +``` +android { + ... + defaultConfig { + ... + multiDexEnabled true + } +} +``` diff --git a/doc/dev_guide/setup_run.md b/doc/dev_guide/setup_run.md new file mode 100644 index 00000000..538f35fc --- /dev/null +++ b/doc/dev_guide/setup_run.md @@ -0,0 +1,37 @@ +# How to run API Dash locally? + +1. Fork the project. +2. Create a clone of the forked project on your computer to run it locally. +3. Based on your desktop environment, enable Windows, macOS or Linux for the project. Select the same target device. + +#### 4. Setup melos + +As API Dash is a monorepo with multi-package architecture we use [melos](https://pub.dev/packages/melos). + +``` +dart pub global activate melos +``` + +Bootstrap to initialize the workspace, link local packages together and install remaining package dependencies. + +``` +melos bootstrap +``` + +Get all dependencies of packages + +``` +melos pub-get +``` + +Get all dependencies of app + +``` +flutter pub get +``` + +Run the project by executing the following command: + +``` +flutter run +``` diff --git a/doc/dev_guide/testing.md b/doc/dev_guide/testing.md new file mode 100644 index 00000000..f9389918 --- /dev/null +++ b/doc/dev_guide/testing.md @@ -0,0 +1,65 @@ +# How to run tests? + +As API Dash is a monorepo with multi-package architecture we use [melos](https://pub.dev/packages/melos). + +``` +dart pub global activate melos +``` + +Bootstrap to initialize the workspace, link local packages together and install remaining package dependencies. + +``` +melos bootstrap +``` + +Get all dependencies of packages + +``` +melos pub-get +``` + +Get all dependencies of main app + +``` +flutter pub get +``` + +To run tests execute the following command: + +``` +flutter test --coverage +``` + +followed by + +``` +melos test +``` + +To generate coverage report as html execute: + +``` +genhtml coverage/lcov.info -o coverage/html +``` + +**Note**: On macOS you need to have `lcov` installed on your system (`brew install lcov`) to run the above command. + +To view the coverage report in the browser for further analysis, execute: + +``` +open coverage/html/index.html +``` + +## Testing a single file + +To run tests specified in a single file, execute the following command: + +``` +flutter test .dart +``` + +Example: + +``` +flutter test test/widgets/codegen_previewer_test.dart +``` diff --git a/integration_test/req_helper.dart b/integration_test/req_helper.dart index 4d2fd68c..392f1c0b 100644 --- a/integration_test/req_helper.dart +++ b/integration_test/req_helper.dart @@ -1,3 +1,4 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:spot/spot.dart'; diff --git a/integration_test/test_helper.dart b/integration_test/test_helper.dart index f05a7cf7..c7ce0b0b 100644 --- a/integration_test/test_helper.dart +++ b/integration_test/test_helper.dart @@ -1,10 +1,10 @@ import 'package:apidash/models/settings_model.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/services/services.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:integration_test/integration_test.dart'; import 'package:apidash/main.dart' as app; import 'package:apidash/app.dart'; diff --git a/lib/app.dart b/lib/app.dart index 48c49a86..ac6f708b 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; diff --git a/lib/codegen/c/curl.dart b/lib/codegen/c/curl.dart index fae29ec9..8077a301 100644 --- a/lib/codegen/c/curl.dart +++ b/lib/codegen/c/curl.dart @@ -1,7 +1,5 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show getValidRequestUri; -import 'package:apidash/models/models.dart'; class CCurlCodeGen { final String kTemplateStart = """#include diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index fe468ad0..a69e3eca 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -27,6 +27,7 @@ import 'ruby/faraday.dart'; import 'ruby/net_http.dart'; import 'rust/actix.dart'; import 'rust/curl_rust.dart'; +import 'rust/hyper.dart'; import 'rust/reqwest.dart'; import 'rust/ureq.dart'; import 'swift/urlsession.dart'; @@ -96,6 +97,8 @@ class Codegen { return RustActixCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rustCurl: return RustCurlCodeGen().getCode(rM); + case CodegenLanguage.rustHyper: + return RustHyperCodeGen().getCode(rM); case CodegenLanguage.rustReqwest: return RustReqwestCodeGen().getCode(rM); case CodegenLanguage.rustUreq: diff --git a/lib/codegen/csharp/http_client.dart b/lib/codegen/csharp/http_client.dart index 390966d9..6d086db8 100644 --- a/lib/codegen/csharp/http_client.dart +++ b/lib/codegen/csharp/http_client.dart @@ -1,7 +1,5 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/models/models.dart'; -import 'package:apidash/utils/http_utils.dart'; class CSharpHttpClientCodeGen { final String kTemplateNamespaces = r''' diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 47f3379b..efebb7cf 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -1,9 +1,6 @@ import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/extensions/extensions.dart'; -import 'package:apidash/utils/http_utils.dart'; class CSharpRestSharp { String kStringImports = """ diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index 63a1d532..8db444c7 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -1,8 +1,7 @@ import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; import 'shared.dart'; class DartDioCodeGen { diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 5a341606..be586721 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -1,9 +1,8 @@ import 'dart:convert'; import 'dart:io'; +import 'package:apidash_core/apidash_core.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; import 'shared.dart'; class DartHttpCodeGen { diff --git a/lib/codegen/go/http.dart b/lib/codegen/go/http.dart index bc7dfa08..28fd805a 100644 --- a/lib/codegen/go/http.dart +++ b/lib/codegen/go/http.dart @@ -1,7 +1,5 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show getValidRequestUri; -import 'package:apidash/models/models.dart'; class GoHttpCodeGen { final String kTemplateStart = """package main diff --git a/lib/codegen/java/async_http_client.dart b/lib/codegen/java/async_http_client.dart index d163a578..4b195738 100644 --- a/lib/codegen/java/async_http_client.dart +++ b/lib/codegen/java/async_http_client.dart @@ -1,8 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; class JavaAsyncHttpClientGen { final String kStringStart = ''' diff --git a/lib/codegen/java/httpclient.dart b/lib/codegen/java/httpclient.dart index 5dbe27f9..e929b7b5 100644 --- a/lib/codegen/java/httpclient.dart +++ b/lib/codegen/java/httpclient.dart @@ -1,8 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, requestModelToHARJsonRequest; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import '../../utils/har_utils.dart'; class JavaHttpClientCodeGen { final String kTemplateStart = """import java.net.URI; diff --git a/lib/codegen/java/okhttp.dart b/lib/codegen/java/okhttp.dart index 9045aa55..e9b849a7 100644 --- a/lib/codegen/java/okhttp.dart +++ b/lib/codegen/java/okhttp.dart @@ -1,9 +1,6 @@ import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; class JavaOkHttpCodeGen { final String kTemplateStart = """ diff --git a/lib/codegen/java/unirest.dart b/lib/codegen/java/unirest.dart index c8bccbf1..ad3a3e99 100644 --- a/lib/codegen/java/unirest.dart +++ b/lib/codegen/java/unirest.dart @@ -1,7 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/models/models.dart'; -import 'package:apidash/utils/http_utils.dart'; -import 'package:apidash/consts.dart'; class JavaUnirestGen { final String kStringUnirestImports = ''' diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index 6314bdcd..e6651976 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -1,8 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show padMultilineString, requestModelToHARJsonRequest, stripUrlParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import '../../utils/utils.dart'; class AxiosCodeGen { AxiosCodeGen({this.isNodeJs = false}); diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index c4ca14b0..5f610738 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -1,8 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show padMultilineString, requestModelToHARJsonRequest; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import '../../utils/utils.dart'; class FetchCodeGen { FetchCodeGen({this.isNodeJs = false}); diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index f5d55e1a..3425dc09 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -1,8 +1,6 @@ import 'dart:io'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; class JuliaHttpClientCodeGen { final String kTemplateStart = """ diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index 8f4605b4..418c0ba9 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -1,9 +1,6 @@ import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; class KotlinOkHttpCodeGen { final String kTemplateStart = """import okhttp3.OkHttpClient diff --git a/lib/codegen/others/curl.dart b/lib/codegen/others/curl.dart index 1fb6bfd8..7ddeb1b2 100644 --- a/lib/codegen/others/curl.dart +++ b/lib/codegen/others/curl.dart @@ -1,7 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show requestModelToHARJsonRequest; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import '../../utils/utils.dart'; // ignore: camel_case_types class cURLCodeGen { diff --git a/lib/codegen/others/har.dart b/lib/codegen/others/har.dart index acef6357..ad8c559b 100644 --- a/lib/codegen/others/har.dart +++ b/lib/codegen/others/har.dart @@ -1,6 +1,5 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' show requestModelToHARJsonRequest; -import 'package:apidash/models/models.dart'; +import 'package:apidash_core/apidash_core.dart'; +import '../../utils/utils.dart'; class HARCodeGen { String? getCode( diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index a9ff8b91..24ff2579 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -1,8 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; class PHPcURLCodeGen { final String kTemplateStart = r''' diff --git a/lib/codegen/php/guzzle.dart b/lib/codegen/php/guzzle.dart index d60c43fb..d6fe79f6 100644 --- a/lib/codegen/php/guzzle.dart +++ b/lib/codegen/php/guzzle.dart @@ -1,7 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show stripUrlParams; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; class PhpGuzzleCodeGen { String kTemplateImport = """ Result<(), Box> { + let http{% if isHttps %}s{% endif %} = Http{% if isHttps %}s{% endif %}Connector::new(); + let client = Client::builder().build::<_, hyper::Body>(http{% if isHttps %}s{% endif %}); + let url = "{{ url }}".parse::().unwrap(); + +"""; + + final String kTemplateMethod = """ + let req_builder = Request::builder() + .method("{{ method }}") + .uri(url) +"""; + final String kTemplateMethodNoHeadersButForm = """ + let req_builder = Request::builder() + .method("{{ method }}") + .uri(url); +"""; + + final String kTemplateHeaders = """ + {% for key, val in headers %} + .header("{{ key }}", "{{ val }}") + {% endfor %}"""; + + final String kTemplateHeadersFormData = """ + {% for key, val in headers %} + .header("{{ key }}", "{{ val }}"){% if loop.last %};{% endif %} + {% endfor %} +"""; + + final String kTemplateBody = """ + + .body(Body::from(r#"{{ body }}"#))?;\n +"""; + + final String kTemplateJsonBody = """ + + .body(Body::from(json!({{ body }}).to_string()))?;\n +"""; + + final String kTemplateEmptyBody = """ + + .body(Body::empty())?;\n +"""; + + final String kTemplateFormData = """ + + let mut form = multipart::Form::default(); + {%- for field in fields_list %} + {%- if field.type == "file" %} + form.add_file("{{ field.name }}", r"{{ field.value }}").unwrap(); + {%- else %} + form.add_text("{{ field.name }}", "{{ field.value }}"); + {%- endif %} + {%- endfor %} + + let req = form.set_body_convert::(req_builder).unwrap(); + + """; + + final String kTemplateEndForm = """ + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + +"""; + + final String kTemplateRequestEnd = """ + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + +"""; + + final String kTemplateEnd = """ + Ok(()) +} + +"""; + + String? getCode(HttpRequestModel requestModel) { + try { + String result = ""; + + String url = requestModel.url; + var rec = getValidRequestUri(url, requestModel.enabledParams); + Uri? uri = rec.$1; + + if (uri != null) { + var headers = requestModel.enabledHeadersMap; + result += jj.Template(kTemplateStart).render({ + "url": uri, + "isHttps": uri.scheme == "https" ? true : false, + 'hasJsonBody': requestModel.hasJsonData, + 'hasForm': requestModel.hasFormData, + }); + + if (requestModel.hasFormData && headers.isEmpty) { + result += jj.Template(kTemplateMethodNoHeadersButForm).render({ + "method": requestModel.method.name.toUpperCase(), + }); + } else { + result += jj.Template(kTemplateMethod).render({ + "method": requestModel.method.name.toUpperCase(), + }); + } + + // Add headers if available + + if (headers.isNotEmpty) { + if (requestModel.hasFormData) { + result += jj.Template(kTemplateHeadersFormData) + .render({"headers": headers}); + } else { + result += + jj.Template(kTemplateHeaders).render({"headers": headers}); + } + } + + // Handle body (JSON or raw) + var requestBody = requestModel.body; + if (requestModel.hasFormData) { + result += jj.Template(kTemplateFormData).render({ + "fields_list": requestModel.formDataMapList, + }); + } else if (requestBody == "" || + requestBody == null || + requestModel.method == HTTPVerb.get || + requestModel.method == HTTPVerb.head) { + result += kTemplateEmptyBody; + } else if (requestModel.hasJsonData) { + result += + jj.Template(kTemplateJsonBody).render({"body": requestBody}); + } else if (requestModel.hasTextData) { + result += jj.Template(kTemplateBody).render({"body": requestBody}); + } + // End request + + if (requestModel.hasFormData && requestModel.method != HTTPVerb.get) { + result += kTemplateEndForm; + } else { + result += kTemplateRequestEnd; + } + result += kTemplateEnd; + } + + return result; + } catch (e) { + return null; + } + } +} diff --git a/lib/codegen/rust/reqwest.dart b/lib/codegen/rust/reqwest.dart index 0e678575..1e72807b 100644 --- a/lib/codegen/rust/reqwest.dart +++ b/lib/codegen/rust/reqwest.dart @@ -1,10 +1,7 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; class RustReqwestCodeGen { final String kTemplateStart = diff --git a/lib/codegen/rust/ureq.dart b/lib/codegen/rust/ureq.dart index f91e56a0..0a8a0744 100644 --- a/lib/codegen/rust/ureq.dart +++ b/lib/codegen/rust/ureq.dart @@ -1,10 +1,8 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' - show getNewUuid, getValidRequestUri, stripUriParams; -import 'package:apidash/models/models.dart'; +import '../../utils/utils.dart'; class RustUreqCodeGen { final String kTemplateStart = """ diff --git a/lib/consts.dart b/lib/consts.dart index 685002af..524d8e45 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -1,9 +1,8 @@ -import 'dart:convert'; import 'dart:io'; - +import 'package:apidash_design_system/apidash_design_system.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; const kDiscordUrl = "https://bit.ly/heyfoss"; const kGitUrl = "https://github.com/foss42/apidash"; @@ -26,15 +25,6 @@ final kIsIOS = !kIsWeb && Platform.isIOS; final kIsAndroid = !kIsWeb && Platform.isAndroid; final kIsMobile = !kIsWeb && (Platform.isIOS || Platform.isAndroid); -final kColorTransparentState = - WidgetStateProperty.all(Colors.transparent); -const kColorTransparent = Colors.transparent; -const kColorWhite = Colors.white; -const kColorBlack = Colors.black; -const kColorRed = Colors.red; -final kColorLightDanger = Colors.red.withOpacity(0.9); -const kColorDarkDanger = Color(0xffcf6679); - const kWindowTitle = "API Dash"; const kMinWindowSize = Size(320, 640); const kMinInitialWindowWidth = 1200.0; @@ -45,148 +35,10 @@ const kMediumWindowWidth = 840.0; const kExpandedWindowWidth = 1200.0; const kLargeWindowWidth = 1600.0; -const kColorSchemeSeed = Colors.blue; -final kFontFamily = GoogleFonts.openSans().fontFamily; -final kFontFamilyFallback = - kIsApple ? null : [GoogleFonts.notoColorEmoji().fontFamily!]; - -final kLightMaterialAppTheme = ThemeData( - fontFamily: kFontFamily, - fontFamilyFallback: kFontFamilyFallback, - colorSchemeSeed: kColorSchemeSeed, - useMaterial3: true, - brightness: Brightness.light, - visualDensity: VisualDensity.adaptivePlatformDensity, -); -final kDarkMaterialAppTheme = ThemeData( - fontFamily: kFontFamily, - fontFamilyFallback: kFontFamilyFallback, - colorSchemeSeed: kColorSchemeSeed, - useMaterial3: true, - brightness: Brightness.dark, - visualDensity: VisualDensity.adaptivePlatformDensity, -); - -final kCodeStyle = TextStyle( - fontFamily: GoogleFonts.sourceCodePro().fontFamily, - fontFamilyFallback: kFontFamilyFallback, -); - final kHomeScaffoldKey = GlobalKey(); final kEnvScaffoldKey = GlobalKey(); final kHisScaffoldKey = GlobalKey(); -const kHintOpacity = 0.6; -const kForegroundOpacity = 0.05; -const kOverlayBackgroundOpacity = 0.5; - -const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); -const kTextStyleTab = TextStyle(fontSize: 14); -const kTextStyleButtonSmall = TextStyle(fontSize: 12); -const kFormDataButtonLabelTextStyle = TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, -); -const kTextStylePopupMenuItem = TextStyle(fontSize: 14); - -final kButtonSidebarStyle = ElevatedButton.styleFrom(padding: kPh12); - -const kBorderRadius4 = BorderRadius.all(Radius.circular(4)); -const kBorderRadius6 = BorderRadius.all(Radius.circular(6)); -const kBorderRadius8 = BorderRadius.all(Radius.circular(8)); -final kBorderRadius10 = BorderRadius.circular(10); -const kBorderRadius12 = BorderRadius.all(Radius.circular(12)); -const kBorderRadius20 = BorderRadius.all(Radius.circular(20)); - -const kP1 = EdgeInsets.all(1); -const kP4 = EdgeInsets.all(4); -const kP5 = EdgeInsets.all(5); -const kP6 = EdgeInsets.all(6); -const kP8 = EdgeInsets.all(8); -const kPs8 = EdgeInsets.only(left: 8); -const kPs2 = EdgeInsets.only(left: 2); -const kPe4 = EdgeInsets.only(right: 4); -const kPe8 = EdgeInsets.only(right: 8); -const kPh20v5 = EdgeInsets.symmetric(horizontal: 20, vertical: 5); -const kPh20v10 = EdgeInsets.symmetric(horizontal: 20, vertical: 10); -const kP10 = EdgeInsets.all(10); -const kPv2 = EdgeInsets.symmetric(vertical: 2); -const kPv6 = EdgeInsets.symmetric(vertical: 6); -const kPv8 = EdgeInsets.symmetric(vertical: 8); -const kPv10 = EdgeInsets.symmetric(vertical: 10); -const kPv20 = EdgeInsets.symmetric(vertical: 20); -const kPh2 = EdgeInsets.symmetric(horizontal: 2); -const kPt28o8 = EdgeInsets.only(top: 28, left: 8.0, right: 8.0, bottom: 8.0); -const kPt5o10 = - EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0); -const kPh4 = EdgeInsets.symmetric(horizontal: 4); -const kPh8 = EdgeInsets.symmetric(horizontal: 8); -const kPh12 = EdgeInsets.symmetric(horizontal: 12); -const kPh20 = EdgeInsets.symmetric(horizontal: 20); -const kPh24 = EdgeInsets.symmetric(horizontal: 24); -const kPh20t40 = EdgeInsets.only( - left: 20, - right: 20, - top: 40, -); -const kPs0o6 = EdgeInsets.only( - left: 0, - top: 6, - right: 6, - bottom: 6, -); -const kPh60 = EdgeInsets.symmetric(horizontal: 60); -const kPh60v60 = EdgeInsets.symmetric(vertical: 60, horizontal: 60); -const kP24CollectionPane = EdgeInsets.only( - top: 24, - left: 4.0, - //right: 4.0, - // bottom: 8.0, -); -const kP8CollectionPane = EdgeInsets.only( - top: 8.0, - left: 4.0, - //right: 4.0, - // bottom: 8.0, -); -const kPt8 = EdgeInsets.only( - top: 8, -); -const kPt20 = EdgeInsets.only( - top: 20, -); -const kPt24 = EdgeInsets.only( - top: 24, -); -const kPt28 = EdgeInsets.only( - top: 28, -); -const kPt32 = EdgeInsets.only( - top: 32, -); -const kPb10 = EdgeInsets.only( - bottom: 10, -); -const kPb15 = EdgeInsets.only( - bottom: 15, -); -const kPb70 = EdgeInsets.only( - bottom: 70, -); -const kHSpacer2 = SizedBox(width: 2); -const kHSpacer4 = SizedBox(width: 4); -const kHSpacer5 = SizedBox(width: 5); -const kHSpacer10 = SizedBox(width: 10); -const kHSpacer12 = SizedBox(width: 12); -const kHSpacer20 = SizedBox(width: 20); -const kHSpacer40 = SizedBox(width: 40); -const kVSpacer5 = SizedBox(height: 5); -const kVSpacer8 = SizedBox(height: 8); -const kVSpacer10 = SizedBox(height: 10); -const kVSpacer16 = SizedBox(height: 16); -const kVSpacer20 = SizedBox(height: 20); -const kVSpacer40 = SizedBox(height: 40); - const kTabAnimationDuration = Duration(milliseconds: 200); const kTabHeight = 40.0; const kHeaderHeight = 32.0; @@ -220,108 +72,6 @@ final kIconRemoveLight = Icon( ); const kCodePreviewLinesLimit = 500; -const kCodeCharsPerLineLimit = 200; - -const kLightCodeTheme = { - 'root': - TextStyle(backgroundColor: Color(0xffffffff), color: Color(0xff000000)), - 'addition': TextStyle(backgroundColor: Color(0xffbaeeba)), - 'attr': TextStyle(color: Color(0xff836C28)), - 'attribute': TextStyle(color: Color(0xffaa0d91)), - 'built_in': TextStyle(color: Color(0xff5c2699)), - 'builtin-name': TextStyle(color: Color(0xff5c2699)), - 'bullet': TextStyle(color: Color(0xff1c00cf)), - 'code': TextStyle(color: Color(0xffc41a16)), - 'comment': TextStyle(color: Color(0xff007400), fontStyle: FontStyle.italic), - 'deletion': TextStyle(backgroundColor: Color(0xffffc8bd)), - 'doctag': TextStyle(fontWeight: FontWeight.bold), - 'emphasis': TextStyle(fontStyle: FontStyle.italic), - 'formula': TextStyle( - backgroundColor: Color(0xffeeeeee), fontStyle: FontStyle.italic), - 'keyword': TextStyle(color: Color(0xffaa0d91)), - 'link': TextStyle(color: Color(0xff0E0EFF)), - 'literal': TextStyle(color: Color(0xffaa0d91)), - 'meta': TextStyle(color: Color(0xff643820)), - 'meta-string': TextStyle(color: Color(0xffc41a16)), - 'name': TextStyle(color: Color(0xffaa0d91)), - 'number': TextStyle(color: Color(0xff1c00cf)), - 'params': TextStyle(color: Color(0xff5c2699)), - 'quote': TextStyle(color: Color(0xff007400)), - 'regexp': TextStyle(color: Color(0xff0E0EFF)), - 'section': TextStyle(color: Color(0xff643820)), - 'selector-class': TextStyle(color: Color(0xff9b703f)), - 'selector-id': TextStyle(color: Color(0xff9b703f)), - 'selector-tag': TextStyle(color: Color(0xffaa0d91)), - 'string': TextStyle(color: Color(0xffc41a16)), - 'strong': TextStyle(fontWeight: FontWeight.bold), - 'subst': TextStyle(color: Color(0xff000000)), - 'symbol': TextStyle(color: Color(0xff1c00cf)), - 'tag': TextStyle(color: Color(0xffaa0d91)), - 'template-variable': TextStyle(color: Color(0xff3F6E74)), - 'title': TextStyle(color: Color(0xff1c00cf)), - 'type': TextStyle(color: Color(0xff5c2699)), - 'variable': TextStyle(color: Color(0xff3F6E74)), -}; - -const kDarkCodeTheme = { - 'root': - TextStyle(backgroundColor: Color(0xff011627), color: Color(0xffd6deeb)), - 'addition': TextStyle(color: Color(0xffaddb67)), - 'attr': TextStyle(color: Color(0xff7fdbca)), - 'attribute': TextStyle(color: Color(0xff80cbc4)), - 'built_in': TextStyle(color: Color(0xffaddb67)), - 'builtin-name': TextStyle(color: Color(0xff7fdbca)), - 'bullet': TextStyle(color: Color(0xffd9f5dd)), - 'class': TextStyle(color: Color(0xffffcb8b)), - 'code': TextStyle(color: Color(0xff80CBC4)), - 'comment': TextStyle(color: Color(0xff637777), fontStyle: FontStyle.italic), - 'deletion': TextStyle(color: Color(0xffef5350)), - 'doctag': TextStyle(color: Color(0xff7fdbca)), - 'emphasis': TextStyle(color: Color(0xffc792ea)), - 'formula': TextStyle(color: Color(0xffc792ea), fontStyle: FontStyle.italic), - 'function': TextStyle(color: Color(0xff82AAFF)), - 'keyword': TextStyle(color: Color(0xffc792ea)), - 'link': TextStyle(color: Color(0xffff869a)), - 'literal': TextStyle(color: Color(0xffff5874)), - 'meta': TextStyle(color: Color(0xff82aaff)), - 'meta-keyword': TextStyle(color: Color(0xff82aaff)), - 'meta-string': TextStyle(color: Color(0xffecc48d)), - 'name': TextStyle(color: Color(0xff7fdbca)), - 'number': TextStyle(color: Color(0xffF78C6C)), - 'params': TextStyle(color: Color(0xff7fdbca)), - 'quote': TextStyle(color: Color(0xff697098)), - 'regexp': TextStyle(color: Color(0xff5ca7e4)), - 'section': TextStyle(color: Color(0xff82b1ff)), - 'selector-attr': TextStyle(color: Color(0xffc792ea)), - 'selector-class': TextStyle(color: Color(0xffaddb67)), - 'selector-id': TextStyle(color: Color(0xfffad430)), - 'selector-pseudo': TextStyle(color: Color(0xffc792ea)), - 'selector-tag': TextStyle(color: Color(0xffff6363)), - 'string': TextStyle(color: Color(0xffecc48d)), - 'strong': TextStyle(color: Color(0xffaddb67), fontWeight: FontWeight.bold), - 'subst': TextStyle(color: Color(0xffd3423e)), - 'symbol': TextStyle(color: Color(0xff82aaff)), - 'tag': TextStyle(color: Color(0xff7fdbca)), - 'template-tag': TextStyle(color: Color(0xffc792ea)), - 'template-variable': TextStyle(color: Color(0xffaddb67)), - 'title': TextStyle(color: Color(0xffDCDCAA)), - 'type': TextStyle(color: Color(0xff82aaff)), - 'variable': TextStyle(color: Color(0xffaddb67)), -}; - -final kColorStatusCodeDefault = Colors.grey.shade700; -final kColorStatusCode200 = Colors.green.shade800; -final kColorStatusCode300 = Colors.blue.shade800; -final kColorStatusCode400 = Colors.red.shade800; -final kColorStatusCode500 = Colors.amber.shade900; -const kOpacityDarkModeBlend = 0.4; - -final kColorHttpMethodGet = Colors.green.shade800; -final kColorHttpMethodHead = kColorHttpMethodGet; -final kColorHttpMethodPost = Colors.blue.shade800; -final kColorHttpMethodPut = Colors.amber.shade900; -final kColorHttpMethodPatch = kColorHttpMethodPut; -final kColorHttpMethodDelete = Colors.red.shade800; enum HistoryRetentionPeriod { oneWeek("1 Week", Icons.calendar_view_week_rounded), @@ -350,26 +100,10 @@ enum SidebarMenuOption { final String label; } -enum HTTPVerb { get, head, post, put, patch, delete } - -enum FormDataType { text, file } - enum EnvironmentVariableType { variable, secret } final kEnvVarRegEx = RegExp(r'{{([^{}]*)}}'); -const kSupportedUriSchemes = ["https", "http"]; -const kDefaultUriScheme = "https"; -const kMethodsWithBody = [ - HTTPVerb.post, - HTTPVerb.put, - HTTPVerb.patch, - HTTPVerb.delete, -]; - -const kDefaultHttpMethod = HTTPVerb.get; -const kDefaultContentType = ContentType.json; - enum CodegenLanguage { curl("cURL", "bash", "curl"), har("HAR", "json", "har"), @@ -389,6 +123,7 @@ enum CodegenLanguage { rubyFaraday("Ruby (Faraday)", "ruby", "rb"), rubyNetHttp("Ruby (Net::Http)", "ruby", "rb"), rustActix("Rust (Actix Client)", "rust", "rs"), + rustHyper("Rust (Hyper)", "rust", "rs"), rustReqwest("Rust (reqwest)", "rust", "rs"), rustCurl("Rust (curl-rust)", "rust", "rs"), rustUreq("Rust (ureq)", "rust", "rs"), @@ -415,59 +150,8 @@ enum ImportFormat { final String label; } -const JsonEncoder kJsonEncoder = JsonEncoder.withIndent(' '); -const JsonDecoder kJsonDecoder = JsonDecoder(); -const LineSplitter kSplitter = LineSplitter(); - const String kGlobalEnvironmentId = "global"; -const kHeaderContentType = "Content-Type"; - -const kTypeApplication = 'application'; -// application -const kSubTypeJson = 'json'; -const kSubTypeOctetStream = 'octet-stream'; -const kSubTypePdf = 'pdf'; -const kSubTypeSql = 'sql'; -const kSubTypeXml = 'xml'; -const kSubTypeYaml = 'yaml'; -const kSubTypeXYaml = 'x-yaml'; -const kSubTypeYml = 'x-yml'; -const kSubTypeXWwwFormUrlencoded = 'x-www-form-urlencoded'; - -const kTypeText = 'text'; -// text -const kSubTypeCss = 'css'; -const kSubTypeCsv = 'csv'; -const kSubTypeHtml = 'html'; -const kSubTypeJavascript = 'javascript'; -const kSubTypeMarkdown = 'markdown'; -const kSubTypePlain = 'plain'; -const kSubTypeTextXml = 'xml'; -const kSubTypeTextYaml = 'yaml'; -const kSubTypeTextYml = 'yml'; - -const kTypeImage = 'image'; -//image -const kSubTypeSvg = 'svg+xml'; - -const kTypeAudio = 'audio'; -const kTypeVideo = 'video'; - -const kTypeMultipart = "multipart"; -const kSubTypeFormData = "form-data"; - -const kSubTypeDefaultViewOptions = 'all'; - -enum ContentType { - json("$kTypeApplication/$kSubTypeJson"), - text("$kTypeText/$kSubTypePlain"), - formdata("$kTypeMultipart/$kSubTypeFormData"); - - const ContentType(this.header); - final String header; -} - enum ResponseBodyView { preview("Preview", Icons.visibility_rounded), code("Preview", Icons.code_rounded), diff --git a/lib/extensions/extensions.dart b/lib/extensions/extensions.dart index 1c398f76..96498f9b 100644 --- a/lib/extensions/extensions.dart +++ b/lib/extensions/extensions.dart @@ -1,2 +1 @@ export 'context_extensions.dart'; -export 'string_extensions.dart'; diff --git a/lib/importer/curl/curl.dart b/lib/importer/curl/curl.dart index 6807168b..7608c7c2 100644 --- a/lib/importer/curl/curl.dart +++ b/lib/importer/curl/curl.dart @@ -1,6 +1,4 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/utils/utils.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:curl_converter/curl_converter.dart'; class CurlFileImport { diff --git a/lib/importer/importer.dart b/lib/importer/importer.dart index 37c40a28..607bc816 100644 --- a/lib/importer/importer.dart +++ b/lib/importer/importer.dart @@ -1,5 +1,5 @@ import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'curl/curl.dart'; class Importer { diff --git a/lib/main.dart b/lib/main.dart index 7e212dad..8b5fab32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ -import 'package:apidash/providers/settings_providers.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'models/models.dart'; import 'providers/providers.dart'; import 'services/services.dart'; diff --git a/lib/models/environment_model.dart b/lib/models/environment_model.dart index 2d0014fa..7f37fb6f 100644 --- a/lib/models/environment_model.dart +++ b/lib/models/environment_model.dart @@ -1,5 +1,5 @@ import 'package:apidash/consts.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:apidash_core/apidash_core.dart'; part 'environment_model.freezed.dart'; diff --git a/lib/models/history_meta_model.dart b/lib/models/history_meta_model.dart index 9188b6ad..0e2bdb43 100644 --- a/lib/models/history_meta_model.dart +++ b/lib/models/history_meta_model.dart @@ -1,5 +1,4 @@ -import 'package:apidash/consts.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:apidash_core/apidash_core.dart'; part 'history_meta_model.freezed.dart'; diff --git a/lib/models/history_request_model.dart b/lib/models/history_request_model.dart index 5a9a2b53..a895e945 100644 --- a/lib/models/history_request_model.dart +++ b/lib/models/history_request_model.dart @@ -1,4 +1,4 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'models.dart'; part 'history_request_model.freezed.dart'; diff --git a/lib/models/models.dart b/lib/models/models.dart index 2471d12c..d8ea6ac0 100644 --- a/lib/models/models.dart +++ b/lib/models/models.dart @@ -1,9 +1,5 @@ export 'environment_model.dart'; -export 'form_data_model.dart'; export 'history_meta_model.dart'; export 'history_request_model.dart'; -export 'http_request_model.dart'; -export 'http_response_model.dart'; -export 'name_value_model.dart'; export 'request_model.dart'; export 'settings_model.dart'; diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 96da70a3..7cf34c85 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,5 +1,4 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'models.dart'; +import 'package:apidash_core/apidash_core.dart'; part 'request_model.freezed.dart'; diff --git a/lib/models/settings_model.dart b/lib/models/settings_model.dart index 6784f214..c2237a07 100644 --- a/lib/models/settings_model.dart +++ b/lib/models/settings_model.dart @@ -1,3 +1,4 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 02eead40..2f6680f4 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,9 +1,9 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart' as http; import 'package:apidash/consts.dart'; import 'providers.dart'; import '../models/models.dart'; -import '../services/services.dart' show hiveHandler, HiveHandler, request; +import '../services/services.dart' show hiveHandler, HiveHandler; import '../utils/utils.dart' show getNewUuid, collectionToHAR, substituteHttpRequestModel; @@ -259,7 +259,7 @@ class CollectionStateNotifier ); state = map; - (http.Response?, Duration?, String?)? responseRec = await request( + (HttpResponse?, Duration?, String?)? responseRec = await request( substitutedHttpRequestModel, defaultUriScheme: defaultUriScheme, ); diff --git a/lib/screens/common_widgets/editor_title_actions.dart b/lib/screens/common_widgets/editor_title_actions.dart index 51d69798..526e4f0c 100644 --- a/lib/screens/common_widgets/editor_title_actions.dart +++ b/lib/screens/common_widgets/editor_title_actions.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class EditorTitleActions extends StatelessWidget { const EditorTitleActions({ diff --git a/lib/screens/common_widgets/env_trigger_field.dart b/lib/screens/common_widgets/env_trigger_field.dart index 23f01d1b..bccaf048 100644 --- a/lib/screens/common_widgets/env_trigger_field.dart +++ b/lib/screens/common_widgets/env_trigger_field.dart @@ -51,7 +51,8 @@ class EnvironmentTriggerFieldState extends State { @override void didUpdateWidget(EnvironmentTriggerField oldWidget) { super.didUpdateWidget(oldWidget); - if (oldWidget.initialValue != widget.initialValue) { + if ((oldWidget.keyId != widget.keyId) || + (oldWidget.initialValue != widget.initialValue)) { controller.text = widget.initialValue ?? ""; controller.selection = TextSelection.collapsed(offset: controller.text.length); diff --git a/lib/screens/common_widgets/env_trigger_options.dart b/lib/screens/common_widgets/env_trigger_options.dart index 04a21e7d..702209b8 100644 --- a/lib/screens/common_widgets/env_trigger_options.dart +++ b/lib/screens/common_widgets/env_trigger_options.dart @@ -1,4 +1,5 @@ import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/models/models.dart'; diff --git a/lib/screens/common_widgets/envfield_cell.dart b/lib/screens/common_widgets/envfield_cell.dart index 609a2ea8..6eedad02 100644 --- a/lib/screens/common_widgets/envfield_cell.dart +++ b/lib/screens/common_widgets/envfield_cell.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; import 'env_trigger_field.dart'; class EnvCellField extends StatelessWidget { diff --git a/lib/screens/common_widgets/envfield_url.dart b/lib/screens/common_widgets/envfield_url.dart index 8f98e597..2e7e7de5 100644 --- a/lib/screens/common_widgets/envfield_url.dart +++ b/lib/screens/common_widgets/envfield_url.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; import 'env_trigger_field.dart'; diff --git a/lib/screens/common_widgets/environment_dropdown.dart b/lib/screens/common_widgets/environment_dropdown.dart index cad6a17a..fc45febd 100644 --- a/lib/screens/common_widgets/environment_dropdown.dart +++ b/lib/screens/common_widgets/environment_dropdown.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/common_widgets/envvar_indicator.dart b/lib/screens/common_widgets/envvar_indicator.dart index 9f1e861d..bc56fc19 100644 --- a/lib/screens/common_widgets/envvar_indicator.dart +++ b/lib/screens/common_widgets/envvar_indicator.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/screens/common_widgets/envvar_popover.dart b/lib/screens/common_widgets/envvar_popover.dart index 2c017889..3d7b93da 100644 --- a/lib/screens/common_widgets/envvar_popover.dart +++ b/lib/screens/common_widgets/envvar_popover.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart'; import 'common_widgets.dart'; diff --git a/lib/screens/common_widgets/sidebar_filter.dart b/lib/screens/common_widgets/sidebar_filter.dart index ad99bebf..fe0d6a84 100644 --- a/lib/screens/common_widgets/sidebar_filter.dart +++ b/lib/screens/common_widgets/sidebar_filter.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; class SidebarFilter extends StatelessWidget { const SidebarFilter({ diff --git a/lib/screens/common_widgets/sidebar_header.dart b/lib/screens/common_widgets/sidebar_header.dart index 1a26f0ea..2bf472be 100644 --- a/lib/screens/common_widgets/sidebar_header.dart +++ b/lib/screens/common_widgets/sidebar_header.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/common_widgets/sidebar_save_button.dart b/lib/screens/common_widgets/sidebar_save_button.dart index 1a04b197..46390ac4 100644 --- a/lib/screens/common_widgets/sidebar_save_button.dart +++ b/lib/screens/common_widgets/sidebar_save_button.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index d5bce2f1..d71b3008 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/envvar/editor_pane/secrets_pane.dart b/lib/screens/envvar/editor_pane/secrets_pane.dart index e159dfd6..802cd9b0 100644 --- a/lib/screens/envvar/editor_pane/secrets_pane.dart +++ b/lib/screens/envvar/editor_pane/secrets_pane.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; diff --git a/lib/screens/envvar/editor_pane/variables_pane.dart b/lib/screens/envvar/editor_pane/variables_pane.dart index 8af4ba6e..6739530b 100644 --- a/lib/screens/envvar/editor_pane/variables_pane.dart +++ b/lib/screens/envvar/editor_pane/variables_pane.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; diff --git a/lib/screens/envvar/editor_pane/variables_tabs.dart b/lib/screens/envvar/editor_pane/variables_tabs.dart index b03e079c..073d74f1 100644 --- a/lib/screens/envvar/editor_pane/variables_tabs.dart +++ b/lib/screens/envvar/editor_pane/variables_tabs.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -5,7 +6,6 @@ import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import 'variables_pane.dart'; import 'secrets_pane.dart'; diff --git a/lib/screens/envvar/environment_editor.dart b/lib/screens/envvar/environment_editor.dart index 934d7ad8..78ca0f63 100644 --- a/lib/screens/envvar/environment_editor.dart +++ b/lib/screens/envvar/environment_editor.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/envvar/environments_pane.dart b/lib/screens/envvar/environments_pane.dart index 34d58e4b..7939fbc0 100644 --- a/lib/screens/envvar/environments_pane.dart +++ b/lib/screens/envvar/environments_pane.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -153,7 +154,7 @@ class EnvironmentsList extends HookConsumerWidget { ), ); } - return const SizedBox(); + return kSizedBoxEmpty; }).toList(), ), ), @@ -193,6 +194,9 @@ class EnvironmentItem extends ConsumerWidget { ref.read(selectedEnvironmentIdStateProvider.notifier).state = id; kEnvScaffoldKey.currentState?.closeDrawer(); }, + onSecondaryTap: () { + ref.read(selectedEnvironmentIdStateProvider.notifier).state = id; + }, focusNode: ref.watch(nameTextFieldFocusNodeProvider), onChangedNameEditor: (value) { value = value.trim(); diff --git a/lib/screens/history/history_details.dart b/lib/screens/history/history_details.dart index 35d00819..196e4a33 100644 --- a/lib/screens/history/history_details.dart +++ b/lib/screens/history/history_details.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; diff --git a/lib/screens/history/history_pane.dart b/lib/screens/history/history_pane.dart index d76eac17..45f0abce 100644 --- a/lib/screens/history/history_pane.dart +++ b/lib/screens/history/history_pane.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; diff --git a/lib/screens/history/history_requests.dart b/lib/screens/history/history_requests.dart index 49f6fc10..8bf4ea32 100644 --- a/lib/screens/history/history_requests.dart +++ b/lib/screens/history/history_requests.dart @@ -1,10 +1,10 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/utils/history_utils.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; class HistoryRequests extends ConsumerWidget { const HistoryRequests({ diff --git a/lib/screens/history/history_viewer.dart b/lib/screens/history/history_viewer.dart index 4dbb5faf..d9a240d5 100644 --- a/lib/screens/history/history_viewer.dart +++ b/lib/screens/history/history_viewer.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/widgets/widgets.dart'; diff --git a/lib/screens/history/history_widgets/his_bottombar.dart b/lib/screens/history/history_widgets/his_bottombar.dart index da6b0ffe..4cc0e8a7 100644 --- a/lib/screens/history/history_widgets/his_bottombar.dart +++ b/lib/screens/history/history_widgets/his_bottombar.dart @@ -1,9 +1,9 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import '../history_requests.dart'; import 'his_action_buttons.dart'; diff --git a/lib/screens/history/history_widgets/his_request_pane.dart b/lib/screens/history/history_widgets/his_request_pane.dart index a2ad35b2..f24fd668 100644 --- a/lib/screens/history/history_widgets/his_request_pane.dart +++ b/lib/screens/history/history_widgets/his_request_pane.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/history/history_widgets/his_sidebar_header.dart b/lib/screens/history/history_widgets/his_sidebar_header.dart index 6af1e1e8..c7d33cc0 100644 --- a/lib/screens/history/history_widgets/his_sidebar_header.dart +++ b/lib/screens/history/history_widgets/his_sidebar_header.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/extensions/extensions.dart'; diff --git a/lib/screens/history/history_widgets/his_url_card.dart b/lib/screens/history/history_widgets/his_url_card.dart index f0e70a2e..80d9a946 100644 --- a/lib/screens/history/history_widgets/his_url_card.dart +++ b/lib/screens/history/history_widgets/his_url_card.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/models/models.dart'; diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index b30eded2..113bd9a7 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -190,7 +191,7 @@ class _RequestListState extends ConsumerState { ), ); } - return const SizedBox(); + return kSizedBoxEmpty; }).toList(), ), ); @@ -223,6 +224,9 @@ class RequestItem extends ConsumerWidget { ref.read(selectedIdStateProvider.notifier).state = id; kHomeScaffoldKey.currentState?.closeDrawer(); }, + onSecondaryTap: () { + ref.read(selectedIdStateProvider.notifier).state = id; + }, // onDoubleTap: () { // ref.read(selectedIdStateProvider.notifier).state = id; // ref.read(selectedIdEditStateProvider.notifier).state = id; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 86ac5a2f..31c52de4 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 9b0bb123..a25faebd 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -1,10 +1,11 @@ import 'dart:math'; +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/models/models.dart'; import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index ae083217..c745ec05 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,10 +1,11 @@ import 'dart:math'; +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/screens/common_widgets/common_widgets.dart'; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 861b95d5..c7ee365f 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -1,10 +1,11 @@ import 'dart:math'; +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/screens/common_widgets/common_widgets.dart'; diff --git a/lib/screens/home_page/editor_pane/editor_default.dart b/lib/screens/home_page/editor_pane/editor_default.dart index 8ebc0645..757d1c30 100644 --- a/lib/screens/home_page/editor_pane/editor_default.dart +++ b/lib/screens/home_page/editor_pane/editor_default.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/home_page/editor_pane/editor_request.dart b/lib/screens/home_page/editor_pane/editor_request.dart index 52f49a3f..dc800b1a 100644 --- a/lib/screens/home_page/editor_pane/editor_request.dart +++ b/lib/screens/home_page/editor_pane/editor_request.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/home_page/editor_pane/url_card.dart b/lib/screens/home_page/editor_pane/url_card.dart index 8640510c..e737609f 100644 --- a/lib/screens/home_page/editor_pane/url_card.dart +++ b/lib/screens/home_page/editor_pane/url_card.dart @@ -1,8 +1,9 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/extensions/extensions.dart'; import '../../common_widgets/common_widgets.dart'; diff --git a/lib/screens/mobile/requests_page/request_tabs.dart b/lib/screens/mobile/requests_page/request_tabs.dart index 7d542095..1cfe1ef0 100644 --- a/lib/screens/mobile/requests_page/request_tabs.dart +++ b/lib/screens/mobile/requests_page/request_tabs.dart @@ -1,4 +1,5 @@ import 'package:apidash/screens/common_widgets/common_widgets.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/screens/mobile/requests_page/requests_page.dart b/lib/screens/mobile/requests_page/requests_page.dart index f9c986d9..77fc6ce7 100644 --- a/lib/screens/mobile/requests_page/requests_page.dart +++ b/lib/screens/mobile/requests_page/requests_page.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:apidash/providers/providers.dart'; diff --git a/lib/screens/mobile/widgets/page_base.dart b/lib/screens/mobile/widgets/page_base.dart index 310e5cc6..fb4e98b1 100644 --- a/lib/screens/mobile/widgets/page_base.dart +++ b/lib/screens/mobile/widgets/page_base.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/screens/settings_page.dart b/lib/screens/settings_page.dart index 933b54b9..f3b784e9 100644 --- a/lib/screens/settings_page.dart +++ b/lib/screens/settings_page.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/providers.dart'; diff --git a/lib/services/services.dart b/lib/services/services.dart index fd8ca0b0..7fa8128d 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -1,4 +1,3 @@ -export 'http_service.dart'; export 'hive_services.dart'; export 'history_service.dart'; export 'window_services.dart'; diff --git a/lib/services/shared_preferences_services.dart b/lib/services/shared_preferences_services.dart index 89d4b590..490413b9 100644 --- a/lib/services/shared_preferences_services.dart +++ b/lib/services/shared_preferences_services.dart @@ -1,6 +1,6 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../models/models.dart'; const String kSharedPrefSettingsKey = 'apidash-settings'; diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index b3c3b2bc..6242f307 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -1,11 +1,7 @@ import 'dart:typed_data'; import 'dart:convert'; -import 'package:apidash/extensions/extensions.dart'; -import 'package:collection/collection.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:intl/intl.dart'; -import '../models/models.dart'; -import '../consts.dart'; -import 'package:http/http.dart' as http; String humanizeDate(DateTime? date) { if (date == null) { @@ -66,76 +62,6 @@ String padMultilineString(String text, int padding, return lines.join("\n"); } -Map? rowsToMap(List? kvRows, - {bool isHeader = false}) { - if (kvRows == null) { - return null; - } - Map finalMap = {}; - for (var row in kvRows) { - if (row.name.trim() != "") { - String key = row.name; - if (isHeader) { - key = key.toLowerCase(); - } - finalMap[key] = row.value.toString(); - } - } - return finalMap; -} - -List? mapToRows(Map? kvMap) { - if (kvMap == null) { - return null; - } - List finalRows = []; - for (var k in kvMap.keys) { - finalRows.add(NameValueModel(name: k, value: kvMap[k])); - } - return finalRows; -} - -List>? rowsToFormDataMapList( - List? kvRows, -) { - if (kvRows == null) { - return null; - } - List> finalMap = kvRows - .map((FormDataModel formData) => - (formData.name.trim().isEmpty && formData.value.trim().isEmpty) - ? null - : { - "name": formData.name, - "value": formData.value, - "type": formData.type.name, - }) - .whereNotNull() - .toList(); - return finalMap; -} - -List? mapListToFormDataModelRows(List? kvMap) { - if (kvMap == null) { - return null; - } - List finalRows = kvMap.map( - (formData) { - return FormDataModel( - name: formData["name"], - value: formData["value"], - type: getFormDataType(formData["type"]), - ); - }, - ).toList(); - return finalRows; -} - -FormDataType getFormDataType(String? type) { - return FormDataType.values.firstWhere((element) => element.name == type, - orElse: () => FormDataType.text); -} - Uint8List? stringToBytes(String? text) { if (text == null) { return null; @@ -156,30 +82,3 @@ Uint8List jsonMapToBytes(Map? map) { return bytes; } } - -Future convertStreamedResponse( - http.StreamedResponse streamedResponse, -) async { - Uint8List bodyBytes = await streamedResponse.stream.toBytes(); - - http.Response response = http.Response.bytes( - bodyBytes, - streamedResponse.statusCode, - headers: streamedResponse.headers, - persistentConnection: streamedResponse.persistentConnection, - reasonPhrase: streamedResponse.reasonPhrase, - request: streamedResponse.request, - ); - - return response; -} - -List? getEnabledRows( - List? rows, List? isRowEnabledList) { - if (rows == null || isRowEnabledList == null) { - return rows; - } - List finalRows = - rows.where((element) => isRowEnabledList[rows.indexOf(element)]).toList(); - return finalRows == [] ? null : finalRows; -} diff --git a/lib/utils/envvar_utils.dart b/lib/utils/envvar_utils.dart index 01e6440f..af0195ff 100644 --- a/lib/utils/envvar_utils.dart +++ b/lib/utils/envvar_utils.dart @@ -1,4 +1,4 @@ -import 'package:collection/collection.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart'; diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index 7912ed86..5f74f819 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -3,9 +3,9 @@ import 'dart:convert'; import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' - show getValidRequestUri, getNewUuid, getFilenameFromPath; +import 'package:apidash/utils/utils.dart' show getNewUuid, getFilenameFromPath; import 'package:apidash/models/models.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:package_info_plus/package_info_plus.dart'; Future> collectionToHAR( diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index e12f029f..9fcfc677 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -1,10 +1,4 @@ -import 'dart:convert'; -import 'dart:io'; -import 'package:collection/collection.dart' show mergeMaps; -import 'package:http_parser/http_parser.dart'; -import 'package:xml/xml.dart'; -import '../models/models.dart'; -import 'convert_utils.dart' show rowsToMap; +import 'package:apidash_core/apidash_core.dart'; import '../consts.dart'; String getRequestTitleFromUrl(String? url) { @@ -21,84 +15,6 @@ String getRequestTitleFromUrl(String? url) { return url; } -String? getContentTypeFromHeaders(Map? headers) { - return headers?[HttpHeaders.contentTypeHeader]; -} - -MediaType? getMediaTypeFromContentType(String? contentType) { - if (contentType != null) { - try { - MediaType mediaType = MediaType.parse(contentType); - return mediaType; - } catch (e) { - return null; - } - } - return null; -} - -MediaType? getMediaTypeFromHeaders(Map? headers) { - var contentType = getContentTypeFromHeaders(headers); - MediaType? mediaType = getMediaTypeFromContentType(contentType); - return mediaType; -} - -(String?, bool) getUriScheme(Uri uri) { - if (uri.hasScheme) { - if (kSupportedUriSchemes.contains(uri.scheme)) { - return (uri.scheme, true); - } - return (uri.scheme, false); - } - return (null, false); -} - -String stripUriParams(Uri uri) { - return "${uri.scheme}://${uri.authority}${uri.path}"; -} - -String stripUrlParams(String url) { - var idx = url.indexOf("?"); - return idx > 0 ? url.substring(0, idx) : url; -} - -(Uri?, String?) getValidRequestUri( - String? url, List? requestParams, - {String defaultUriScheme = kDefaultUriScheme}) { - url = url?.trim(); - if (url == null || url == "") { - return (null, "URL is missing!"); - } - Uri? uri = Uri.tryParse(url); - if (uri == null) { - return (null, "Check URL (malformed)"); - } - (String?, bool) urlScheme = getUriScheme(uri); - - if (urlScheme.$1 != null) { - if (!urlScheme.$2) { - return (null, "Unsupported URL Scheme (${urlScheme.$1})"); - } - } else { - url = "$defaultUriScheme://$url"; - } - - uri = Uri.parse(url); - if (uri.hasFragment) { - uri = uri.removeFragment(); - } - - Map? queryParams = rowsToMap(requestParams); - if (queryParams != null && queryParams.isNotEmpty) { - if (uri.hasQuery) { - Map urlQueryParams = uri.queryParameters; - queryParams = mergeMaps(urlQueryParams, queryParams); - } - uri = uri.replace(queryParameters: queryParams); - } - return (uri, null); -} - (List, String?) getResponseBodyViewOptions( MediaType? mediaType) { if (mediaType == null) { @@ -132,32 +48,3 @@ String stripUrlParams(String url) { } return (kNoBodyViewOptions, null); } - -String? formatBody(String? body, MediaType? mediaType) { - if (mediaType != null && body != null) { - var subtype = mediaType.subtype; - try { - if (subtype.contains(kSubTypeJson)) { - final tmp = jsonDecode(body); - String result = kJsonEncoder.convert(tmp); - return result; - } - if (subtype.contains(kSubTypeXml)) { - final document = XmlDocument.parse(body); - String result = document.toXmlString(pretty: true, indent: ' '); - return result; - } - if (subtype == kSubTypeHtml) { - var len = body.length; - var lines = kSplitter.convert(body); - var numOfLines = lines.length; - if (numOfLines != 0 && len / numOfLines <= kCodeCharsPerLineLimit) { - return body; - } - } - } catch (e) { - return null; - } - } - return null; -} diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index 764c821b..9f4c6a64 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import '../consts.dart'; diff --git a/lib/widgets/button_discord.dart b/lib/widgets/button_discord.dart index 1b348944..54af85fe 100644 --- a/lib/widgets/button_discord.dart +++ b/lib/widgets/button_discord.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/button_form_data_file.dart b/lib/widgets/button_form_data_file.dart index 262ea76b..bbe4c89a 100644 --- a/lib/widgets/button_form_data_file.dart +++ b/lib/widgets/button_form_data_file.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/button_group_filled.dart b/lib/widgets/button_group_filled.dart index 722ed403..1e658458 100644 --- a/lib/widgets/button_group_filled.dart +++ b/lib/widgets/button_group_filled.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class ButtonData { ButtonData({ diff --git a/lib/widgets/button_repo.dart b/lib/widgets/button_repo.dart index 2ff81696..15bfb99b 100644 --- a/lib/widgets/button_repo.dart +++ b/lib/widgets/button_repo.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/button_send.dart b/lib/widgets/button_send.dart index 37d51dd3..e96adcdb 100644 --- a/lib/widgets/button_send.dart +++ b/lib/widgets/button_send.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/card_history_request.dart b/lib/widgets/card_history_request.dart index 228cbf5b..53f994e8 100644 --- a/lib/widgets/card_history_request.dart +++ b/lib/widgets/card_history_request.dart @@ -1,7 +1,7 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import 'texts.dart'; class HistoryRequestCard extends StatelessWidget { diff --git a/lib/widgets/card_request_details.dart b/lib/widgets/card_request_details.dart index 282aec0e..f953435c 100644 --- a/lib/widgets/card_request_details.dart +++ b/lib/widgets/card_request_details.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class RequestDetailsCard extends StatelessWidget { const RequestDetailsCard({super.key, this.child}); diff --git a/lib/widgets/card_sidebar_environment.dart b/lib/widgets/card_sidebar_environment.dart index 48f153ed..413974db 100644 --- a/lib/widgets/card_sidebar_environment.dart +++ b/lib/widgets/card_sidebar_environment.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart'; @@ -69,7 +70,13 @@ class SidebarEnvironmentCard extends StatelessWidget { hoverColor: colorVariant, focusColor: colorVariant.withOpacity(0.5), onTap: inEditMode ? null : onTap, - onSecondaryTap: onSecondaryTap, + // onSecondaryTap: onSecondaryTap, + onSecondaryTapUp: (isGlobal) + ? null + : (details) { + onSecondaryTap?.call(); + showItemCardMenu(context, details, onMenuSelected); + }, child: Padding( padding: EdgeInsets.only( left: 6, @@ -90,6 +97,7 @@ class SidebarEnvironmentCard extends StatelessWidget { focusNode: focusNode, style: Theme.of(context).textTheme.bodyMedium, onTapOutside: (_) { + FocusScope.of(context).unfocus(); onTapOutsideNameEditor?.call(); }, onFieldSubmitted: (value) { diff --git a/lib/widgets/card_sidebar_history.dart b/lib/widgets/card_sidebar_history.dart index 9b1a9f20..49378125 100644 --- a/lib/widgets/card_sidebar_history.dart +++ b/lib/widgets/card_sidebar_history.dart @@ -1,7 +1,8 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import 'texts.dart' show MethodBox; class SidebarHistoryCard extends StatelessWidget { diff --git a/lib/widgets/card_sidebar_request.dart b/lib/widgets/card_sidebar_request.dart index ab8a4706..23455fbd 100644 --- a/lib/widgets/card_sidebar_request.dart +++ b/lib/widgets/card_sidebar_request.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart'; @@ -71,7 +73,10 @@ class SidebarRequestCard extends StatelessWidget { focusColor: colorVariant.withOpacity(0.5), onTap: inEditMode ? null : onTap, // onDoubleTap: inEditMode ? null : onDoubleTap, - onSecondaryTap: onSecondaryTap, + onSecondaryTapUp: (details) { + onSecondaryTap?.call(); + showItemCardMenu(context, details, onMenuSelected); + }, child: Padding( padding: EdgeInsets.only( left: 6, @@ -95,8 +100,8 @@ class SidebarRequestCard extends StatelessWidget { //autofocus: true, style: Theme.of(context).textTheme.bodyMedium, onTapOutside: (_) { + FocusScope.of(context).unfocus(); onTapOutsideNameEditor?.call(); - //FocusScope.of(context).unfocus(); }, onFieldSubmitted: (value) { onTapOutsideNameEditor?.call(); diff --git a/lib/widgets/code_previewer.dart b/lib/widgets/code_previewer.dart index b4e7223b..f805d7f6 100644 --- a/lib/widgets/code_previewer.dart +++ b/lib/widgets/code_previewer.dart @@ -1,3 +1,4 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:highlighter/highlighter.dart' show highlight, Node; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/codegen_previewer.dart b/lib/widgets/codegen_previewer.dart index 2ee02755..5c4aa912 100644 --- a/lib/widgets/codegen_previewer.dart +++ b/lib/widgets/codegen_previewer.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:highlighter/highlighter.dart' show highlight; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/dialog_about.dart b/lib/widgets/dialog_about.dart index 48362f44..9ebeb371 100644 --- a/lib/widgets/dialog_about.dart +++ b/lib/widgets/dialog_about.dart @@ -1,4 +1,4 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; diff --git a/lib/widgets/dialog_history_retention.dart b/lib/widgets/dialog_history_retention.dart index 67f513ac..3cec2b8c 100644 --- a/lib/widgets/dialog_history_retention.dart +++ b/lib/widgets/dialog_history_retention.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/dialog_rename.dart b/lib/widgets/dialog_rename.dart index ee2f9f77..f2c16eb0 100644 --- a/lib/widgets/dialog_rename.dart +++ b/lib/widgets/dialog_rename.dart @@ -1,4 +1,4 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; showRenameDialog( diff --git a/lib/widgets/drag_and_drop_area.dart b/lib/widgets/drag_and_drop_area.dart index 1babea8b..a8b2108a 100644 --- a/lib/widgets/drag_and_drop_area.dart +++ b/lib/widgets/drag_and_drop_area.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:desktop_drop/desktop_drop.dart'; import 'package:file_selector/file_selector.dart'; diff --git a/lib/widgets/dropdown_codegen.dart b/lib/widgets/dropdown_codegen.dart index 4e158377..30b3dbd9 100644 --- a/lib/widgets/dropdown_codegen.dart +++ b/lib/widgets/dropdown_codegen.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/dropdown_content_type.dart b/lib/widgets/dropdown_content_type.dart index 952dcad1..964029d0 100644 --- a/lib/widgets/dropdown_content_type.dart +++ b/lib/widgets/dropdown_content_type.dart @@ -1,5 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class DropdownButtonContentType extends StatelessWidget { const DropdownButtonContentType({ diff --git a/lib/widgets/dropdown_formdata.dart b/lib/widgets/dropdown_formdata.dart index 02645afa..fc59e53a 100644 --- a/lib/widgets/dropdown_formdata.dart +++ b/lib/widgets/dropdown_formdata.dart @@ -1,5 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class DropdownButtonFormData extends StatelessWidget { const DropdownButtonFormData({ diff --git a/lib/widgets/dropdown_http_method.dart b/lib/widgets/dropdown_http_method.dart index 81623325..fa34e359 100644 --- a/lib/widgets/dropdown_http_method.dart +++ b/lib/widgets/dropdown_http_method.dart @@ -1,6 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/extensions/extensions.dart'; class DropdownButtonHttpMethod extends StatelessWidget { diff --git a/lib/widgets/dropdown_import_format.dart b/lib/widgets/dropdown_import_format.dart index 277b92b6..13afd668 100644 --- a/lib/widgets/dropdown_import_format.dart +++ b/lib/widgets/dropdown_import_format.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/editor.dart b/lib/widgets/editor.dart index 5bdd2f82..18b391b9 100644 --- a/lib/widgets/editor.dart +++ b/lib/widgets/editor.dart @@ -1,7 +1,7 @@ import 'dart:math' as math; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:apidash/consts.dart'; class TextFieldEditor extends StatefulWidget { const TextFieldEditor({ diff --git a/lib/widgets/editor_json.dart b/lib/widgets/editor_json.dart index 949af6fc..1c1af0d1 100644 --- a/lib/widgets/editor_json.dart +++ b/lib/widgets/editor_json.dart @@ -1,8 +1,8 @@ import 'dart:math' as math; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:json_text_field/json_text_field.dart'; -import 'package:apidash/consts.dart'; class JsonTextFieldEditor extends StatefulWidget { const JsonTextFieldEditor({ diff --git a/lib/widgets/error_message.dart b/lib/widgets/error_message.dart index ed8a2cb8..dedb83e2 100644 --- a/lib/widgets/error_message.dart +++ b/lib/widgets/error_message.dart @@ -1,4 +1,5 @@ import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/lib/widgets/field_cell.dart b/lib/widgets/field_cell.dart index f750368f..1f588019 100644 --- a/lib/widgets/field_cell.dart +++ b/lib/widgets/field_cell.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class CellField extends StatelessWidget { const CellField({ diff --git a/lib/widgets/field_cell_obscurable.dart b/lib/widgets/field_cell_obscurable.dart index 61aa4bbe..33e41978 100644 --- a/lib/widgets/field_cell_obscurable.dart +++ b/lib/widgets/field_cell_obscurable.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class ObscurableCellField extends HookWidget { diff --git a/lib/widgets/field_header.dart b/lib/widgets/field_header.dart index 2f1236fe..90a5cd76 100644 --- a/lib/widgets/field_header.dart +++ b/lib/widgets/field_header.dart @@ -1,7 +1,7 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; class HeaderField extends StatefulWidget { const HeaderField({ diff --git a/lib/widgets/field_json_search.dart b/lib/widgets/field_json_search.dart index b9a61992..1b435d89 100644 --- a/lib/widgets/field_json_search.dart +++ b/lib/widgets/field_json_search.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; import 'field_raw.dart'; class JsonSearchField extends StatelessWidget { diff --git a/lib/widgets/field_outlined.dart b/lib/widgets/field_outlined.dart index 0c981543..f464488e 100644 --- a/lib/widgets/field_outlined.dart +++ b/lib/widgets/field_outlined.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class OutlinedField extends StatelessWidget { const OutlinedField({ diff --git a/lib/widgets/field_raw.dart b/lib/widgets/field_raw.dart index 1f216b74..23ec43d8 100644 --- a/lib/widgets/field_raw.dart +++ b/lib/widgets/field_raw.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class RawTextField extends StatelessWidget { const RawTextField({ diff --git a/lib/widgets/field_read_only.dart b/lib/widgets/field_read_only.dart index abdb0b4e..4fe7d579 100644 --- a/lib/widgets/field_read_only.dart +++ b/lib/widgets/field_read_only.dart @@ -1,5 +1,5 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; -import 'package:apidash/consts.dart'; class ReadOnlyTextField extends StatelessWidget { const ReadOnlyTextField({ diff --git a/lib/widgets/field_url.dart b/lib/widgets/field_url.dart index f20342bc..a2afb524 100644 --- a/lib/widgets/field_url.dart +++ b/lib/widgets/field_url.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/json_previewer.dart b/lib/widgets/json_previewer.dart index 020015d6..6c3fd3c9 100644 --- a/lib/widgets/json_previewer.dart +++ b/lib/widgets/json_previewer.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:json_data_explorer/json_data_explorer.dart'; diff --git a/lib/widgets/menu_item_card.dart b/lib/widgets/menu_item_card.dart index 5aa9fadb..e31a68b4 100644 --- a/lib/widgets/menu_item_card.dart +++ b/lib/widgets/menu_item_card.dart @@ -41,3 +41,29 @@ class ItemCardMenu extends StatelessWidget { ); } } + +/// Open the item card menu where the right click has been released +Future showItemCardMenu( + BuildContext context, + TapUpDetails details, + Function(ItemMenuOption)? onSelected, +) async { + showMenu( + context: context, + position: RelativeRect.fromLTRB( + details.globalPosition.dx, + details.globalPosition.dy, + details.globalPosition.dx, + details.globalPosition.dy, + ), + items: ItemMenuOption.values + .map>( + (e) => PopupMenuItem( + onTap: () => onSelected?.call(e), + value: e, + child: Text(e.label), + ), + ) + .toList(), + ); +} diff --git a/lib/widgets/overlay_widget.dart b/lib/widgets/overlay_widget.dart index ed800521..9f17c2e7 100644 --- a/lib/widgets/overlay_widget.dart +++ b/lib/widgets/overlay_widget.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; import '../consts.dart'; diff --git a/lib/widgets/popup_menu_codegen.dart b/lib/widgets/popup_menu_codegen.dart index 9d1c3bc4..a978d906 100644 --- a/lib/widgets/popup_menu_codegen.dart +++ b/lib/widgets/popup_menu_codegen.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/popup_menu_env.dart b/lib/widgets/popup_menu_env.dart index 63b6034e..0a58ef58 100644 --- a/lib/widgets/popup_menu_env.dart +++ b/lib/widgets/popup_menu_env.dart @@ -1,8 +1,9 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; class EnvironmentPopupMenu extends StatelessWidget { const EnvironmentPopupMenu({ diff --git a/lib/widgets/popup_menu_history.dart b/lib/widgets/popup_menu_history.dart index 4dfba84b..fd8a9c4f 100644 --- a/lib/widgets/popup_menu_history.dart +++ b/lib/widgets/popup_menu_history.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/popup_menu_uri.dart b/lib/widgets/popup_menu_uri.dart index 418c6a71..c485c0fc 100644 --- a/lib/widgets/popup_menu_uri.dart +++ b/lib/widgets/popup_menu_uri.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/extensions/extensions.dart'; -import 'package:apidash/consts.dart'; class URIPopupMenu extends StatelessWidget { const URIPopupMenu({ diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart index 511d1e4b..36b9ce62 100644 --- a/lib/widgets/previewer.dart +++ b/lib/widgets/previewer.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:jinja/jinja.dart' as jj; diff --git a/lib/widgets/request_widgets.dart b/lib/widgets/request_widgets.dart index 5ad400aa..1b2bf00d 100644 --- a/lib/widgets/request_widgets.dart +++ b/lib/widgets/request_widgets.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:apidash/extensions/extensions.dart'; diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 7b269fc1..2877c801 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,7 +1,8 @@ import 'dart:async'; +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:http_parser/http_parser.dart'; import 'package:lottie/lottie.dart'; import 'package:apidash/utils/utils.dart'; import 'package:apidash/widgets/widgets.dart'; diff --git a/lib/widgets/splitview_dashboard.dart b/lib/widgets/splitview_dashboard.dart index ad27204f..e8b4c1f5 100644 --- a/lib/widgets/splitview_dashboard.dart +++ b/lib/widgets/splitview_dashboard.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:multi_split_view/multi_split_view.dart'; -import 'package:apidash/consts.dart'; class DashboardSplitView extends StatefulWidget { const DashboardSplitView({ diff --git a/lib/widgets/splitview_drawer.dart b/lib/widgets/splitview_drawer.dart index 576e525d..210d2788 100644 --- a/lib/widgets/splitview_drawer.dart +++ b/lib/widgets/splitview_drawer.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/splitview_equal.dart b/lib/widgets/splitview_equal.dart index b8d0309a..522726dc 100644 --- a/lib/widgets/splitview_equal.dart +++ b/lib/widgets/splitview_equal.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:multi_split_view/multi_split_view.dart'; -import 'package:apidash/consts.dart'; class EqualSplitView extends StatelessWidget { const EqualSplitView({ diff --git a/lib/widgets/splitview_history.dart b/lib/widgets/splitview_history.dart index b955eaeb..7ff7348f 100644 --- a/lib/widgets/splitview_history.dart +++ b/lib/widgets/splitview_history.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:multi_split_view/multi_split_view.dart'; -import 'package:apidash/consts.dart'; class HistorySplitView extends StatefulWidget { const HistorySplitView({ diff --git a/lib/widgets/tabbar_segmented.dart b/lib/widgets/tabbar_segmented.dart index bb58dc13..62c7576a 100644 --- a/lib/widgets/tabbar_segmented.dart +++ b/lib/widgets/tabbar_segmented.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/table_map.dart b/lib/widgets/table_map.dart index 6a4a9304..4cc927da 100644 --- a/lib/widgets/table_map.dart +++ b/lib/widgets/table_map.dart @@ -1,6 +1,6 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; class MapTable extends StatelessWidget { const MapTable( diff --git a/lib/widgets/table_request.dart b/lib/widgets/table_request.dart index 8c3d9055..1fda5f75 100644 --- a/lib/widgets/table_request.dart +++ b/lib/widgets/table_request.dart @@ -1,3 +1,4 @@ +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/consts.dart'; diff --git a/lib/widgets/table_request_form.dart b/lib/widgets/table_request_form.dart index 91a1b39d..dd3f196c 100644 --- a/lib/widgets/table_request_form.dart +++ b/lib/widgets/table_request_form.dart @@ -1,6 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:data_table_2/data_table_2.dart'; -import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; import 'button_form_data_file.dart'; import 'field_read_only.dart'; diff --git a/lib/widgets/tabs.dart b/lib/widgets/tabs.dart index c2542a26..7001db91 100644 --- a/lib/widgets/tabs.dart +++ b/lib/widgets/tabs.dart @@ -1,5 +1,6 @@ -import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; +import 'package:flutter/material.dart'; class TabLabel extends StatelessWidget { const TabLabel({ diff --git a/lib/widgets/texts.dart b/lib/widgets/texts.dart index 71753bfc..1db15516 100644 --- a/lib/widgets/texts.dart +++ b/lib/widgets/texts.dart @@ -1,6 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; class MethodBox extends StatelessWidget { const MethodBox({super.key, required this.method}); diff --git a/lib/widgets/uint8_audio_player.dart b/lib/widgets/uint8_audio_player.dart index 30b751dd..39c047b1 100644 --- a/lib/widgets/uint8_audio_player.dart +++ b/lib/widgets/uint8_audio_player.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; -import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; diff --git a/lib/widgets/workspace_selector.dart b/lib/widgets/workspace_selector.dart index 2d41b311..af72ba6d 100644 --- a/lib/widgets/workspace_selector.dart +++ b/lib/widgets/workspace_selector.dart @@ -1,4 +1,5 @@ import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; diff --git a/melos.yaml b/melos.yaml new file mode 100644 index 00000000..76344628 --- /dev/null +++ b/melos.yaml @@ -0,0 +1,17 @@ +name: apidash + +packages: + - packages/** + +scripts: + analyze: + run: melos exec -- "flutter analyze" + description: Analyze all packages + + test: + run: melos exec --dir-exists=test -- "flutter test --coverage" + description: Run tests for all packages + + pub-get: + run: melos exec -- "flutter pub get" + description: Run pub get for all packages diff --git a/packages/apidash_core/.gitignore b/packages/apidash_core/.gitignore new file mode 100644 index 00000000..04a9b6ff --- /dev/null +++ b/packages/apidash_core/.gitignore @@ -0,0 +1,32 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ + +.vscode/ +coverage/ diff --git a/packages/apidash_core/CHANGELOG.md b/packages/apidash_core/CHANGELOG.md new file mode 100644 index 00000000..41cc7d81 --- /dev/null +++ b/packages/apidash_core/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/apidash_core/LICENSE b/packages/apidash_core/LICENSE new file mode 100644 index 00000000..d036f89e --- /dev/null +++ b/packages/apidash_core/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 Ankit Mahato, Ashita Prasad + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/apidash_core/README.md b/packages/apidash_core/README.md new file mode 100644 index 00000000..8ee4276d --- /dev/null +++ b/packages/apidash_core/README.md @@ -0,0 +1 @@ +# API Dash Core diff --git a/packages/apidash_core/analysis_options.yaml b/packages/apidash_core/analysis_options.yaml new file mode 100644 index 00000000..2b9df220 --- /dev/null +++ b/packages/apidash_core/analysis_options.yaml @@ -0,0 +1,10 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options +analyzer: + errors: + invalid_annotation_target: ignore + exclude: + - "**/*.freezed.dart" + - "**/*.g.dart" diff --git a/packages/apidash_core/lib/apidash_core.dart b/packages/apidash_core/lib/apidash_core.dart new file mode 100644 index 00000000..5832bebd --- /dev/null +++ b/packages/apidash_core/lib/apidash_core.dart @@ -0,0 +1,13 @@ +library apidash_core; + +export 'consts.dart'; +export 'extensions/extensions.dart'; +export 'models/models.dart'; +export 'utils/utils.dart'; +export 'services/services.dart'; + +// Export 3rd party packages +export 'package:collection/collection.dart'; +export 'package:freezed_annotation/freezed_annotation.dart'; +export 'package:http/http.dart'; +export 'package:http_parser/http_parser.dart'; diff --git a/packages/apidash_core/lib/consts.dart b/packages/apidash_core/lib/consts.dart new file mode 100644 index 00000000..d2544d04 --- /dev/null +++ b/packages/apidash_core/lib/consts.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +enum HTTPVerb { get, head, post, put, patch, delete } + +enum FormDataType { text, file } + +enum SupportedUriSchemes { https, http } + +final kSupportedUriSchemes = + SupportedUriSchemes.values.map((i) => i.name).toList(); +const kDefaultUriScheme = "https"; +final kLocalhostRegex = RegExp(r'^localhost(:\d+)?(/.*)?$'); + +const kMethodsWithBody = [ + HTTPVerb.post, + HTTPVerb.put, + HTTPVerb.patch, + HTTPVerb.delete, +]; + +const kDefaultHttpMethod = HTTPVerb.get; +const kDefaultContentType = ContentType.json; + +const kTypeApplication = 'application'; +// application +const kSubTypeJson = 'json'; +const kSubTypeOctetStream = 'octet-stream'; +const kSubTypePdf = 'pdf'; +const kSubTypeSql = 'sql'; +const kSubTypeXml = 'xml'; +const kSubTypeYaml = 'yaml'; +const kSubTypeXYaml = 'x-yaml'; +const kSubTypeYml = 'x-yml'; +const kSubTypeXWwwFormUrlencoded = 'x-www-form-urlencoded'; + +const kTypeText = 'text'; +// text +const kSubTypeCss = 'css'; +const kSubTypeCsv = 'csv'; +const kSubTypeHtml = 'html'; +const kSubTypeJavascript = 'javascript'; +const kSubTypeMarkdown = 'markdown'; +const kSubTypePlain = 'plain'; +const kSubTypeTextXml = 'xml'; +const kSubTypeTextYaml = 'yaml'; +const kSubTypeTextYml = 'yml'; + +const kTypeImage = 'image'; +//image +const kSubTypeSvg = 'svg+xml'; + +const kTypeAudio = 'audio'; +const kTypeVideo = 'video'; + +const kTypeMultipart = "multipart"; +const kSubTypeFormData = "form-data"; + +const kSubTypeDefaultViewOptions = 'all'; + +enum ContentType { + json("$kTypeApplication/$kSubTypeJson"), + text("$kTypeText/$kSubTypePlain"), + formdata("$kTypeMultipart/$kSubTypeFormData"); + + const ContentType(this.header); + final String header; +} + +const JsonEncoder kJsonEncoder = JsonEncoder.withIndent(' '); +const JsonDecoder kJsonDecoder = JsonDecoder(); +const LineSplitter kSplitter = LineSplitter(); + +const kCodeCharsPerLineLimit = 200; + +const kHeaderContentType = "Content-Type"; diff --git a/packages/apidash_core/lib/extensions/extensions.dart b/packages/apidash_core/lib/extensions/extensions.dart new file mode 100644 index 00000000..d8c9fa84 --- /dev/null +++ b/packages/apidash_core/lib/extensions/extensions.dart @@ -0,0 +1 @@ +export 'string_extensions.dart'; diff --git a/lib/extensions/string_extensions.dart b/packages/apidash_core/lib/extensions/string_extensions.dart similarity index 100% rename from lib/extensions/string_extensions.dart rename to packages/apidash_core/lib/extensions/string_extensions.dart diff --git a/lib/models/form_data_model.dart b/packages/apidash_core/lib/models/form_data_model.dart similarity index 93% rename from lib/models/form_data_model.dart rename to packages/apidash_core/lib/models/form_data_model.dart index add20833..1ffc25d6 100644 --- a/lib/models/form_data_model.dart +++ b/packages/apidash_core/lib/models/form_data_model.dart @@ -1,5 +1,5 @@ -import 'package:apidash/consts.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import '../consts.dart'; part 'form_data_model.freezed.dart'; part 'form_data_model.g.dart'; diff --git a/lib/models/form_data_model.freezed.dart b/packages/apidash_core/lib/models/form_data_model.freezed.dart similarity index 100% rename from lib/models/form_data_model.freezed.dart rename to packages/apidash_core/lib/models/form_data_model.freezed.dart diff --git a/lib/models/form_data_model.g.dart b/packages/apidash_core/lib/models/form_data_model.g.dart similarity index 100% rename from lib/models/form_data_model.g.dart rename to packages/apidash_core/lib/models/form_data_model.g.dart diff --git a/lib/models/http_request_model.dart b/packages/apidash_core/lib/models/http_request_model.dart similarity index 100% rename from lib/models/http_request_model.dart rename to packages/apidash_core/lib/models/http_request_model.dart diff --git a/lib/models/http_request_model.freezed.dart b/packages/apidash_core/lib/models/http_request_model.freezed.dart similarity index 100% rename from lib/models/http_request_model.freezed.dart rename to packages/apidash_core/lib/models/http_request_model.freezed.dart diff --git a/lib/models/http_request_model.g.dart b/packages/apidash_core/lib/models/http_request_model.g.dart similarity index 100% rename from lib/models/http_request_model.g.dart rename to packages/apidash_core/lib/models/http_request_model.g.dart diff --git a/lib/models/http_response_model.dart b/packages/apidash_core/lib/models/http_response_model.dart similarity index 96% rename from lib/models/http_response_model.dart rename to packages/apidash_core/lib/models/http_response_model.dart index a567524f..bdbe7c3e 100644 --- a/lib/models/http_response_model.dart +++ b/packages/apidash_core/lib/models/http_response_model.dart @@ -5,8 +5,8 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:collection/collection.dart' show mergeMaps; import 'package:http/http.dart'; import 'package:http_parser/http_parser.dart'; -import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; +import '../utils/utils.dart'; +import '../consts.dart'; part 'http_response_model.freezed.dart'; diff --git a/lib/models/http_response_model.freezed.dart b/packages/apidash_core/lib/models/http_response_model.freezed.dart similarity index 100% rename from lib/models/http_response_model.freezed.dart rename to packages/apidash_core/lib/models/http_response_model.freezed.dart diff --git a/lib/models/http_response_model.g.dart b/packages/apidash_core/lib/models/http_response_model.g.dart similarity index 100% rename from lib/models/http_response_model.g.dart rename to packages/apidash_core/lib/models/http_response_model.g.dart diff --git a/packages/apidash_core/lib/models/models.dart b/packages/apidash_core/lib/models/models.dart new file mode 100644 index 00000000..57d2cc44 --- /dev/null +++ b/packages/apidash_core/lib/models/models.dart @@ -0,0 +1,4 @@ +export 'form_data_model.dart'; +export 'http_request_model.dart'; +export 'http_response_model.dart'; +export 'name_value_model.dart'; diff --git a/lib/models/name_value_model.dart b/packages/apidash_core/lib/models/name_value_model.dart similarity index 100% rename from lib/models/name_value_model.dart rename to packages/apidash_core/lib/models/name_value_model.dart diff --git a/lib/models/name_value_model.freezed.dart b/packages/apidash_core/lib/models/name_value_model.freezed.dart similarity index 100% rename from lib/models/name_value_model.freezed.dart rename to packages/apidash_core/lib/models/name_value_model.freezed.dart diff --git a/lib/models/name_value_model.g.dart b/packages/apidash_core/lib/models/name_value_model.g.dart similarity index 100% rename from lib/models/name_value_model.g.dart rename to packages/apidash_core/lib/models/name_value_model.g.dart diff --git a/lib/services/http_service.dart b/packages/apidash_core/lib/services/http_service.dart similarity index 93% rename from lib/services/http_service.dart rename to packages/apidash_core/lib/services/http_service.dart index 619dd50b..4ceee7bb 100644 --- a/lib/services/http_service.dart +++ b/packages/apidash_core/lib/services/http_service.dart @@ -2,11 +2,13 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; -import 'package:apidash/utils/utils.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import '../consts.dart'; +import '../models/models.dart'; +import '../utils/utils.dart'; -Future<(http.Response?, Duration?, String?)> request( +typedef HttpResponse = http.Response; + +Future<(HttpResponse?, Duration?, String?)> request( HttpRequestModel requestModel, { String defaultUriScheme = kDefaultUriScheme, }) async { @@ -18,7 +20,7 @@ Future<(http.Response?, Duration?, String?)> request( if (uriRec.$1 != null) { Uri requestUrl = uriRec.$1!; Map headers = requestModel.enabledHeadersMap; - http.Response response; + HttpResponse response; String? body; try { Stopwatch stopwatch = Stopwatch()..start(); diff --git a/packages/apidash_core/lib/services/services.dart b/packages/apidash_core/lib/services/services.dart new file mode 100644 index 00000000..f6a0ec3b --- /dev/null +++ b/packages/apidash_core/lib/services/services.dart @@ -0,0 +1 @@ +export 'http_service.dart'; diff --git a/packages/apidash_core/lib/utils/http_request_utils.dart b/packages/apidash_core/lib/utils/http_request_utils.dart new file mode 100644 index 00000000..1c09842b --- /dev/null +++ b/packages/apidash_core/lib/utils/http_request_utils.dart @@ -0,0 +1,83 @@ +import 'package:collection/collection.dart'; +import '../consts.dart'; +import '../models/models.dart'; + +Map? rowsToMap(List? kvRows, + {bool isHeader = false}) { + if (kvRows == null) { + return null; + } + Map finalMap = {}; + for (var row in kvRows) { + if (row.name.trim() != "") { + String key = row.name; + if (isHeader) { + key = key.toLowerCase(); + } + finalMap[key] = row.value.toString(); + } + } + return finalMap; +} + +List? mapToRows(Map? kvMap) { + if (kvMap == null) { + return null; + } + List finalRows = []; + for (var k in kvMap.keys) { + finalRows.add(NameValueModel(name: k, value: kvMap[k])); + } + return finalRows; +} + +List>? rowsToFormDataMapList( + List? kvRows, +) { + if (kvRows == null) { + return null; + } + List> finalMap = kvRows + .map((FormDataModel formData) => + (formData.name.trim().isEmpty && formData.value.trim().isEmpty) + ? null + : { + "name": formData.name, + "value": formData.value, + "type": formData.type.name, + }) + .whereNotNull() + .toList(); + return finalMap; +} + +List? mapListToFormDataModelRows(List? kvMap) { + if (kvMap == null) { + return null; + } + List finalRows = kvMap.map( + (formData) { + return FormDataModel( + name: formData["name"], + value: formData["value"], + type: getFormDataType(formData["type"]), + ); + }, + ).toList(); + return finalRows; +} + +FormDataType getFormDataType(String? type) { + return FormDataType.values.firstWhere((element) => element.name == type, + orElse: () => FormDataType.text); +} + +List? getEnabledRows( + List? rows, List? isRowEnabledList) { + if (rows == null || isRowEnabledList == null) { + return rows; + } + List finalRows = + rows.where((element) => isRowEnabledList[rows.indexOf(element)]).toList(); + return finalRows == [] ? null : finalRows; +} diff --git a/packages/apidash_core/lib/utils/http_response_utils.dart b/packages/apidash_core/lib/utils/http_response_utils.dart new file mode 100644 index 00000000..58704475 --- /dev/null +++ b/packages/apidash_core/lib/utils/http_response_utils.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; +import 'package:xml/xml.dart'; +import '../consts.dart'; + +String? getContentTypeFromHeaders(Map? headers) { + return headers?[HttpHeaders.contentTypeHeader]; +} + +MediaType? getMediaTypeFromHeaders(Map? headers) { + var contentType = getContentTypeFromHeaders(headers); + MediaType? mediaType = getMediaTypeFromContentType(contentType); + return mediaType; +} + +MediaType? getMediaTypeFromContentType(String? contentType) { + if (contentType != null) { + try { + MediaType mediaType = MediaType.parse(contentType); + return mediaType; + } catch (e) { + return null; + } + } + return null; +} + +String? formatBody(String? body, MediaType? mediaType) { + if (mediaType != null && body != null) { + var subtype = mediaType.subtype; + try { + if (subtype.contains(kSubTypeJson)) { + final tmp = jsonDecode(body); + String result = kJsonEncoder.convert(tmp); + return result; + } + if (subtype.contains(kSubTypeXml)) { + final document = XmlDocument.parse(body); + String result = document.toXmlString(pretty: true, indent: ' '); + return result; + } + if (subtype == kSubTypeHtml) { + var len = body.length; + var lines = kSplitter.convert(body); + var numOfLines = lines.length; + if (numOfLines != 0 && len / numOfLines <= kCodeCharsPerLineLimit) { + return body; + } + } + } catch (e) { + return null; + } + } + return null; +} + +Future convertStreamedResponse( + http.StreamedResponse streamedResponse, +) async { + Uint8List bodyBytes = await streamedResponse.stream.toBytes(); + + http.Response response = http.Response.bytes( + bodyBytes, + streamedResponse.statusCode, + headers: streamedResponse.headers, + persistentConnection: streamedResponse.persistentConnection, + reasonPhrase: streamedResponse.reasonPhrase, + request: streamedResponse.request, + ); + + return response; +} diff --git a/test/test_utilities.dart b/packages/apidash_core/lib/utils/string_utils.dart similarity index 100% rename from test/test_utilities.dart rename to packages/apidash_core/lib/utils/string_utils.dart diff --git a/packages/apidash_core/lib/utils/uri_utils.dart b/packages/apidash_core/lib/utils/uri_utils.dart new file mode 100644 index 00000000..09c159ab --- /dev/null +++ b/packages/apidash_core/lib/utils/uri_utils.dart @@ -0,0 +1,64 @@ +import 'package:collection/collection.dart' show mergeMaps; +import '../consts.dart'; +import '../models/name_value_model.dart'; +import 'http_request_utils.dart'; + +(String?, bool) getUriScheme(Uri uri) { + if (uri.hasScheme) { + if (kSupportedUriSchemes.contains(uri.scheme)) { + return (uri.scheme, true); + } + return (uri.scheme, false); + } + return (null, false); +} + +String stripUriParams(Uri uri) { + return "${uri.scheme}://${uri.authority}${uri.path}"; +} + +String stripUrlParams(String url) { + var idx = url.indexOf("?"); + return idx > 0 ? url.substring(0, idx) : url; +} + +(Uri?, String?) getValidRequestUri( + String? url, List? requestParams, + {String defaultUriScheme = kDefaultUriScheme}) { + url = url?.trim(); + if (url == null || url == "") { + return (null, "URL is missing!"); + } + + if (kLocalhostRegex.hasMatch(url)) { + url = '${SupportedUriSchemes.http.name}://$url'; + } + Uri? uri = Uri.tryParse(url); + if (uri == null) { + return (null, "Check URL (malformed)"); + } + (String?, bool) urlScheme = getUriScheme(uri); + + if (urlScheme.$1 != null) { + if (!urlScheme.$2) { + return (null, "Unsupported URL Scheme (${urlScheme.$1})"); + } + } else { + url = "$defaultUriScheme://$url"; + } + + uri = Uri.parse(url); + if (uri.hasFragment) { + uri = uri.removeFragment(); + } + + Map? queryParams = rowsToMap(requestParams); + if (queryParams != null && queryParams.isNotEmpty) { + if (uri.hasQuery) { + Map urlQueryParams = uri.queryParameters; + queryParams = mergeMaps(urlQueryParams, queryParams); + } + uri = uri.replace(queryParameters: queryParams); + } + return (uri, null); +} diff --git a/packages/apidash_core/lib/utils/utils.dart b/packages/apidash_core/lib/utils/utils.dart new file mode 100644 index 00000000..5e1dbbcb --- /dev/null +++ b/packages/apidash_core/lib/utils/utils.dart @@ -0,0 +1,4 @@ +export 'http_request_utils.dart'; +export 'http_response_utils.dart'; +export 'string_utils.dart'; +export 'uri_utils.dart'; diff --git a/packages/apidash_core/pubspec.yaml b/packages/apidash_core/pubspec.yaml new file mode 100644 index 00000000..8c93cc36 --- /dev/null +++ b/packages/apidash_core/pubspec.yaml @@ -0,0 +1,62 @@ +name: apidash_core +description: "API Dash Core" +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: ^3.5.3 + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + collection: ^1.18.0 + freezed_annotation: ^2.4.1 + http: ^1.2.1 + http_parser: ^4.0.2 + xml: ^6.3.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^4.0.0 + freezed: ^2.5.7 + test: ^1.25.2 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/apidash_core/test/apidash_core_test.dart b/packages/apidash_core/test/apidash_core_test.dart new file mode 100644 index 00000000..4fbba06e --- /dev/null +++ b/packages/apidash_core/test/apidash_core_test.dart @@ -0,0 +1,7 @@ +// ignore_for_file: unused_import + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:apidash_core/apidash_core.dart'; + +void main() {} diff --git a/test/extensions/string_extensions_test.dart b/packages/apidash_core/test/extensions/string_extensions_test.dart similarity index 96% rename from test/extensions/string_extensions_test.dart rename to packages/apidash_core/test/extensions/string_extensions_test.dart index c0fcbd58..b28b91d2 100644 --- a/test/extensions/string_extensions_test.dart +++ b/packages/apidash_core/test/extensions/string_extensions_test.dart @@ -1,5 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; -import 'package:apidash/extensions/string_extensions.dart'; void main() { group('Testing StringExtensions', () { diff --git a/test/models/form_data_model_test.dart b/packages/apidash_core/test/models/form_data_model_test.dart similarity index 92% rename from test/models/form_data_model_test.dart rename to packages/apidash_core/test/models/form_data_model_test.dart index c8569a57..d6b6f272 100644 --- a/test/models/form_data_model_test.dart +++ b/packages/apidash_core/test/models/form_data_model_test.dart @@ -1,6 +1,5 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; -import 'package:apidash/models/form_data_model.dart'; void main() { const fdmRow1 = FormDataModel( diff --git a/test/models/name_value_model_test.dart b/packages/apidash_core/test/models/name_value_model_test.dart similarity index 93% rename from test/models/name_value_model_test.dart rename to packages/apidash_core/test/models/name_value_model_test.dart index c1fd9f57..636cfec7 100644 --- a/test/models/name_value_model_test.dart +++ b/packages/apidash_core/test/models/name_value_model_test.dart @@ -1,5 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; -import 'package:apidash/models/name_value_model.dart'; void main() { const nmRow1 = NameValueModel(name: "harry", value: 23); diff --git a/packages/apidash_core/test/utils/https_response_utils.dart b/packages/apidash_core/test/utils/https_response_utils.dart new file mode 100644 index 00000000..07ff4336 --- /dev/null +++ b/packages/apidash_core/test/utils/https_response_utils.dart @@ -0,0 +1,190 @@ +import 'package:apidash_core/utils/http_response_utils.dart'; +import 'package:apidash_core/utils/string_utils.dart'; +import 'package:http_parser/http_parser.dart'; +import 'package:test/test.dart'; + +void main() { + group("Testing getContentTypeFromHeaders function", () { + test('Testing getContentTypeFromHeaders for header1', () { + Map header1 = { + "content-type": "application/json", + }; + String contentType1Expected = "application/json"; + expect(getContentTypeFromHeaders(header1), contentType1Expected); + }); + test('Testing getContentTypeFromHeaders for null headers', () { + expect(getContentTypeFromHeaders(null), null); + }); + test( + 'Testing getContentTypeFromHeaders when header keys are in header case', + () { + Map header2 = { + "Content-Type": "application/json", + }; + expect(getContentTypeFromHeaders(header2), null); + }); + }); + + group('Testing getMediaTypeFromContentType function', () { + test('Testing getMediaTypeFromContentType for json type', () { + String contentType1 = "application/json"; + MediaType mediaType1Expected = MediaType("application", "json"); + expect(getMediaTypeFromContentType(contentType1).toString(), + mediaType1Expected.toString()); + }); + test('Testing getMediaTypeFromContentType for null', () { + expect(getMediaTypeFromContentType(null), null); + }); + test('Testing getMediaTypeFromContentType for image svg+xml type', () { + String contentType3 = "image/svg+xml"; + MediaType mediaType3Expected = MediaType("image", "svg+xml"); + expect(getMediaTypeFromContentType(contentType3).toString(), + mediaType3Expected.toString()); + }); + test('Testing getMediaTypeFromContentType for incorrect content type', () { + String contentType4 = "text/html : charset=utf-8"; + expect(getMediaTypeFromContentType(contentType4), null); + }); + test('Testing getMediaTypeFromContentType for text/css type', () { + String contentType5 = "text/css; charset=utf-8"; + MediaType mediaType5Expected = + MediaType("text", "css", {"charset": "utf-8"}); + expect(getMediaTypeFromContentType(contentType5).toString(), + mediaType5Expected.toString()); + }); + test('Testing getMediaTypeFromContentType for incorrect with double ;', () { + String contentType6 = + "application/xml; charset=utf-16be ; date=21/03/2023"; + expect(getMediaTypeFromContentType(contentType6), null); + }); + test('Testing getMediaTypeFromContentType for empty content type', () { + expect(getMediaTypeFromContentType(""), null); + }); + test('Testing getMediaTypeFromContentType for missing subtype', () { + String contentType7 = "audio"; + expect(getMediaTypeFromContentType(contentType7), null); + }); + test('Testing getMediaTypeFromContentType for missing Type', () { + String contentType8 = "/html"; + expect(getMediaTypeFromContentType(contentType8), null); + }); + }); + + group("Testing getMediaTypeFromHeaders", () { + test('Testing getMediaTypeFromHeaders for basic case', () { + Map header1 = { + "content-length": "4506", + "cache-control": "private", + "content-type": "application/json" + }; + MediaType mediaType1Expected = MediaType("application", "json"); + expect(getMediaTypeFromHeaders(header1).toString(), + mediaType1Expected.toString()); + }); + test('Testing getMediaTypeFromHeaders for null header', () { + expect(getMediaTypeFromHeaders(null), null); + }); + test('Testing getMediaTypeFromHeaders for incomplete header value', () { + Map header2 = {"content-length": "4506"}; + expect(getMediaTypeFromHeaders(header2), null); + }); + test('Testing getMediaTypeFromHeaders for empty header value', () { + Map header3 = {"content-type": ""}; + expect(getMediaTypeFromHeaders(header3), null); + }); + test( + 'Testing getMediaTypeFromHeaders for erroneous header value - missing type', + () { + Map header4 = {"content-type": "/json"}; + expect(getMediaTypeFromHeaders(header4), null); + }); + test( + 'Testing getMediaTypeFromHeaders for erroneous header value - missing subtype', + () { + Map header5 = {"content-type": "application"}; + expect(getMediaTypeFromHeaders(header5), null); + }); + test('Testing getMediaTypeFromHeaders for header6', () { + Map header6 = {"content-type": "image/svg+xml"}; + MediaType mediaType6Expected = MediaType("image", "svg+xml"); + expect(getMediaTypeFromHeaders(header6).toString(), + mediaType6Expected.toString()); + }); + }); + + group("Testing formatBody", () { + test('Testing formatBody for null values', () { + expect(formatBody(null, null), null); + }); + test('Testing formatBody for null body values', () { + MediaType mediaType1 = MediaType("application", "xml"); + expect(formatBody(null, mediaType1), null); + }); + test('Testing formatBody for null MediaType values', () { + String body1 = ''' + { + "text":"The Chosen One"; + } +'''; + expect(formatBody(body1, null), null); + }); + test('Testing formatBody for json subtype values', () { + String body2 = '''{"data":{"area":9831510.0,"population":331893745}}'''; + MediaType mediaType2 = MediaType("application", "json"); + String result2Expected = '''{ + "data": { + "area": 9831510.0, + "population": 331893745 + } +}'''; + expect(formatBody(body2, mediaType2), result2Expected); + }); + test('Testing formatBody for xml subtype values', () { + String body3 = ''' + + +Belgian Waffles +5.95 USD +Two of our famous Belgian Waffles with plenty of real maple syrup +650 + + +'''; + MediaType mediaType3 = MediaType("application", "xml"); + String result3Expected = ''' + + Belgian Waffles + 5.95 USD + Two of our famous Belgian Waffles with plenty of real maple syrup + 650 + +'''; + expect(formatBody(body3, mediaType3), result3Expected); + }); + group("Testing formatBody for html", () { + MediaType mediaTypeHtml = MediaType("text", "html"); + test('Testing formatBody for html subtype values', () { + String body4 = ''' + +

My First Heading

+

My first paragraph.

+ +'''; + expect(formatBody(body4, mediaTypeHtml), body4); + }); + + test('Testing formatBody for html subtype values with random values', () { + String body5 = + '''${RandomStringGenerator.getRandomStringLines(100, 10000)}'''; + expect(formatBody(body5, mediaTypeHtml), null); + }); + test( + 'Testing formatBody for html subtype values with random values within limit', + () { + String body6 = + '''${RandomStringGenerator.getRandomStringLines(100, 190)}'''; + expect(formatBody(body6, mediaTypeHtml), body6); + }); + }); + }); +} diff --git a/packages/apidash_core/test/utils/uri_utils_test.dart b/packages/apidash_core/test/utils/uri_utils_test.dart new file mode 100644 index 00000000..1d754522 --- /dev/null +++ b/packages/apidash_core/test/utils/uri_utils_test.dart @@ -0,0 +1,127 @@ +import 'package:apidash_core/models/models.dart'; +import 'package:apidash_core/utils/uri_utils.dart'; +import 'package:test/test.dart'; + +void main() { + group("Testing getUriScheme", () { + test('Testing getUriScheme for https', () { + Uri uri1 = Uri( + scheme: 'https', + host: 'dart.dev', + path: 'guides/libraries/library-tour', + fragment: 'numbers'); + String uriScheme1Expected = 'https'; + expect(getUriScheme(uri1), (uriScheme1Expected, true)); + }); + test('Testing getUriScheme for mailto scheme value', () { + Uri uri2 = Uri(scheme: 'mailto'); + String uriScheme2Expected = 'mailto'; + expect(getUriScheme(uri2), (uriScheme2Expected, false)); + }); + test('Testing getUriScheme for empty scheme value', () { + Uri uri3 = Uri(scheme: ''); + expect(getUriScheme(uri3), (null, false)); + }); + test('Testing getUriScheme for null scheme value', () { + Uri uri4 = Uri(scheme: null); + expect(getUriScheme(uri4), (null, false)); + }); + }); + + group("Testing getValidRequestUri", () { + test('Testing getValidRequestUri with localhost URL without port or path', + () { + String url1 = "localhost"; + Uri uri1Expected = Uri(scheme: 'http', host: 'localhost'); + expect(getValidRequestUri(url1, []), (uri1Expected, null)); + }); + + test('Testing getValidRequestUri with localhost URL with port', () { + String url1 = "localhost:8080"; + Uri uri1Expected = Uri(scheme: 'http', host: 'localhost', port: 8080); + expect(getValidRequestUri(url1, []), (uri1Expected, null)); + }); + + test('Testing getValidRequestUri with localhost URL with port and path', + () { + String url1 = "localhost:8080/hello"; + Uri uri1Expected = + Uri(scheme: 'http', host: 'localhost', port: 8080, path: '/hello'); + expect(getValidRequestUri(url1, []), (uri1Expected, null)); + }); + + test('Testing getValidRequestUri with localhost URL with http prefix', () { + String url1 = "http://localhost:3080"; + Uri uri1Expected = Uri(scheme: 'http', host: 'localhost', port: 3080); + expect(getValidRequestUri(url1, []), (uri1Expected, null)); + }); + + test('Testing getValidRequestUri with localhost URL with https prefix', () { + String url1 = "https://localhost:8080"; + Uri uri1Expected = Uri(scheme: 'https', host: 'localhost', port: 8080); + expect(getValidRequestUri(url1, []), (uri1Expected, null)); + }); + + test('Testing getValidRequestUri for normal values', () { + String url1 = "https://api.apidash.dev/country/data"; + const kvRow1 = NameValueModel(name: "code", value: "US"); + Uri uri1Expected = Uri( + scheme: 'https', + host: 'api.apidash.dev', + path: 'country/data', + queryParameters: {'code': 'US'}); + expect(getValidRequestUri(url1, [kvRow1]), (uri1Expected, null)); + }); + test('Testing getValidRequestUri for null url value', () { + const kvRow2 = NameValueModel(name: "code", value: "US"); + expect(getValidRequestUri(null, [kvRow2]), (null, "URL is missing!")); + }); + test('Testing getValidRequestUri for empty url value', () { + const kvRow3 = NameValueModel(name: "", value: ""); + expect(getValidRequestUri("", [kvRow3]), (null, "URL is missing!")); + }); + test('Testing getValidRequestUri when https is not provided in url', () { + String url4 = "api.apidash.dev/country/data"; + const kvRow4 = NameValueModel(name: "code", value: "US"); + Uri uri4Expected = Uri( + scheme: 'https', + host: 'api.apidash.dev', + path: 'country/data', + queryParameters: {'code': 'US'}); + expect(getValidRequestUri(url4, [kvRow4]), (uri4Expected, null)); + }); + test('Testing getValidRequestUri when url has fragment', () { + String url5 = "https://dart.dev/guides/libraries/library-tour#numbers"; + Uri uri5Expected = Uri( + scheme: 'https', + host: 'dart.dev', + path: '/guides/libraries/library-tour'); + expect(getValidRequestUri(url5, null), (uri5Expected, null)); + }); + test('Testing getValidRequestUri when uri scheme is not supported', () { + String url5 = "mailto:someone@example.com"; + expect(getValidRequestUri(url5, null), + (null, "Unsupported URL Scheme (mailto)")); + }); + test('Testing getValidRequestUri when query params in both url and kvrow', + () { + String url6 = "api.apidash.dev/country/data?code=IND"; + const kvRow6 = NameValueModel(name: "code", value: "US"); + Uri uri6Expected = Uri( + scheme: 'https', + host: 'api.apidash.dev', + path: 'country/data', + queryParameters: {'code': 'US'}); + expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null)); + }); + test('Testing getValidRequestUri when kvrow is null', () { + String url7 = "api.apidash.dev/country/data?code=US"; + Uri uri7Expected = Uri( + scheme: 'https', + host: 'api.apidash.dev', + path: 'country/data', + queryParameters: {'code': 'US'}); + expect(getValidRequestUri(url7, null), (uri7Expected, null)); + }); + }); +} diff --git a/packages/apidash_design_system/.gitignore b/packages/apidash_design_system/.gitignore new file mode 100644 index 00000000..de54a3c2 --- /dev/null +++ b/packages/apidash_design_system/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ + +coverage/ diff --git a/packages/apidash_design_system/CHANGELOG.md b/packages/apidash_design_system/CHANGELOG.md new file mode 100644 index 00000000..41cc7d81 --- /dev/null +++ b/packages/apidash_design_system/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/apidash_design_system/LICENSE b/packages/apidash_design_system/LICENSE new file mode 100644 index 00000000..d036f89e --- /dev/null +++ b/packages/apidash_design_system/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 Ankit Mahato, Ashita Prasad + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/apidash_design_system/README.md b/packages/apidash_design_system/README.md new file mode 100644 index 00000000..cee6aa8d --- /dev/null +++ b/packages/apidash_design_system/README.md @@ -0,0 +1,2 @@ +# API Dash Design System + diff --git a/packages/apidash_design_system/analysis_options.yaml b/packages/apidash_design_system/analysis_options.yaml new file mode 100644 index 00000000..a5744c1c --- /dev/null +++ b/packages/apidash_design_system/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/google_fonts/NotoColorEmoji-Regular.ttf b/packages/apidash_design_system/google_fonts/NotoColorEmoji-Regular.ttf similarity index 100% rename from google_fonts/NotoColorEmoji-Regular.ttf rename to packages/apidash_design_system/google_fonts/NotoColorEmoji-Regular.ttf diff --git a/google_fonts/OpenSans-Bold.ttf b/packages/apidash_design_system/google_fonts/OpenSans-Bold.ttf similarity index 100% rename from google_fonts/OpenSans-Bold.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-Bold.ttf diff --git a/google_fonts/OpenSans-BoldItalic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-BoldItalic.ttf similarity index 100% rename from google_fonts/OpenSans-BoldItalic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-BoldItalic.ttf diff --git a/google_fonts/OpenSans-ExtraBold.ttf b/packages/apidash_design_system/google_fonts/OpenSans-ExtraBold.ttf similarity index 100% rename from google_fonts/OpenSans-ExtraBold.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-ExtraBold.ttf diff --git a/google_fonts/OpenSans-ExtraBoldItalic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-ExtraBoldItalic.ttf similarity index 100% rename from google_fonts/OpenSans-ExtraBoldItalic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-ExtraBoldItalic.ttf diff --git a/google_fonts/OpenSans-Italic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-Italic.ttf similarity index 100% rename from google_fonts/OpenSans-Italic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-Italic.ttf diff --git a/google_fonts/OpenSans-Light.ttf b/packages/apidash_design_system/google_fonts/OpenSans-Light.ttf similarity index 100% rename from google_fonts/OpenSans-Light.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-Light.ttf diff --git a/google_fonts/OpenSans-LightItalic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-LightItalic.ttf similarity index 100% rename from google_fonts/OpenSans-LightItalic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-LightItalic.ttf diff --git a/google_fonts/OpenSans-Medium.ttf b/packages/apidash_design_system/google_fonts/OpenSans-Medium.ttf similarity index 100% rename from google_fonts/OpenSans-Medium.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-Medium.ttf diff --git a/google_fonts/OpenSans-MediumItalic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-MediumItalic.ttf similarity index 100% rename from google_fonts/OpenSans-MediumItalic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-MediumItalic.ttf diff --git a/google_fonts/OpenSans-Regular.ttf b/packages/apidash_design_system/google_fonts/OpenSans-Regular.ttf similarity index 100% rename from google_fonts/OpenSans-Regular.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-Regular.ttf diff --git a/google_fonts/OpenSans-SemiBold.ttf b/packages/apidash_design_system/google_fonts/OpenSans-SemiBold.ttf similarity index 100% rename from google_fonts/OpenSans-SemiBold.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-SemiBold.ttf diff --git a/google_fonts/OpenSans-SemiBoldItalic.ttf b/packages/apidash_design_system/google_fonts/OpenSans-SemiBoldItalic.ttf similarity index 100% rename from google_fonts/OpenSans-SemiBoldItalic.ttf rename to packages/apidash_design_system/google_fonts/OpenSans-SemiBoldItalic.ttf diff --git a/google_fonts/SourceCodePro-Bold.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-Bold.ttf similarity index 100% rename from google_fonts/SourceCodePro-Bold.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-Bold.ttf diff --git a/google_fonts/SourceCodePro-BoldItalic.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-BoldItalic.ttf similarity index 100% rename from google_fonts/SourceCodePro-BoldItalic.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-BoldItalic.ttf diff --git a/google_fonts/SourceCodePro-Italic.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-Italic.ttf similarity index 100% rename from google_fonts/SourceCodePro-Italic.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-Italic.ttf diff --git a/google_fonts/SourceCodePro-Medium.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-Medium.ttf similarity index 100% rename from google_fonts/SourceCodePro-Medium.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-Medium.ttf diff --git a/google_fonts/SourceCodePro-MediumItalic.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-MediumItalic.ttf similarity index 100% rename from google_fonts/SourceCodePro-MediumItalic.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-MediumItalic.ttf diff --git a/google_fonts/SourceCodePro-Regular.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-Regular.ttf similarity index 100% rename from google_fonts/SourceCodePro-Regular.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-Regular.ttf diff --git a/google_fonts/SourceCodePro-SemiBold.ttf b/packages/apidash_design_system/google_fonts/SourceCodePro-SemiBold.ttf similarity index 100% rename from google_fonts/SourceCodePro-SemiBold.ttf rename to packages/apidash_design_system/google_fonts/SourceCodePro-SemiBold.ttf diff --git a/packages/apidash_design_system/lib/apidash_design_system.dart b/packages/apidash_design_system/lib/apidash_design_system.dart new file mode 100644 index 00000000..a9d394c4 --- /dev/null +++ b/packages/apidash_design_system/lib/apidash_design_system.dart @@ -0,0 +1,4 @@ +library apidash_design_system; + +export 'package:google_fonts/google_fonts.dart'; +export 'consts.dart'; diff --git a/packages/apidash_design_system/lib/consts.dart b/packages/apidash_design_system/lib/consts.dart new file mode 100644 index 00000000..9a9536f4 --- /dev/null +++ b/packages/apidash_design_system/lib/consts.dart @@ -0,0 +1,254 @@ +import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +final kColorTransparentState = + WidgetStateProperty.all(Colors.transparent); +const kColorTransparent = Colors.transparent; +const kColorWhite = Colors.white; +const kColorBlack = Colors.black; +const kColorRed = Colors.red; +final kColorLightDanger = Colors.red.withOpacity(0.9); +const kColorDarkDanger = Color(0xffcf6679); + +const kColorSchemeSeed = Colors.blue; +final kFontFamily = GoogleFonts.openSans().fontFamily; +final kFontFamilyFallback = !kIsWeb && (Platform.isIOS || Platform.isMacOS) + ? null + : [GoogleFonts.notoColorEmoji().fontFamily!]; + +final kLightMaterialAppTheme = ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.light, + visualDensity: VisualDensity.adaptivePlatformDensity, +); +final kDarkMaterialAppTheme = ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.dark, + visualDensity: VisualDensity.adaptivePlatformDensity, +); + +final kCodeStyle = TextStyle( + fontFamily: GoogleFonts.sourceCodePro().fontFamily, + fontFamilyFallback: kFontFamilyFallback, +); + +const kHintOpacity = 0.6; +const kForegroundOpacity = 0.05; +const kOverlayBackgroundOpacity = 0.5; + +const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); +const kTextStyleTab = TextStyle(fontSize: 14); +const kTextStyleButtonSmall = TextStyle(fontSize: 12); +const kFormDataButtonLabelTextStyle = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, +); +const kTextStylePopupMenuItem = TextStyle(fontSize: 14); + +final kButtonSidebarStyle = ElevatedButton.styleFrom(padding: kPh12); + +const kBorderRadius4 = BorderRadius.all(Radius.circular(4)); +const kBorderRadius6 = BorderRadius.all(Radius.circular(6)); +const kBorderRadius8 = BorderRadius.all(Radius.circular(8)); +final kBorderRadius10 = BorderRadius.circular(10); +const kBorderRadius12 = BorderRadius.all(Radius.circular(12)); +const kBorderRadius20 = BorderRadius.all(Radius.circular(20)); + +const kP1 = EdgeInsets.all(1); +const kP4 = EdgeInsets.all(4); +const kP5 = EdgeInsets.all(5); +const kP6 = EdgeInsets.all(6); +const kP8 = EdgeInsets.all(8); +const kPs8 = EdgeInsets.only(left: 8); +const kPs2 = EdgeInsets.only(left: 2); +const kPe4 = EdgeInsets.only(right: 4); +const kPe8 = EdgeInsets.only(right: 8); +const kPh20v5 = EdgeInsets.symmetric(horizontal: 20, vertical: 5); +const kPh20v10 = EdgeInsets.symmetric(horizontal: 20, vertical: 10); +const kP10 = EdgeInsets.all(10); +const kPv2 = EdgeInsets.symmetric(vertical: 2); +const kPv6 = EdgeInsets.symmetric(vertical: 6); +const kPv8 = EdgeInsets.symmetric(vertical: 8); +const kPv10 = EdgeInsets.symmetric(vertical: 10); +const kPv20 = EdgeInsets.symmetric(vertical: 20); +const kPh2 = EdgeInsets.symmetric(horizontal: 2); +const kPt28o8 = EdgeInsets.only(top: 28, left: 8.0, right: 8.0, bottom: 8.0); +const kPt5o10 = + EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0); +const kPh4 = EdgeInsets.symmetric(horizontal: 4); +const kPh8 = EdgeInsets.symmetric(horizontal: 8); +const kPh12 = EdgeInsets.symmetric(horizontal: 12); +const kPh20 = EdgeInsets.symmetric(horizontal: 20); +const kPh24 = EdgeInsets.symmetric(horizontal: 24); +const kPh20t40 = EdgeInsets.only( + left: 20, + right: 20, + top: 40, +); +const kPs0o6 = EdgeInsets.only( + left: 0, + top: 6, + right: 6, + bottom: 6, +); +const kPh60 = EdgeInsets.symmetric(horizontal: 60); +const kPh60v60 = EdgeInsets.symmetric(vertical: 60, horizontal: 60); +const kP24CollectionPane = EdgeInsets.only( + top: 24, + left: 4.0, + //right: 4.0, + // bottom: 8.0, +); +const kP8CollectionPane = EdgeInsets.only( + top: 8.0, + left: 4.0, + //right: 4.0, + // bottom: 8.0, +); +const kPt8 = EdgeInsets.only( + top: 8, +); +const kPt20 = EdgeInsets.only( + top: 20, +); +const kPt24 = EdgeInsets.only( + top: 24, +); +const kPt28 = EdgeInsets.only( + top: 28, +); +const kPt32 = EdgeInsets.only( + top: 32, +); +const kPb10 = EdgeInsets.only( + bottom: 10, +); +const kPb15 = EdgeInsets.only( + bottom: 15, +); +const kPb70 = EdgeInsets.only( + bottom: 70, +); +const kSizedBoxEmpty = SizedBox(); +const kHSpacer2 = SizedBox(width: 2); +const kHSpacer4 = SizedBox(width: 4); +const kHSpacer5 = SizedBox(width: 5); +const kHSpacer10 = SizedBox(width: 10); +const kHSpacer12 = SizedBox(width: 12); +const kHSpacer20 = SizedBox(width: 20); +const kHSpacer40 = SizedBox(width: 40); +const kVSpacer5 = SizedBox(height: 5); +const kVSpacer8 = SizedBox(height: 8); +const kVSpacer10 = SizedBox(height: 10); +const kVSpacer16 = SizedBox(height: 16); +const kVSpacer20 = SizedBox(height: 20); +const kVSpacer40 = SizedBox(height: 40); + +const kLightCodeTheme = { + 'root': + TextStyle(backgroundColor: Color(0xffffffff), color: Color(0xff000000)), + 'addition': TextStyle(backgroundColor: Color(0xffbaeeba)), + 'attr': TextStyle(color: Color(0xff836C28)), + 'attribute': TextStyle(color: Color(0xffaa0d91)), + 'built_in': TextStyle(color: Color(0xff5c2699)), + 'builtin-name': TextStyle(color: Color(0xff5c2699)), + 'bullet': TextStyle(color: Color(0xff1c00cf)), + 'code': TextStyle(color: Color(0xffc41a16)), + 'comment': TextStyle(color: Color(0xff007400), fontStyle: FontStyle.italic), + 'deletion': TextStyle(backgroundColor: Color(0xffffc8bd)), + 'doctag': TextStyle(fontWeight: FontWeight.bold), + 'emphasis': TextStyle(fontStyle: FontStyle.italic), + 'formula': TextStyle( + backgroundColor: Color(0xffeeeeee), fontStyle: FontStyle.italic), + 'keyword': TextStyle(color: Color(0xffaa0d91)), + 'link': TextStyle(color: Color(0xff0E0EFF)), + 'literal': TextStyle(color: Color(0xffaa0d91)), + 'meta': TextStyle(color: Color(0xff643820)), + 'meta-string': TextStyle(color: Color(0xffc41a16)), + 'name': TextStyle(color: Color(0xffaa0d91)), + 'number': TextStyle(color: Color(0xff1c00cf)), + 'params': TextStyle(color: Color(0xff5c2699)), + 'quote': TextStyle(color: Color(0xff007400)), + 'regexp': TextStyle(color: Color(0xff0E0EFF)), + 'section': TextStyle(color: Color(0xff643820)), + 'selector-class': TextStyle(color: Color(0xff9b703f)), + 'selector-id': TextStyle(color: Color(0xff9b703f)), + 'selector-tag': TextStyle(color: Color(0xffaa0d91)), + 'string': TextStyle(color: Color(0xffc41a16)), + 'strong': TextStyle(fontWeight: FontWeight.bold), + 'subst': TextStyle(color: Color(0xff000000)), + 'symbol': TextStyle(color: Color(0xff1c00cf)), + 'tag': TextStyle(color: Color(0xffaa0d91)), + 'template-variable': TextStyle(color: Color(0xff3F6E74)), + 'title': TextStyle(color: Color(0xff1c00cf)), + 'type': TextStyle(color: Color(0xff5c2699)), + 'variable': TextStyle(color: Color(0xff3F6E74)), +}; + +const kDarkCodeTheme = { + 'root': + TextStyle(backgroundColor: Color(0xff011627), color: Color(0xffd6deeb)), + 'addition': TextStyle(color: Color(0xffaddb67)), + 'attr': TextStyle(color: Color(0xff7fdbca)), + 'attribute': TextStyle(color: Color(0xff80cbc4)), + 'built_in': TextStyle(color: Color(0xffaddb67)), + 'builtin-name': TextStyle(color: Color(0xff7fdbca)), + 'bullet': TextStyle(color: Color(0xffd9f5dd)), + 'class': TextStyle(color: Color(0xffffcb8b)), + 'code': TextStyle(color: Color(0xff80CBC4)), + 'comment': TextStyle(color: Color(0xff637777), fontStyle: FontStyle.italic), + 'deletion': TextStyle(color: Color(0xffef5350)), + 'doctag': TextStyle(color: Color(0xff7fdbca)), + 'emphasis': TextStyle(color: Color(0xffc792ea)), + 'formula': TextStyle(color: Color(0xffc792ea), fontStyle: FontStyle.italic), + 'function': TextStyle(color: Color(0xff82AAFF)), + 'keyword': TextStyle(color: Color(0xffc792ea)), + 'link': TextStyle(color: Color(0xffff869a)), + 'literal': TextStyle(color: Color(0xffff5874)), + 'meta': TextStyle(color: Color(0xff82aaff)), + 'meta-keyword': TextStyle(color: Color(0xff82aaff)), + 'meta-string': TextStyle(color: Color(0xffecc48d)), + 'name': TextStyle(color: Color(0xff7fdbca)), + 'number': TextStyle(color: Color(0xffF78C6C)), + 'params': TextStyle(color: Color(0xff7fdbca)), + 'quote': TextStyle(color: Color(0xff697098)), + 'regexp': TextStyle(color: Color(0xff5ca7e4)), + 'section': TextStyle(color: Color(0xff82b1ff)), + 'selector-attr': TextStyle(color: Color(0xffc792ea)), + 'selector-class': TextStyle(color: Color(0xffaddb67)), + 'selector-id': TextStyle(color: Color(0xfffad430)), + 'selector-pseudo': TextStyle(color: Color(0xffc792ea)), + 'selector-tag': TextStyle(color: Color(0xffff6363)), + 'string': TextStyle(color: Color(0xffecc48d)), + 'strong': TextStyle(color: Color(0xffaddb67), fontWeight: FontWeight.bold), + 'subst': TextStyle(color: Color(0xffd3423e)), + 'symbol': TextStyle(color: Color(0xff82aaff)), + 'tag': TextStyle(color: Color(0xff7fdbca)), + 'template-tag': TextStyle(color: Color(0xffc792ea)), + 'template-variable': TextStyle(color: Color(0xffaddb67)), + 'title': TextStyle(color: Color(0xffDCDCAA)), + 'type': TextStyle(color: Color(0xff82aaff)), + 'variable': TextStyle(color: Color(0xffaddb67)), +}; + +final kColorStatusCodeDefault = Colors.grey.shade700; +final kColorStatusCode200 = Colors.green.shade800; +final kColorStatusCode300 = Colors.blue.shade800; +final kColorStatusCode400 = Colors.red.shade800; +final kColorStatusCode500 = Colors.amber.shade900; +const kOpacityDarkModeBlend = 0.4; + +final kColorHttpMethodGet = Colors.green.shade800; +final kColorHttpMethodHead = kColorHttpMethodGet; +final kColorHttpMethodPost = Colors.blue.shade800; +final kColorHttpMethodPut = Colors.amber.shade900; +final kColorHttpMethodPatch = kColorHttpMethodPut; +final kColorHttpMethodDelete = Colors.red.shade800; diff --git a/packages/apidash_design_system/pubspec.yaml b/packages/apidash_design_system/pubspec.yaml new file mode 100644 index 00000000..7c5f1088 --- /dev/null +++ b/packages/apidash_design_system/pubspec.yaml @@ -0,0 +1,26 @@ +name: apidash_design_system +description: "API Dash Design System" +version: 0.0.1 +homepage: + +environment: + sdk: ^3.5.3 + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + google_fonts: ^6.2.1 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^4.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + assets: + - google_fonts/ diff --git a/packages/apidash_design_system/test/apidash_design_system_test.dart b/packages/apidash_design_system/test/apidash_design_system_test.dart new file mode 100644 index 00000000..e094bba6 --- /dev/null +++ b/packages/apidash_design_system/test/apidash_design_system_test.dart @@ -0,0 +1,7 @@ +// ignore_for_file: unused_import + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:apidash_design_system/apidash_design_system.dart'; + +void main() {} diff --git a/pubspec.lock b/pubspec.lock index 779555b1..aea51a4d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.7.0" + ansi_styles: + dependency: transitive + description: + name: ansi_styles + sha256: "9c656cc12b3c27b17dd982b2cc5c0cfdfbdabd7bc8f3ae5e8542d9867b47ce8a" + url: "https://pub.dev" + source: hosted + version: "0.3.2+1" ansicolor: dependency: transitive description: @@ -30,6 +38,20 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + apidash_core: + dependency: "direct main" + description: + path: "packages/apidash_core" + relative: true + source: path + version: "0.0.1" + apidash_design_system: + dependency: "direct main" + description: + path: "packages/apidash_design_system" + relative: true + source: path + version: "0.0.1" archive: dependency: transitive description: @@ -158,6 +180,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" + source: hosted + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -174,6 +204,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + cli_launcher: + dependency: transitive + description: + name: cli_launcher + sha256: "5e7e0282b79e8642edd6510ee468ae2976d847a0a29b3916e85f5fa1bfe24005" + url: "https://pub.dev" + source: hosted + version: "0.3.1" cli_util: dependency: transitive description: @@ -199,13 +237,21 @@ packages: source: hosted version: "4.10.0" collection: - dependency: "direct main" + dependency: transitive description: name: collection sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted version: "1.18.0" + conventional_commit: + dependency: transitive + description: + name: conventional_commit + sha256: dec15ad1118f029c618651a4359eb9135d8b88f761aa24e4016d061cd45948f2 + url: "https://pub.dev" + source: hosted + version: "0.6.0+1" convert: dependency: transitive description: @@ -588,7 +634,7 @@ packages: source: hosted version: "2.5.7" freezed_annotation: - dependency: "direct main" + dependency: transitive description: name: freezed_annotation sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 @@ -625,7 +671,7 @@ packages: source: hosted version: "2.1.2" google_fonts: - dependency: "direct main" + dependency: transitive description: name: google_fonts sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 @@ -689,7 +735,7 @@ packages: source: hosted version: "2.0.0" http: - dependency: "direct main" + dependency: transitive description: name: http sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 @@ -705,7 +751,7 @@ packages: source: hosted version: "3.2.1" http_parser: - dependency: "direct main" + dependency: transitive description: name: http_parser sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" @@ -910,6 +956,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.1" + melos: + dependency: "direct dev" + description: + name: melos + sha256: a62abfa8c7826cec927f8585572bb9adf591be152150494d879ca2c75118809d + url: "https://pub.dev" + source: hosted + version: "6.2.0" meta: dependency: transitive description: @@ -959,6 +1013,14 @@ packages: url: "https://github.com/foss42/multi_trigger_autocomplete.git" source: git version: "1.0.1" + mustache_template: + dependency: transitive + description: + name: mustache_template + sha256: a46e26f91445bfb0b60519be280555b06792460b27b19e2b19ad5b9740df5d1c + url: "https://pub.dev" + source: hosted + version: "2.0.0" nanoid2: dependency: transitive description: @@ -1167,6 +1229,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.2" + prompts: + dependency: transitive + description: + name: prompts + sha256: "3773b845e85a849f01e793c4fc18a45d52d7783b4cb6c0569fad19f9d0a774a1" + url: "https://pub.dev" + source: hosted + version: "2.0.0" provider: dependency: "direct main" description: @@ -1183,6 +1253,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pub_updater: + dependency: transitive + description: + name: pub_updater + sha256: "54e8dc865349059ebe7f163d6acce7c89eb958b8047e6d6e80ce93b13d7c9e60" + url: "https://pub.dev" + source: hosted + version: "0.4.0" + pubspec: + dependency: transitive + description: + name: pubspec + sha256: f534a50a2b4d48dc3bc0ec147c8bd7c304280fff23b153f3f11803c4d49d927e + url: "https://pub.dev" + source: hosted + version: "2.3.0" pubspec_parse: dependency: transitive description: @@ -1199,6 +1285,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + quiver: + dependency: transitive + description: + name: quiver + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 + url: "https://pub.dev" + source: hosted + version: "3.2.2" riverpod: dependency: "direct main" description: @@ -1508,6 +1602,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + uri: + dependency: transitive + description: + name: uri + sha256: "889eea21e953187c6099802b7b4cf5219ba8f3518f604a1033064d45b1b8268a" + url: "https://pub.dev" + source: hosted + version: "1.0.0" url_launcher: dependency: "direct main" description: @@ -1734,7 +1836,7 @@ packages: source: hosted version: "1.0.4" xml: - dependency: "direct main" + dependency: transitive description: name: xml sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 @@ -1749,6 +1851,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + yaml_edit: + dependency: transitive + description: + name: yaml_edit + sha256: e9c1a3543d2da0db3e90270dbb1e4eebc985ee5e3ffe468d83224472b2194a5f + url: "https://pub.dev" + source: hosted + version: "2.2.1" sdks: - dart: ">=3.5.0-259.0.dev <3.999.0" + dart: ">=3.5.3 <3.999.0" flutter: ">=3.24.2" diff --git a/pubspec.yaml b/pubspec.yaml index 66dde1e8..50849da9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,8 +10,11 @@ environment: dependencies: flutter: sdk: flutter + apidash_core: + path: packages/apidash_core + apidash_design_system: + path: packages/apidash_design_system code_builder: ^4.10.0 - collection: ^1.18.0 csv: ^6.0.0 curl_converter: git: @@ -29,14 +32,10 @@ dependencies: flutter_riverpod: ^2.5.1 flutter_svg: ^2.0.10+1 flutter_typeahead: ^5.2.0 - freezed_annotation: ^2.4.1 fvp: ^0.26.1 - google_fonts: ^6.2.1 highlighter: ^0.1.1 hive_flutter: ^1.1.0 hooks_riverpod: ^2.5.2 - http: ^1.2.1 - http_parser: ^4.0.2 intl: ^0.19.0 jinja: ^0.6.0 json_annotation: ^4.9.0 @@ -74,7 +73,6 @@ dependencies: git: url: https://github.com/google/flutter-desktop-embedding.git path: plugins/window_size - xml: ^6.3.0 dependency_overrides: extended_text_field: ^16.0.0 @@ -92,12 +90,11 @@ dev_dependencies: json_serializable: ^6.7.1 integration_test: sdk: flutter + melos: ^6.2.0 spot: ^0.13.0 test: ^1.25.2 flutter: uses-material-design: true assets: - - google_fonts/ - assets/ - - assets/intro/ diff --git a/screenshots/apidash-desktop.png b/screenshots/apidash-desktop.png new file mode 100644 index 00000000..1414c5ca Binary files /dev/null and b/screenshots/apidash-desktop.png differ diff --git a/screenshots/apidash-mobile.png b/screenshots/apidash-mobile.png new file mode 100644 index 00000000..013f87bb Binary files /dev/null and b/screenshots/apidash-mobile.png differ diff --git a/screenshots/apidash.png b/screenshots/apidash.png new file mode 100644 index 00000000..87acb23c Binary files /dev/null and b/screenshots/apidash.png differ diff --git a/assets/intro/dark-darkmode.gif b/screenshots/dark-darkmode.gif similarity index 100% rename from assets/intro/dark-darkmode.gif rename to screenshots/dark-darkmode.gif diff --git a/assets/intro/dark-download.png b/screenshots/dark-download.png similarity index 100% rename from assets/intro/dark-download.png rename to screenshots/dark-download.png diff --git a/assets/intro/dark-emoji.png b/screenshots/dark-emoji.png similarity index 100% rename from assets/intro/dark-emoji.png rename to screenshots/dark-emoji.png diff --git a/assets/intro/dark-rename.gif b/screenshots/dark-rename.gif similarity index 100% rename from assets/intro/dark-rename.gif rename to screenshots/dark-rename.gif diff --git a/assets/intro/dark-ui.png b/screenshots/dark-ui.png similarity index 100% rename from assets/intro/dark-ui.png rename to screenshots/dark-ui.png diff --git a/assets/intro/light-darkmode.gif b/screenshots/light-darkmode.gif similarity index 100% rename from assets/intro/light-darkmode.gif rename to screenshots/light-darkmode.gif diff --git a/assets/intro/light-download.png b/screenshots/light-download.png similarity index 100% rename from assets/intro/light-download.png rename to screenshots/light-download.png diff --git a/assets/intro/light-emoji.png b/screenshots/light-emoji.png similarity index 100% rename from assets/intro/light-emoji.png rename to screenshots/light-emoji.png diff --git a/assets/intro/light-rename.gif b/screenshots/light-rename.gif similarity index 100% rename from assets/intro/light-rename.gif rename to screenshots/light-rename.gif diff --git a/assets/intro/light-ui.png b/screenshots/light-ui.png similarity index 100% rename from assets/intro/light-ui.png rename to screenshots/light-ui.png diff --git a/test/codegen/rust_hyper_codegen_test.dart b/test/codegen/rust_hyper_codegen_test.dart new file mode 100644 index 00000000..6c70173e --- /dev/null +++ b/test/codegen/rust_hyper_codegen_test.dart @@ -0,0 +1,997 @@ +import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/consts.dart'; +import 'package:test/test.dart'; +import '../models/request_models.dart'; + +void main() { + final codeGen = Codegen(); + group('GET Request', () { + test('GET1', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet1, "https"), + expectedCode); + }); + test('GET2', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/country/data?code=US".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet2, "https"), + expectedCode); + }); + + test('GET3', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/country/data?code=IND".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet3, "https"), + expectedCode); + }); + + test('GET4', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/humanize/social?num=8700000&digits=3&system=SS&add_space=true&trailing_zeros=true".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet4, "https"), + expectedCode); + }); + + test('GET5', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.github.com/repos/foss42/apidash".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet5, "https"), + expectedCode); + }); + + test('GET6', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.github.com/repos/foss42/apidash?raw=true".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet6, "https"), + expectedCode); + }); + + test('GET7', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet7, "https"), + expectedCode); + }); + + test('GET8', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.github.com/repos/foss42/apidash?raw=true".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet8, "https"), + expectedCode); + }); + test('GET9', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/humanize/social?num=8700000&add_space=true".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelGet9, "https"), + expectedCode); + }); + + test('GET10', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/humanize/social".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelGet10, "https"), + expectedCode); + }); + + test('GET11', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/humanize/social?num=8700000&digits=3".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelGet11, "https"), + expectedCode); + }); + + test('GET12', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/humanize/social".parse::().unwrap(); + let req_builder = Request::builder() + .method("GET") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelGet12, "https"), + expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD1', () { + const expectedCode = """ +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev".parse::().unwrap(); + let req_builder = Request::builder() + .method("HEAD") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelHead1, "https"), + expectedCode); + }); + + test('HEAD2', () { + const expectedCode = """ +use hyper::{Body, Client, Request, Uri}; +use hyper::client::HttpConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let http = HttpConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(http); + let url = "http://api.apidash.dev".parse::().unwrap(); + let req_builder = Request::builder() + .method("HEAD") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelHead2, "http"), + expectedCode); + }); + }); + + group('POST Request', () { + test('POST1', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/case/lower".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url) + .body(Body::from(r#"{ +"text": "I LOVE Flutter" +}"#))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost1, "https"), + expectedCode); + }); + test('POST2', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use serde_json::json; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/case/lower".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url) + .body(Body::from(json!({ +"text": "I LOVE Flutter", +"flag": null, +"male": true, +"female": false, +"no": 1.2, +"arr": ["null", "true", "false", null] +}).to_string()))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost2, "https"), + expectedCode); + }); + test('POST3', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use serde_json::json; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/case/lower".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url) + .header("User-Agent", "Test Agent") + + .body(Body::from(json!({ +"text": "I LOVE Flutter" +}).to_string()))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost3, "https"), + expectedCode); + }); + test('POST4', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/form".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url); + let mut form = multipart::Form::default(); + form.add_text("text", "API"); + form.add_text("sep", "|"); + form.add_text("times", "3"); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost4, "https"), + expectedCode); + }); + test('POST5', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/form".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url) + .header("User-Agent", "Test Agent"); + + let mut form = multipart::Form::default(); + form.add_text("text", "API"); + form.add_text("sep", "|"); + form.add_text("times", "3"); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost5, "https"), + expectedCode); + }); + test('POST6', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/img".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url); + let mut form = multipart::Form::default(); + form.add_text("token", "xyz"); + form.add_file("imfile", r"/Documents/up/1.png").unwrap(); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost6, "https"), + expectedCode); + }); + test('POST7', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/img".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url); + let mut form = multipart::Form::default(); + form.add_text("token", "xyz"); + form.add_file("imfile", r"/Documents/up/1.png").unwrap(); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost7, "https"), + expectedCode); + }); + test('POST8', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/form?size=2&len=3".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url); + let mut form = multipart::Form::default(); + form.add_text("text", "API"); + form.add_text("sep", "|"); + form.add_text("times", "3"); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost8, "https"), + expectedCode); + }); + test('POST9', () { + const expectedCode = r""" +extern crate hyper_multipart_rfc7578 as hyper_multipart; +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use hyper_multipart::client::multipart; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://api.apidash.dev/io/img?size=2&len=3".parse::().unwrap(); + let req_builder = Request::builder() + .method("POST") + .uri(url) + .header("User-Agent", "Test Agent") + + .header("Keep-Alive", "true"); + + let mut form = multipart::Form::default(); + form.add_text("token", "xyz"); + form.add_file("imfile", r"/Documents/up/1.png").unwrap(); + + let req = form.set_body_convert::(req_builder).unwrap(); + + let res = client.request(req).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPost9, "https"), + expectedCode); + }); + }); + + group('PUT Request', () { + test('PUT1', () { + const expectedCode = """ +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use serde_json::json; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://reqres.in/api/users/2".parse::().unwrap(); + let req_builder = Request::builder() + .method("PUT") + .uri(url) + .body(Body::from(json!({ +"name": "morpheus", +"job": "zion resident" +}).to_string()))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode(CodegenLanguage.rustHyper, requestModelPut1, "https"), + expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH1', () { + const expectedCode = """ +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use serde_json::json; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://reqres.in/api/users/2".parse::().unwrap(); + let req_builder = Request::builder() + .method("PATCH") + .uri(url) + .body(Body::from(json!({ +"name": "marfeus", +"job": "accountant" +}).to_string()))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelPatch1, "https"), + expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE1', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://reqres.in/api/users/2".parse::().unwrap(); + let req_builder = Request::builder() + .method("DELETE") + .uri(url) + .body(Body::empty())?; + + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelDelete1, "https"), + expectedCode); + }); + test('DELETE2', () { + const expectedCode = r""" +use hyper::{Body, Client, Request, Uri}; +use hyper_tls::HttpsConnector; +use serde_json::json; +use tokio; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, hyper::Body>(https); + let url = "https://reqres.in/api/users/2".parse::().unwrap(); + let req_builder = Request::builder() + .method("DELETE") + .uri(url) + .body(Body::from(json!({ +"name": "marfeus", +"job": "accountant" +}).to_string()))?; + let res = client.request(req_builder).await?; + let status = res.status(); + let body_bytes = hyper::body::to_bytes(res).await?; + let body = String::from_utf8(body_bytes.to_vec())?; + + println!("Response Status: {}", status); + println!("Response: {:?}", body); + + Ok(()) +} + +"""; + expect( + codeGen.getCode( + CodegenLanguage.rustHyper, requestModelDelete2, "https"), + expectedCode); + }); + }); +} diff --git a/test/models/history_models.dart b/test/models/history_models.dart index 13d1603f..5deeb655 100644 --- a/test/models/history_models.dart +++ b/test/models/history_models.dart @@ -1,6 +1,6 @@ -import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart' show HistoryMetaModel, HistoryRequestModel; +import 'package:apidash_core/apidash_core.dart'; import 'http_request_models.dart'; import 'http_response_models.dart'; diff --git a/test/models/history_models_test.dart b/test/models/history_models_test.dart index 7f2ae5aa..91a085e9 100644 --- a/test/models/history_models_test.dart +++ b/test/models/history_models_test.dart @@ -1,7 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; - import 'history_models.dart'; import 'http_request_models.dart'; import 'http_response_models.dart'; diff --git a/test/models/http_request_model_test.dart b/test/models/http_request_model_test.dart index ec7494a3..78a52097 100644 --- a/test/models/http_request_model_test.dart +++ b/test/models/http_request_model_test.dart @@ -1,6 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; import 'http_request_models.dart'; void main() { diff --git a/test/models/http_request_models.dart b/test/models/http_request_models.dart index a9eeed3f..9f42bc4a 100644 --- a/test/models/http_request_models.dart +++ b/test/models/http_request_models.dart @@ -1,6 +1,4 @@ -import 'package:apidash/models/models.dart' - show FormDataModel, NameValueModel, HttpRequestModel; -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; /// Basic GET request model const httpRequestModelGet1 = HttpRequestModel( diff --git a/test/models/http_response_models.dart b/test/models/http_response_models.dart index 001aa46c..5b04ce3b 100644 --- a/test/models/http_response_models.dart +++ b/test/models/http_response_models.dart @@ -1,5 +1,5 @@ import 'dart:typed_data'; -import 'package:apidash/models/models.dart'; +import 'package:apidash_core/apidash_core.dart'; const int statusCode = 200; const Map headers = { diff --git a/test/models/response_model_test.dart b/test/models/response_model_test.dart index 4f3b1089..c5deb183 100644 --- a/test/models/response_model_test.dart +++ b/test/models/response_model_test.dart @@ -1,5 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; -import 'package:apidash/models/models.dart'; import 'package:http/http.dart' as http; import 'http_response_models.dart'; diff --git a/test/providers/collection_providers_test.dart b/test/providers/collection_providers_test.dart index fb939522..097b71f0 100644 --- a/test/providers/collection_providers_test.dart +++ b/test/providers/collection_providers_test.dart @@ -1,6 +1,6 @@ -import 'package:apidash/consts.dart'; import 'package:apidash/screens/home_page/editor_pane/details_card/request_pane/request_body.dart'; import 'package:apidash/widgets/editor.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index e8fd0582..f75a7d19 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -13,8 +13,9 @@ import 'package:apidash/screens/settings_page.dart'; import 'package:apidash/screens/history/history_page.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:extended_text_field/extended_text_field.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +// import 'package:flutter/services.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -27,9 +28,10 @@ void main() { setUp(() async { await testSetUpTempDirForHive(); - final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf'); - final fontLoader = FontLoader('OpenSans')..addFont(flamante); - await fontLoader.load(); + // FIXME: Font file moved to design system so this must be fixed if spot screenshot is used + // final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf'); + // final fontLoader = FontLoader('OpenSans')..addFont(flamante); + // await fontLoader.load(); }); group('Testing navRailIndexStateProvider', () { @@ -279,7 +281,7 @@ void main() { }); testWidgets( - 'selectedIdEditStateProvider should not be null after rename button has been tapped', + 'selectedIdEditStateProvider should not be null after Duplicate button has been tapped', (tester) async { await tester.pumpWidget( ProviderScope( @@ -304,7 +306,11 @@ void main() { await tester.pump(); await tester.tap(find.byType(RequestItem)); await tester.pump(); - await tester.tap(find.byIcon(Icons.more_vert).at(1)); + //await tester.tap(find.byIcon(Icons.more_vert).at(1)); + await tester.tap( + find.byType(RequestItem), + buttons: kSecondaryButton, + ); await tester.pumpAndSettle(); // Tap on the "Duplicate" option in the menu @@ -313,7 +319,7 @@ void main() { await tester.tap(byType); await tester.pumpAndSettle(); - // Screenshot using spot + // INFO: Screenshot using spot // await takeScreenshot(); var dupId = container.read(selectedIdStateProvider); diff --git a/test/screens/common_widgets/env_trigger_field_test.dart b/test/screens/common_widgets/env_trigger_field_test.dart index 622f10ac..c4ec063e 100644 --- a/test/screens/common_widgets/env_trigger_field_test.dart +++ b/test/screens/common_widgets/env_trigger_field_test.dart @@ -45,4 +45,46 @@ void main() { expect(fieldKey.currentState!.controller.text, updatedValue); }); + + testWidgets( + 'Testing EnvironmentTriggerField with empty initialValue clears the controller text', + (WidgetTester tester) async { + final fieldKey = GlobalKey(); + const initialValue = 'initial'; + const emptyValue = ''; + + await tester.pumpWidget( + Portal( + child: MaterialApp( + home: Scaffold( + body: EnvironmentTriggerField( + key: fieldKey, + keyId: 'testKey', + initialValue: initialValue, + ), + ), + ), + ), + ); + + Finder field = find.byType(ExtendedTextField); + expect(field, findsOneWidget); + expect(fieldKey.currentState!.controller.text, initialValue); + + await tester.pumpWidget( + Portal( + child: MaterialApp( + home: Scaffold( + body: EnvironmentTriggerField( + key: fieldKey, + keyId: 'testKey', + initialValue: emptyValue, + ), + ), + ), + ), + ); + + expect(fieldKey.currentState!.controller.text, emptyValue); + }); } diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index ab853bfe..45ac5556 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -1,8 +1,6 @@ -import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; import 'package:apidash/utils/convert_utils.dart'; -import 'package:apidash/models/name_value_model.dart'; -import 'package:apidash/models/form_data_model.dart'; void main() { group("Testing humanizeDate function", () { diff --git a/test/utils/envvar_utils_test.dart b/test/utils/envvar_utils_test.dart index 84b14652..5c166566 100644 --- a/test/utils/envvar_utils_test.dart +++ b/test/utils/envvar_utils_test.dart @@ -1,6 +1,7 @@ import 'package:apidash/models/models.dart'; import 'package:apidash/utils/envvar_utils.dart'; import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; import 'package:test/test.dart'; const envVars = [ diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 2b660fcb..0f777ab1 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -1,9 +1,7 @@ +import 'package:apidash_core/apidash_core.dart' show MediaType; import 'package:test/test.dart'; -import 'package:http_parser/http_parser.dart'; import 'package:apidash/utils/http_utils.dart'; -import 'package:apidash/models/name_value_model.dart'; import 'package:apidash/consts.dart'; -import '../test_utilities.dart'; void main() { group("Testing getRequestTitleFromUrl function", () { @@ -40,203 +38,6 @@ void main() { }); }); - group("Testing getContentTypeFromHeaders function", () { - test('Testing getContentTypeFromHeaders for header1', () { - Map header1 = { - "content-type": "application/json", - }; - String contentType1Expected = "application/json"; - expect(getContentTypeFromHeaders(header1), contentType1Expected); - }); - test('Testing getContentTypeFromHeaders for null headers', () { - expect(getContentTypeFromHeaders(null), null); - }); - test( - 'Testing getContentTypeFromHeaders when header keys are in header case', - () { - Map header2 = { - "Content-Type": "application/json", - }; - expect(getContentTypeFromHeaders(header2), null); - }); - }); - - group('Testing getMediaTypeFromContentType function', () { - test('Testing getMediaTypeFromContentType for json type', () { - String contentType1 = "application/json"; - MediaType mediaType1Expected = MediaType("application", "json"); - expect(getMediaTypeFromContentType(contentType1).toString(), - mediaType1Expected.toString()); - }); - test('Testing getMediaTypeFromContentType for null', () { - expect(getMediaTypeFromContentType(null), null); - }); - test('Testing getMediaTypeFromContentType for image svg+xml type', () { - String contentType3 = "image/svg+xml"; - MediaType mediaType3Expected = MediaType("image", "svg+xml"); - expect(getMediaTypeFromContentType(contentType3).toString(), - mediaType3Expected.toString()); - }); - test('Testing getMediaTypeFromContentType for incorrect content type', () { - String contentType4 = "text/html : charset=utf-8"; - expect(getMediaTypeFromContentType(contentType4), null); - }); - test('Testing getMediaTypeFromContentType for text/css type', () { - String contentType5 = "text/css; charset=utf-8"; - MediaType mediaType5Expected = - MediaType("text", "css", {"charset": "utf-8"}); - expect(getMediaTypeFromContentType(contentType5).toString(), - mediaType5Expected.toString()); - }); - test('Testing getMediaTypeFromContentType for incorrect with double ;', () { - String contentType6 = - "application/xml; charset=utf-16be ; date=21/03/2023"; - expect(getMediaTypeFromContentType(contentType6), null); - }); - test('Testing getMediaTypeFromContentType for empty content type', () { - expect(getMediaTypeFromContentType(""), null); - }); - test('Testing getMediaTypeFromContentType for missing subtype', () { - String contentType7 = "audio"; - expect(getMediaTypeFromContentType(contentType7), null); - }); - test('Testing getMediaTypeFromContentType for missing Type', () { - String contentType8 = "/html"; - expect(getMediaTypeFromContentType(contentType8), null); - }); - }); - - group("Testing getMediaTypeFromHeaders", () { - test('Testing getMediaTypeFromHeaders for basic case', () { - Map header1 = { - "content-length": "4506", - "cache-control": "private", - "content-type": "application/json" - }; - MediaType mediaType1Expected = MediaType("application", "json"); - expect(getMediaTypeFromHeaders(header1).toString(), - mediaType1Expected.toString()); - }); - test('Testing getMediaTypeFromHeaders for null header', () { - expect(getMediaTypeFromHeaders(null), null); - }); - test('Testing getMediaTypeFromHeaders for incomplete header value', () { - Map header2 = {"content-length": "4506"}; - expect(getMediaTypeFromHeaders(header2), null); - }); - test('Testing getMediaTypeFromHeaders for empty header value', () { - Map header3 = {"content-type": ""}; - expect(getMediaTypeFromHeaders(header3), null); - }); - test( - 'Testing getMediaTypeFromHeaders for erroneous header value - missing type', - () { - Map header4 = {"content-type": "/json"}; - expect(getMediaTypeFromHeaders(header4), null); - }); - test( - 'Testing getMediaTypeFromHeaders for erroneous header value - missing subtype', - () { - Map header5 = {"content-type": "application"}; - expect(getMediaTypeFromHeaders(header5), null); - }); - test('Testing getMediaTypeFromHeaders for header6', () { - Map header6 = {"content-type": "image/svg+xml"}; - MediaType mediaType6Expected = MediaType("image", "svg+xml"); - expect(getMediaTypeFromHeaders(header6).toString(), - mediaType6Expected.toString()); - }); - }); - - group("Testing getUriScheme", () { - test('Testing getUriScheme for https', () { - Uri uri1 = Uri( - scheme: 'https', - host: 'dart.dev', - path: 'guides/libraries/library-tour', - fragment: 'numbers'); - String uriScheme1Expected = 'https'; - expect(getUriScheme(uri1), (uriScheme1Expected, true)); - }); - test('Testing getUriScheme for mailto scheme value', () { - Uri uri2 = Uri(scheme: 'mailto'); - String uriScheme2Expected = 'mailto'; - expect(getUriScheme(uri2), (uriScheme2Expected, false)); - }); - test('Testing getUriScheme for empty scheme value', () { - Uri uri3 = Uri(scheme: ''); - expect(getUriScheme(uri3), (null, false)); - }); - test('Testing getUriScheme for null scheme value', () { - Uri uri4 = Uri(scheme: null); - expect(getUriScheme(uri4), (null, false)); - }); - }); - - group("Testing getValidRequestUri", () { - test('Testing getValidRequestUri for normal values', () { - String url1 = "https://api.apidash.dev/country/data"; - const kvRow1 = NameValueModel(name: "code", value: "US"); - Uri uri1Expected = Uri( - scheme: 'https', - host: 'api.apidash.dev', - path: 'country/data', - queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url1, [kvRow1]), (uri1Expected, null)); - }); - test('Testing getValidRequestUri for null url value', () { - const kvRow2 = NameValueModel(name: "code", value: "US"); - expect(getValidRequestUri(null, [kvRow2]), (null, "URL is missing!")); - }); - test('Testing getValidRequestUri for empty url value', () { - const kvRow3 = NameValueModel(name: "", value: ""); - expect(getValidRequestUri("", [kvRow3]), (null, "URL is missing!")); - }); - test('Testing getValidRequestUri when https is not provided in url', () { - String url4 = "api.apidash.dev/country/data"; - const kvRow4 = NameValueModel(name: "code", value: "US"); - Uri uri4Expected = Uri( - scheme: 'https', - host: 'api.apidash.dev', - path: 'country/data', - queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url4, [kvRow4]), (uri4Expected, null)); - }); - test('Testing getValidRequestUri when url has fragment', () { - String url5 = "https://dart.dev/guides/libraries/library-tour#numbers"; - Uri uri5Expected = Uri( - scheme: 'https', - host: 'dart.dev', - path: '/guides/libraries/library-tour'); - expect(getValidRequestUri(url5, null), (uri5Expected, null)); - }); - test('Testing getValidRequestUri when uri scheme is not supported', () { - String url5 = "mailto:someone@example.com"; - expect(getValidRequestUri(url5, null), - (null, "Unsupported URL Scheme (mailto)")); - }); - test('Testing getValidRequestUri when query params in both url and kvrow', - () { - String url6 = "api.apidash.dev/country/data?code=IND"; - const kvRow6 = NameValueModel(name: "code", value: "US"); - Uri uri6Expected = Uri( - scheme: 'https', - host: 'api.apidash.dev', - path: 'country/data', - queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null)); - }); - test('Testing getValidRequestUri when kvrow is null', () { - String url7 = "api.apidash.dev/country/data?code=US"; - Uri uri7Expected = Uri( - scheme: 'https', - host: 'api.apidash.dev', - path: 'country/data', - queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url7, null), (uri7Expected, null)); - }); - }); - group("Testing getResponseBodyViewOptions", () { test('Testing getResponseBodyViewOptions for application/json', () { MediaType mediaType1 = MediaType("application", "json"); @@ -305,80 +106,4 @@ void main() { expect(result10.$2, "calendar"); }); }); - - group("Testing formatBody", () { - test('Testing formatBody for null values', () { - expect(formatBody(null, null), null); - }); - test('Testing formatBody for null body values', () { - MediaType mediaType1 = MediaType("application", "xml"); - expect(formatBody(null, mediaType1), null); - }); - test('Testing formatBody for null MediaType values', () { - String body1 = ''' - { - "text":"The Chosen One"; - } -'''; - expect(formatBody(body1, null), null); - }); - test('Testing formatBody for json subtype values', () { - String body2 = '''{"data":{"area":9831510.0,"population":331893745}}'''; - MediaType mediaType2 = MediaType("application", "json"); - String result2Expected = '''{ - "data": { - "area": 9831510.0, - "population": 331893745 - } -}'''; - expect(formatBody(body2, mediaType2), result2Expected); - }); - test('Testing formatBody for xml subtype values', () { - String body3 = ''' - - -Belgian Waffles -5.95 USD -Two of our famous Belgian Waffles with plenty of real maple syrup -650 - - -'''; - MediaType mediaType3 = MediaType("application", "xml"); - String result3Expected = ''' - - Belgian Waffles - 5.95 USD - Two of our famous Belgian Waffles with plenty of real maple syrup - 650 - -'''; - expect(formatBody(body3, mediaType3), result3Expected); - }); - group("Testing formatBody for html", () { - MediaType mediaTypeHtml = MediaType("text", "html"); - test('Testing formatBody for html subtype values', () { - String body4 = ''' - -

My First Heading

-

My first paragraph.

- -'''; - expect(formatBody(body4, mediaTypeHtml), body4); - }); - - test('Testing formatBody for html subtype values with random values', () { - String body5 = - '''${RandomStringGenerator.getRandomStringLines(100, 10000)}'''; - expect(formatBody(body5, mediaTypeHtml), null); - }); - test( - 'Testing formatBody for html subtype values with random values within limit', - () { - String body6 = - '''${RandomStringGenerator.getRandomStringLines(100, 190)}'''; - expect(formatBody(body6, mediaTypeHtml), body6); - }); - }); - }); } diff --git a/test/utils/ui_utils_test.dart b/test/utils/ui_utils_test.dart index 4d5a686b..c990f70d 100644 --- a/test/utils/ui_utils_test.dart +++ b/test/utils/ui_utils_test.dart @@ -1,3 +1,5 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:test/test.dart'; import 'package:apidash/utils/ui_utils.dart'; import 'package:flutter/material.dart'; diff --git a/test/widgets/card_history_request_test.dart b/test/widgets/card_history_request_test.dart index becc9d7f..7c811a88 100644 --- a/test/widgets/card_history_request_test.dart +++ b/test/widgets/card_history_request_test.dart @@ -1,9 +1,9 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/widgets/texts.dart'; import 'package:apidash/utils/utils.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/widgets/card_history_request.dart'; void main() { diff --git a/test/widgets/card_sidebar_history_test.dart b/test/widgets/card_sidebar_history_test.dart index 472831df..a4d3c0a1 100644 --- a/test/widgets/card_sidebar_history_test.dart +++ b/test/widgets/card_sidebar_history_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart'; import '../test_consts.dart'; diff --git a/test/widgets/card_sidebar_request_test.dart b/test/widgets/card_sidebar_request_test.dart index d3ba3155..2d1f2be9 100644 --- a/test/widgets/card_sidebar_request_test.dart +++ b/test/widgets/card_sidebar_request_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import '../test_consts.dart'; void main() { diff --git a/test/widgets/code_previewer_test.dart b/test/widgets/code_previewer_test.dart index 56bb3384..73f09ead 100644 --- a/test/widgets/code_previewer_test.dart +++ b/test/widgets/code_previewer_test.dart @@ -1,9 +1,9 @@ +import 'package:apidash_core/apidash_core.dart' show RandomStringGenerator; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/code_previewer.dart'; -import 'package:apidash/consts.dart'; import '../test_consts.dart'; -import '../test_utilities.dart'; void main() { String code = r'''import 'package:http/http.dart' as http; diff --git a/test/widgets/codegen_previewer_test.dart b/test/widgets/codegen_previewer_test.dart index cc337d2c..549bb00a 100644 --- a/test/widgets/codegen_previewer_test.dart +++ b/test/widgets/codegen_previewer_test.dart @@ -1,5 +1,6 @@ import 'package:apidash/widgets/widgets.dart' show ViewCodePane, CodeGenPreviewer; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/consts.dart'; diff --git a/test/widgets/dropdown_content_type_test.dart b/test/widgets/dropdown_content_type_test.dart index 62e10cc6..f39a2a68 100644 --- a/test/widgets/dropdown_content_type_test.dart +++ b/test/widgets/dropdown_content_type_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import '../test_consts.dart'; void main() { diff --git a/test/widgets/dropdown_formdata_test.dart b/test/widgets/dropdown_formdata_test.dart index 2b7b5238..4766d4a9 100644 --- a/test/widgets/dropdown_formdata_test.dart +++ b/test/widgets/dropdown_formdata_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import '../test_consts.dart'; void main() { diff --git a/test/widgets/dropdowns_http_method_test.dart b/test/widgets/dropdowns_http_method_test.dart index 663face7..5fe2a080 100644 --- a/test/widgets/dropdowns_http_method_test.dart +++ b/test/widgets/dropdowns_http_method_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import '../test_consts.dart'; void main() { diff --git a/test/widgets/field_read_only_test.dart b/test/widgets/field_read_only_test.dart index 4c198246..82a5e34b 100644 --- a/test/widgets/field_read_only_test.dart +++ b/test/widgets/field_read_only_test.dart @@ -1,7 +1,7 @@ import 'package:apidash/widgets/field_read_only.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:apidash/consts.dart'; void main() { testWidgets('Testing ReadOnlyTextField displays initial value and decoration', diff --git a/test/widgets/menu_item_card_test.dart b/test/widgets/menu_item_card_test.dart index 52cbcabf..d223eeb6 100644 --- a/test/widgets/menu_item_card_test.dart +++ b/test/widgets/menu_item_card_test.dart @@ -49,4 +49,32 @@ void main() { expect(changedValue, ItemMenuOption.duplicate); }); + + testWidgets('showItemCardMenu shows the menu at the right position', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Builder( + builder: (BuildContext context) { + return GestureDetector( + onTapUp: (details) { + showItemCardMenu( + context, details, (ItemMenuOption option) {}); + }, + child: const Text('Show Menu'), + ); + }, + ), + ), + ), + ); + + await tester.tap(find.text('Show Menu')); + await tester.pumpAndSettle(); + + for (var option in ItemMenuOption.values) { + expect(find.text(option.label), findsOneWidget); + } + }); } diff --git a/test/widgets/previewer_test.dart b/test/widgets/previewer_test.dart index 3a2cbb44..7bf0ac92 100644 --- a/test/widgets/previewer_test.dart +++ b/test/widgets/previewer_test.dart @@ -1,7 +1,7 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; import 'package:flutter/foundation.dart'; import 'package:printing/printing.dart' show PdfPreview; import 'package:flutter_svg/flutter_svg.dart' show SvgPicture; diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 74df9a1b..ecb22bed 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -1,6 +1,6 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; -import 'package:http_parser/http_parser.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/response_widgets.dart'; import 'package:lottie/lottie.dart'; diff --git a/test/widgets/table_request_form_test.dart b/test/widgets/table_request_form_test.dart index c21a9b70..49438d75 100644 --- a/test/widgets/table_request_form_test.dart +++ b/test/widgets/table_request_form_test.dart @@ -1,9 +1,8 @@ +import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; void main() { dataTableShowLogs = false; diff --git a/test/widgets/texts_test.dart b/test/widgets/texts_test.dart index 8fcdfa30..303a6d0f 100644 --- a/test/widgets/texts_test.dart +++ b/test/widgets/texts_test.dart @@ -1,8 +1,9 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/utils/utils.dart' show getDarkModeColor; import 'package:apidash/widgets/texts.dart'; -import 'package:apidash/consts.dart'; void main() { testWidgets('Testing when method is GET', (tester) async {