diff --git a/package.json b/package.json
index 9aaaf23f..67faaf11 100644
--- a/package.json
+++ b/package.json
@@ -20,9 +20,11 @@
"@playwright/test": "^1.27.1",
"husky": "^8.0.3",
"jest": "^29.2.0",
+ "prettier": "^2.0.2",
"pretty-quick": "^3.1.3",
"randomstring": "^1.2.2",
- "ts-jest": "^29.0.5"
+ "ts-jest": "^29.0.5",
+ "typescript": "^5.2.2"
},
"scripts": {
"dev:web": "npm run dev --workspace=packages/bruno-app",
diff --git a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js
index 9b56ca1b..bfe59ae8 100644
--- a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js
+++ b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js
@@ -29,9 +29,7 @@ const CreateCollection = ({ onClose }) => {
.max(50, 'must be 50 characters or less')
.matches(/^[\w\-. ]+$/, 'Folder name contains invalid characters')
.required('folder name is required'),
- collectionLocation: Yup.string()
- .min(1, 'location is required')
- .required('location is required'),
+ collectionLocation: Yup.string().min(1, 'location is required').required('location is required')
}),
onSubmit: (values) => {
dispatch(createCollection(values.collectionName, values.collectionFolderName, values.collectionLocation))
@@ -116,7 +114,10 @@ const CreateCollection = ({ onClose }) => {
{
return nameSuffix;
}, 0);
return nameSuffix !== 0 ? `${item.name}_${nameSuffix}` : item.name;
-}
+};
const transformInsomniaRequestItem = (request, index, allRequests) => {
const name = addSuffixToDuplicateName(request, index, allRequests);
diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js
index abc5583f..f4af7092 100644
--- a/packages/bruno-app/src/utils/network/index.js
+++ b/packages/bruno-app/src/utils/network/index.js
@@ -1,10 +1,8 @@
export const sendNetworkRequest = async (item, collection, environment, collectionVariables) => {
return new Promise((resolve, reject) => {
if (['http-request', 'graphql-request'].includes(item.type)) {
- const timeStart = Date.now();
sendHttpRequest(item, collection, environment, collectionVariables)
.then((response) => {
- const timeEnd = Date.now();
resolve({
state: 'success',
data: response.data,
@@ -12,7 +10,7 @@ export const sendNetworkRequest = async (item, collection, environment, collecti
size: response.headers['content-length'] || 0,
status: response.status,
statusText: response.statusText,
- duration: timeEnd - timeStart
+ duration: response.duration
});
})
.catch((err) => reject(err));
diff --git a/packages/bruno-electron/src/ipc/network/axios-instance.js b/packages/bruno-electron/src/ipc/network/axios-instance.js
new file mode 100644
index 00000000..f4abd839
--- /dev/null
+++ b/packages/bruno-electron/src/ipc/network/axios-instance.js
@@ -0,0 +1,38 @@
+const axios = require('axios');
+
+/**
+ * Function that configures axios with timing interceptors
+ * Important to note here that the timings are not completely accurate.
+ * @see https://github.com/axios/axios/issues/695
+ * @returns {import('axios').AxiosStatic}
+ */
+function makeAxiosInstance() {
+ /** @type {import('axios').AxiosStatic} */
+ const instance = axios.create();
+
+ instance.interceptors.request.use((config) => {
+ config.headers['request-start-time'] = Date.now();
+ return config;
+ });
+
+ instance.interceptors.response.use(
+ (response) => {
+ const end = Date.now();
+ const start = response.config.headers['request-start-time'];
+ response.headers['request-duration'] = end - start;
+ return response;
+ },
+ (error) => {
+ const end = Date.now();
+ const start = error.config.headers['request-start-time'];
+ error.response.headers['request-duration'] = end - start;
+ return Promise.reject(error);
+ }
+ );
+
+ return instance;
+}
+
+module.exports = {
+ makeAxiosInstance
+};
diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js
index 9b92dbfa..c3ade9c0 100644
--- a/packages/bruno-electron/src/ipc/network/index.js
+++ b/packages/bruno-electron/src/ipc/network/index.js
@@ -15,6 +15,7 @@ const { sortFolder, getAllRequestsInFolderRecursively } = require('./helper');
const { getPreferences } = require('../../store/preferences');
const { getProcessEnvVars } = require('../../store/process-env');
const { getBrunoConfig } = require('../../store/bruno-config');
+const { makeAxiosInstance } = require('./axios-instance');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {
@@ -242,7 +243,10 @@ const registerNetworkIpc = (mainWindow) => {
});
}
- const response = await axios(request);
+ const axiosInstance = makeAxiosInstance();
+
+ /** @type {import('axios').AxiosResponse} */
+ const response = await axiosInstance(request);
// run post-response vars
const postResponseVars = get(request, 'vars.res', []);
@@ -347,12 +351,16 @@ const registerNetworkIpc = (mainWindow) => {
}
deleteCancelToken(cancelTokenUid);
+ // Prevents the duration on leaking to the actual result
+ const requestDuration = response.headers.get('request-duration');
+ response.headers.delete('request-duration');
return {
status: response.status,
statusText: response.statusText,
headers: response.headers,
- data: response.data
+ data: response.data,
+ duration: requestDuration
};
} catch (error) {
// todo: better error handling
@@ -421,11 +429,15 @@ const registerNetworkIpc = (mainWindow) => {
});
}
+ // Prevents the duration from leaking to the actual result
+ const requestDuration = error.response.headers.get('request-duration');
+ error.response.headers.delete('request-duration');
return {
status: error.response.status,
statusText: error.response.statusText,
headers: error.response.headers,
- data: error.response.data
+ data: error.response.data,
+ duration: requestDuration ?? 0
};
}