diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index 7be069c17..625e9dc0d 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -30,6 +30,7 @@ "graphiql": "^1.5.9", "graphql": "^16.6.0", "graphql-request": "^3.7.0", + "handlebars": "^4.7.8", "httpsnippet": "^3.0.1", "idb": "^7.0.0", "immer": "^9.0.15", diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js index ba100b4fe..79d636daf 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js @@ -1,21 +1,21 @@ import CodeEditor from 'components/CodeEditor/index'; -import HTTPSnippet from 'httpsnippet'; +import { HTTPSnippet } from 'httpsnippet'; import { useTheme } from 'providers/Theme/index'; import { buildHarRequest } from 'utils/codegenerator/har'; -const index = ({ language, item }) => { - const { target, client, language: lang } = language; - const snippet = new HTTPSnippet(buildHarRequest(item.request)).convert(target, client); +const CodeView = ({ language, item }) => { const { storedTheme } = useTheme(); - return ( - - ); + const { target, client, language: lang } = language; + let snippet = ''; + + try { + snippet = new HTTPSnippet(buildHarRequest(item.request)).convert(target, client); + } catch (e) { + console.error(e); + snippet = 'Error generating code snippet'; + } + + return ; }; -export default index; +export default CodeView; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/StyledWrapper.js index 4b6eec556..f1c1c33e4 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/StyledWrapper.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/StyledWrapper.js @@ -3,7 +3,6 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` margin-inline: -1rem; margin-block: -1.5rem; - position: absolute; background-color: ${(props) => props.theme.collection.environment.settings.bg}; .generate-code-sidebar { diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js index 35f01972f..509a529bd 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js @@ -2,8 +2,28 @@ import Modal from 'components/Modal/index'; import { useState } from 'react'; import CodeView from './CodeView'; import StyledWrapper from './StyledWrapper'; -import ErrorBoundary from 'src/pages/ErrorBoundary/index'; import { isValidUrl } from 'utils/url/index'; +import get from 'lodash/get'; +import handlebars from 'handlebars'; +import { findEnvironmentInCollection } from 'utils/collections'; + +const interpolateUrl = ({ url, envVars, collectionVariables, processEnvVars }) => { + if (!url || !url.length || typeof url !== 'string') { + return str; + } + + const template = handlebars.compile(url, { noEscape: true }); + + return template({ + ...envVars, + ...collectionVariables, + process: { + env: { + ...processEnvVars + } + } + }); +}; const languages = [ { @@ -52,12 +72,32 @@ const languages = [ client: 'httpie' } ]; -const index = ({ item, onClose }) => { + +const GenerateCodeItem = ({ collection, item, onClose }) => { + const url = get(item, 'request.url') || ''; + const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid); + + let envVars = {}; + if (environment) { + const vars = get(environment, 'variables', []); + envVars = vars.reduce((acc, curr) => { + acc[curr.name] = curr.value; + return acc; + }, {}); + } + + const interpolatedUrl = interpolateUrl({ + url, + envVars, + collectionVariables: collection.collectionVariables, + processEnvVars: collection.processEnvVariables + }); + const [selectedLanguage, setSelectedLanguage] = useState(languages[0]); return ( - - -
+ + +
{languages && @@ -75,20 +115,31 @@ const index = ({ item, onClose }) => { ))}
- {isValidUrl(item.request.url) ? ( - - ) : ( -
-
-

Invalid URL

-

Please check the URL and try again

+
+ {isValidUrl(interpolatedUrl) ? ( + + ) : ( +
+
+

Invalid URL: {interpolatedUrl}

+

Please check the URL and try again

+
-
- )} + )} +
- - + + ); }; -export default index; +export default GenerateCodeItem; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js index a59503be0..daed44279 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js @@ -169,7 +169,7 @@ const CollectionItem = ({ item, collection, searchText }) => { setRunCollectionModalOpen(false)} /> )} {generateCodeItemModalOpen && ( - setGenerateCodeItemModalOpen(false)} /> + setGenerateCodeItemModalOpen(false)} /> )}
drag(drop(node))}>
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 24ad23a8d..213761029 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -44,9 +44,8 @@ export const collectionsSlice = createSlice({ // this is used in scenarios where we want to know the last action performed on the collection // and take some extra action based on that // for example, when a env is created, we want to auto select it the env modal - collection.importedAt = new Date().getTime() + collection.importedAt = new Date().getTime(); collection.lastAction = null; - console.log(collection) collapseCollection(collection); addDepth(collection.items); @@ -73,16 +72,16 @@ export const collectionsSlice = createSlice({ state.collections = filter(state.collections, (c) => c.uid !== action.payload.collectionUid); }, sortCollections: (state, action) => { - state.collectionSortOrder = action.payload.order + state.collectionSortOrder = action.payload.order; switch (action.payload.order) { case 'default': - state.collections = state.collections.sort((a, b) => a.importedAt - b.importedAt) + state.collections = state.collections.sort((a, b) => a.importedAt - b.importedAt); break; case 'alphabetical': - state.collections = state.collections.sort((a, b) => a.name.localeCompare(b.name)) + state.collections = state.collections.sort((a, b) => a.name.localeCompare(b.name)); break; case 'reverseAlphabetical': - state.collections = state.collections.sort((a, b) => b.name.localeCompare(a.name)) + state.collections = state.collections.sort((a, b) => b.name.localeCompare(a.name)); break; } }, diff --git a/packages/bruno-app/src/utils/codegenerator/har.js b/packages/bruno-app/src/utils/codegenerator/har.js index ada2854d7..b48fbc3c7 100644 --- a/packages/bruno-app/src/utils/codegenerator/har.js +++ b/packages/bruno-app/src/utils/codegenerator/har.js @@ -30,12 +30,11 @@ const createHeaders = (headers, mode) => { return headersArray; }; -const createQuery = (url) => { - const params = new URLSearchParams(url); - return params.forEach((value, name) => { +const createQuery = (queryParams = []) => { + return queryParams.map((param) => { return { - name, - value + name: param.name, + value: param.value }; }); }; @@ -57,28 +56,14 @@ const createPostData = (body) => { } }; -const createUrl = (request) => { - let url = request.url; - const variablePattern = /\{\{([^}]+)\}\}/g; - const variables = request.url.match(variablePattern); - if (variables) { - variables.forEach((variable) => { - const variableName = variable.replaceAll('{', '').replaceAll('}', ''); - const variableValue = request.vars.req.find((v) => v.name === variableName).value; - url = url.replace(variable, variableValue); - }); - } - return url; -}; - export const buildHarRequest = (request) => { return { method: request.method, - url: createUrl(request), + url: request.url, httpVersion: 'HTTP/1.1', cookies: [], headers: createHeaders(request.headers, request.body.mode), - queryString: createQuery(request.url), + queryString: createQuery(request.params), postData: createPostData(request.body), headersSize: 0, bodySize: 0