From e5ddc4f9f7d77e5b2e30cd6c3a432fcce83093b2 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sat, 7 Oct 2023 18:31:22 +0530 Subject: [PATCH] feat: JS/node.js axios codegen --- lib/codegen/codegen.dart | 6 + lib/codegen/js/axios.dart | 104 +++++ lib/consts.dart | 2 + test/codegen/js_axios_codegen_test.dart | 428 ++++++++++++++++++ test/codegen/nodejs_axios_codegen_test.dart | 462 ++++++++++++++++++++ 5 files changed, 1002 insertions(+) create mode 100644 lib/codegen/js/axios.dart create mode 100644 test/codegen/js_axios_codegen_test.dart create mode 100644 test/codegen/nodejs_axios_codegen_test.dart diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 1a30ec16..356854f6 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -4,6 +4,7 @@ import 'dart/http.dart'; import 'kotlin/okhttp.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; +import 'js/axios.dart'; import 'js/fetch.dart'; import 'others/har.dart'; import 'others/curl.dart'; @@ -21,8 +22,13 @@ class Codegen { return HARCodeGen().getCode(requestModel, defaultUriScheme); case CodegenLanguage.dartHttp: return DartHttpCodeGen().getCode(requestModel, defaultUriScheme); + case CodegenLanguage.jsAxios: + return AxiosCodeGen().getCode(requestModel, defaultUriScheme); case CodegenLanguage.jsFetch: return FetchCodeGen().getCode(requestModel, defaultUriScheme); + case CodegenLanguage.nodejsAxios: + return AxiosCodeGen(isNodeJs: true) + .getCode(requestModel, defaultUriScheme); case CodegenLanguage.nodejsFetch: return FetchCodeGen(isNodeJs: true) .getCode(requestModel, defaultUriScheme); diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart new file mode 100644 index 00000000..21c99c8b --- /dev/null +++ b/lib/codegen/js/axios.dart @@ -0,0 +1,104 @@ +import 'package:apidash/consts.dart'; +import 'package:jinja/jinja.dart' as jj; +import 'package:apidash/utils/utils.dart' + show requestModelToHARJsonRequest, padMultilineString, stripUrlParams; +import 'package:apidash/models/models.dart' show RequestModel; + +class AxiosCodeGen { + AxiosCodeGen({this.isNodeJs = false}); + + final bool isNodeJs; + + String kStringImportNode = """import axios from 'axios'; + +"""; + + String kTemplateStart = """let config = { + url: '{{url}}', + method: '{{method}}' +"""; + + String kTemplateParams = """, + params: {{params}} +"""; + + String kTemplateHeader = """, + headers: {{headers}} +"""; + + String kTemplateBody = """, + data: {{body}} +"""; + + String kStringRequest = """ + +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + + String? getCode( + RequestModel requestModel, + String defaultUriScheme, + ) { + try { + String result = isNodeJs ? kStringImportNode : ""; + + String url = requestModel.url; + if (!url.contains("://") && url.isNotEmpty) { + url = "$defaultUriScheme://$url"; + } + var rM = requestModel.copyWith(url: url); + + var harJson = requestModelToHARJsonRequest(rM); + + var templateStart = jj.Template(kTemplateStart); + result += templateStart.render({ + "url": stripUrlParams(url), + "method": harJson["method"].toLowerCase(), + }); + + var params = harJson["queryString"]; + if (params.isNotEmpty) { + var templateParams = jj.Template(kTemplateParams); + var m = {}; + for (var i in params) { + m[i["name"]] = i["value"]; + } + result += templateParams + .render({"params": padMultilineString(kEncoder.convert(m), 2)}); + } + + var headers = harJson["headers"]; + if (headers.isNotEmpty) { + var templateHeader = jj.Template(kTemplateHeader); + var m = {}; + for (var i in headers) { + m[i["name"]] = i["value"]; + } + result += templateHeader + .render({"headers": padMultilineString(kEncoder.convert(m), 2)}); + } + + if (harJson["postData"]?["text"] != null) { + var templateBody = jj.Template(kTemplateBody); + result += templateBody + .render({"body": kEncoder.convert(harJson["postData"]["text"])}); + } + result += kStringRequest; + return result; + } catch (e) { + return null; + } + } +} diff --git a/lib/consts.dart b/lib/consts.dart index c8f489be..588b96ed 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -234,7 +234,9 @@ enum CodegenLanguage { curl("cURL", "bash", "curl"), har("HAR", "json", "har"), dartHttp("Dart (http)", "dart", "dart"), + jsAxios("JavaScript (axios)", "javascript", "js"), jsFetch("JavaScript (fetch)", "javascript", "js"), + nodejsAxios("node.js (axios)", "javascript", "js"), nodejsFetch("node.js (fetch)", "javascript", "js"), kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"), pythonHttpClient("Python (http.client)", "python", "py"), diff --git a/test/codegen/js_axios_codegen_test.dart b/test/codegen/js_axios_codegen_test.dart new file mode 100644 index 00000000..d809a122 --- /dev/null +++ b/test/codegen/js_axios_codegen_test.dart @@ -0,0 +1,428 @@ +import 'package:apidash/codegen/js/axios.dart'; +import '../request_models.dart'; +import 'package:test/test.dart'; + +void main() { + final axiosCodeGen = AxiosCodeGen(); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet1, "https"), expectedCode); + }); + + test('GET 2', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/country/data', + method: 'get', + params: { + "code": "US" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet2, "https"), expectedCode); + }); + + test('GET 3', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/country/data', + method: 'get', + params: { + "code": "IND" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet3, "https"), expectedCode); + }); + + test('GET 4', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3", + "system": "SS", + "add_space": "true", + "trailing_zeros": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet4, "https"), expectedCode); + }); + + test('GET 5', () { + const expectedCode = r"""let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet5, "https"), expectedCode); + }); + + test('GET 6', () { + const expectedCode = r"""let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + params: { + "raw": "true" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet6, "https"), expectedCode); + }); + + test('GET 7', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet7, "https"), expectedCode); + }); + + test('GET 8', () { + const expectedCode = r"""let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + params: { + "raw": "true" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet8, "https"), expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com', + method: 'head' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelHead1, "https"), expectedCode); + }); + + test('HEAD 2', () { + const expectedCode = r"""let config = { + url: 'http://api.foss42.com', + method: 'head' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelHead2, "http"), expectedCode); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "text/plain" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost1, "https"), expectedCode); + }); + + test('POST 2', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost2, "https"), expectedCode); + }); + + test('POST 3', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "application/json", + "User-Agent": "Test Agent" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost3, "https"), expectedCode); + }); + }); + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""let config = { + url: 'https://reqres.in/api/users/2', + method: 'put', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPut1, "https"), expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""let config = { + url: 'https://reqres.in/api/users/2', + method: 'patch', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPatch1, "https"), expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""let config = { + url: 'https://reqres.in/api/users/2', + method: 'delete' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDelete1, "https"), expectedCode); + }); + + test('DELETE 2', () { + const expectedCode = r"""let config = { + url: 'https://reqres.in/api/users/2', + method: 'delete', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); + }); + }); +} diff --git a/test/codegen/nodejs_axios_codegen_test.dart b/test/codegen/nodejs_axios_codegen_test.dart new file mode 100644 index 00000000..180edb8a --- /dev/null +++ b/test/codegen/nodejs_axios_codegen_test.dart @@ -0,0 +1,462 @@ +import 'package:apidash/codegen/js/axios.dart'; +import '../request_models.dart'; +import 'package:test/test.dart'; + +void main() { + final axiosCodeGen = AxiosCodeGen(isNodeJs: true); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet1, "https"), expectedCode); + }); + + test('GET 2', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/country/data', + method: 'get', + params: { + "code": "US" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet2, "https"), expectedCode); + }); + + test('GET 3', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/country/data', + method: 'get', + params: { + "code": "IND" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet3, "https"), expectedCode); + }); + + test('GET 4', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3", + "system": "SS", + "add_space": "true", + "trailing_zeros": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet4, "https"), expectedCode); + }); + + test('GET 5', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet5, "https"), expectedCode); + }); + + test('GET 6', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + params: { + "raw": "true" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet6, "https"), expectedCode); + }); + + test('GET 7', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet7, "https"), expectedCode); + }); + + test('GET 8', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.github.com/repos/foss42/apidash', + method: 'get', + params: { + "raw": "true" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet8, "https"), expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com', + method: 'head' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelHead1, "https"), expectedCode); + }); + + test('HEAD 2', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'http://api.foss42.com', + method: 'head' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelHead2, "http"), expectedCode); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "text/plain" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost1, "https"), expectedCode); + }); + + test('POST 2', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost2, "https"), expectedCode); + }); + + test('POST 3', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/case/lower', + method: 'post', + headers: { + "Content-Type": "application/json", + "User-Agent": "Test Agent" + }, + data: "{\n\"text\": \"I LOVE Flutter\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPost3, "https"), expectedCode); + }); + }); + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://reqres.in/api/users/2', + method: 'put', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPut1, "https"), expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://reqres.in/api/users/2', + method: 'patch', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelPatch1, "https"), expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://reqres.in/api/users/2', + method: 'delete' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDelete1, "https"), expectedCode); + }); + + test('DELETE 2', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://reqres.in/api/users/2', + method: 'delete', + headers: { + "Content-Type": "application/json" + }, + data: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); + }); + }); +}