From dda1673a0fbf9335deae768ecc8a150f97006d40 Mon Sep 17 00:00:00 2001 From: Maintainer Bruno Date: Tue, 15 Jul 2025 02:19:21 +0530 Subject: [PATCH] feat(url): move url encoding utils to bruno common --- .../ReduxStore/slices/collections/actions.js | 3 +- .../ReduxStore/slices/collections/index.js | 3 +- .../bruno-app/src/utils/curl/curl-to-json.js | 4 +- .../bruno-app/src/utils/curl/parse-curl.js | 2 +- packages/bruno-app/src/utils/url/index.js | 54 ------- .../bruno-app/src/utils/url/index.spec.js | 70 +-------- .../src/runner/run-single-request.js | 2 +- packages/bruno-common/package.json | 5 + packages/bruno-common/rollup.config.js | 6 + packages/bruno-common/src/index.ts | 2 + packages/bruno-common/src/utils/index.ts | 5 + .../src/utils/url/index.spec.ts | 6 +- .../src/utils/url/index.ts | 40 ++++-- .../bruno-electron/src/ipc/network/index.js | 2 +- .../src/utils/cookie-utils.spec.js | 133 ++++++++++++++++++ packages/bruno-requests/src/utils/index.ts | 1 - 16 files changed, 189 insertions(+), 149 deletions(-) create mode 100644 packages/bruno-common/src/utils/index.ts rename packages/{bruno-requests => bruno-common}/src/utils/url/index.spec.ts (98%) rename packages/{bruno-requests => bruno-common}/src/utils/url/index.ts (62%) create mode 100644 packages/bruno-requests/src/utils/cookie-utils.spec.js diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 7c097916e..4749958e3 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -1,4 +1,5 @@ import { collectionSchema, environmentSchema, itemSchema } from '@usebruno/schema'; +import { parseQueryParams } from '@usebruno/common/utils'; import cloneDeep from 'lodash/cloneDeep'; import filter from 'lodash/filter'; import find from 'lodash/find'; @@ -43,7 +44,7 @@ import { import { each } from 'lodash'; import { closeAllCollectionTabs } from 'providers/ReduxStore/slices/tabs'; import { resolveRequestFilename } from 'utils/common/platform'; -import { parsePathParams, parseQueryParams, splitOnFirst } from 'utils/url/index'; +import { parsePathParams, splitOnFirst } from 'utils/url/index'; import { sendCollectionOauth2Request as _sendCollectionOauth2Request } from 'utils/network/index'; import { getGlobalEnvironmentVariables, findCollectionByPathname, findEnvironmentInCollectionByName, getReorderedItemsInTargetDirectory, resetSequencesInFolder, getReorderedItemsInSourceDirectory, calculateDraggedItemNewPathname } from 'utils/collections/index'; import { sanitizeName } from 'utils/common/regex'; 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 490eabd91..fa3c28aee 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -1,3 +1,4 @@ +import { parseQueryParams, buildQueryString as stringifyQueryParams } from '@usebruno/common/utils'; import { uuid } from 'utils/common'; import { find, map, forOwn, concat, filter, each, cloneDeep, get, set, findIndex } from 'lodash'; import { createSlice } from '@reduxjs/toolkit'; @@ -15,7 +16,7 @@ import { isItemAFolder, isItemARequest } from 'utils/collections'; -import { parsePathParams, parseQueryParams, splitOnFirst, stringifyQueryParams } from 'utils/url'; +import { parsePathParams, splitOnFirst } from 'utils/url'; import { getSubdirectoriesFromRoot } from 'utils/common/platform'; import toast from 'react-hot-toast'; import mime from 'mime-types'; diff --git a/packages/bruno-app/src/utils/curl/curl-to-json.js b/packages/bruno-app/src/utils/curl/curl-to-json.js index b6d6a323f..21daf8283 100644 --- a/packages/bruno-app/src/utils/curl/curl-to-json.js +++ b/packages/bruno-app/src/utils/curl/curl-to-json.js @@ -9,7 +9,7 @@ import parseCurlCommand from './parse-curl'; import * as querystring from 'query-string'; import * as jsesc from 'jsesc'; -import { stringifyQueryParams } from '../url'; +import { buildQueryString } from '@usebruno/common/utils'; function getContentType(headers = {}) { const contentType = Object.keys(headers).find((key) => key.toLowerCase() === 'content-type'); @@ -163,7 +163,7 @@ const curlToJson = (curlCommand) => { } if (request.queries) { - requestJson.url = requestJson.url + '?' + stringifyQueryParams(request.queries, { encode: false }); + requestJson.url = requestJson.url + '?' + buildQueryString(request.queries, { encode: false }); } if (request.multipartUploads) { diff --git a/packages/bruno-app/src/utils/curl/parse-curl.js b/packages/bruno-app/src/utils/curl/parse-curl.js index 592f54817..d44aa547a 100644 --- a/packages/bruno-app/src/utils/curl/parse-curl.js +++ b/packages/bruno-app/src/utils/curl/parse-curl.js @@ -2,7 +2,7 @@ import cookie from 'cookie'; import URL from 'url'; import { parse } from 'shell-quote'; import { isEmpty } from 'lodash'; -import { parseQueryParams } from '../url'; +import { parseQueryParams } from '@usebruno/common/utils'; /** * Flag definitions - maps flag names to their states and actions diff --git a/packages/bruno-app/src/utils/url/index.js b/packages/bruno-app/src/utils/url/index.js index 577a89cdf..7f9bdcc99 100644 --- a/packages/bruno-app/src/utils/url/index.js +++ b/packages/bruno-app/src/utils/url/index.js @@ -1,6 +1,3 @@ -import isEmpty from 'lodash/isEmpty'; -import trim from 'lodash/trim'; -import each from 'lodash/each'; import find from 'lodash/find'; import { interpolate } from '@usebruno/common'; @@ -15,35 +12,6 @@ const hasLength = (str) => { return str.length > 0; }; -export const parseQueryParams = (query, { decode = false } = {}) => { - try { - if (!query || !query.length) { - return []; - } - - const [queryString, ...hashParts] = query.split('#'); - const pairs = queryString.split('&'); - - const params = pairs.map(pair => { - const [key, ...valueParts] = pair.split('='); - - if (!key) { - return null; - } - - return { - name: decode ? decodeURIComponent(key) : key, - value: decode ? decodeURIComponent(valueParts.join('=')) : valueParts.join('=') - }; - }).filter(Boolean); - - return params; - } catch (error) { - console.error('Error parsing query params:', error); - return []; - } -}; - export const parsePathParams = (url) => { let uri = url.slice(); @@ -79,28 +47,6 @@ export const parsePathParams = (url) => { return paths; }; -export const stringifyQueryParams = (params, { encode = false } = {}) => { - if (!params || isEmpty(params)) { - return ''; - } - - let queryString = []; - each(params, (p) => { - const hasEmptyName = isEmpty(trim(p.name)); - const hasEmptyVal = isEmpty(p.value); - - // query param name must be present - if (!hasEmptyName) { - const finalName = encode ? encodeURIComponent(p.name) : p.name; - const finalValue = encode ? encodeURIComponent(p.value) : p.value; - - queryString.push(hasEmptyVal ? finalName : `${finalName}=${finalValue}`); - } - }); - - return queryString.join('&'); -}; - export const splitOnFirst = (str, char) => { if (!str || !str.length) { return [str]; diff --git a/packages/bruno-app/src/utils/url/index.spec.js b/packages/bruno-app/src/utils/url/index.spec.js index 0645befee..8ecd0531d 100644 --- a/packages/bruno-app/src/utils/url/index.spec.js +++ b/packages/bruno-app/src/utils/url/index.spec.js @@ -1,72 +1,4 @@ -import { parseQueryParams, splitOnFirst, parsePathParams, interpolateUrl, interpolateUrlPathParams } from './index'; - -describe('Url Utils - parseQueryParams', () => { - it('should parse query - case 1', () => { - const params = parseQueryParams(''); - expect(params).toEqual([]); - }); - - it('should parse query - case 2', () => { - const params = parseQueryParams('a'); - expect(params).toEqual([{ name: 'a', value: '' }]); - }); - - it('should parse query - case 3', () => { - const params = parseQueryParams('a='); - expect(params).toEqual([{ name: 'a', value: '' }]); - }); - - it('should parse query - case 4', () => { - const params = parseQueryParams('a=1'); - expect(params).toEqual([{ name: 'a', value: '1' }]); - }); - - it('should parse query - case 5', () => { - const params = parseQueryParams('a=1&'); - expect(params).toEqual([{ name: 'a', value: '1' }]); - }); - - it('should parse query - case 6', () => { - const params = parseQueryParams('a=1&b'); - expect(params).toEqual([ - { name: 'a', value: '1' }, - { name: 'b', value: '' } - ]); - }); - - it('should parse query - case 7', () => { - const params = parseQueryParams('a=1&b='); - expect(params).toEqual([ - { name: 'a', value: '1' }, - { name: 'b', value: '' } - ]); - }); - - it('should parse query - case 8', () => { - const params = parseQueryParams('a=1&b=2'); - expect(params).toEqual([ - { name: 'a', value: '1' }, - { name: 'b', value: '2' } - ]); - }); - - it('should parse query with "=" character - case 9', () => { - const params = parseQueryParams('a=1&b={color=red,size=large}&c=3'); - expect(params).toEqual([ - { name: 'a', value: '1' }, - { name: 'b', value: '{color=red,size=large}' }, - { name: 'c', value: '3' } - ]); - }); - - it('should parse query with fragment - case 10', () => { - const params = parseQueryParams('a=1&b=2#I-AM-FRAGMENT'); - expect(params).toEqual([ - { name: 'a', value: '1' }, - { name: 'b', value: '2' } - ]); - }); -}); +import { splitOnFirst, parsePathParams, interpolateUrl, interpolateUrlPathParams } from './index'; describe('Url Utils - parsePathParams', () => { it('should parse path - case 1', () => { diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index f39d79762..e8ecb4d61 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -26,7 +26,7 @@ const { getOAuth2Token } = require('./oauth2'); const protocolRegex = /^([-+\w]{1,25})(:?\/\/|:)/; const { NtlmClient } = require('axios-ntlm'); const { addDigestInterceptor } = require('@usebruno/requests'); -const { encodeUrl } = require('@usebruno/requests').utils; +const { encodeUrl } = require('@usebruno/common').utils; const onConsoleLog = (type, args) => { console[type](...args); diff --git a/packages/bruno-common/package.json b/packages/bruno-common/package.json index a29f586ec..66ded2519 100644 --- a/packages/bruno-common/package.json +++ b/packages/bruno-common/package.json @@ -15,6 +15,11 @@ "require": "./dist/runner/cjs/index.js", "import": "./dist/runner/esm/index.js", "types": "./dist/runner/index.d.ts" + }, + "./utils": { + "require": "./dist/utils/cjs/index.js", + "import": "./dist/utils/esm/index.js", + "types": "./dist/utils/index.d.ts" } }, "files": [ diff --git a/packages/bruno-common/rollup.config.js b/packages/bruno-common/rollup.config.js index 8eec5127f..398379451 100644 --- a/packages/bruno-common/rollup.config.js +++ b/packages/bruno-common/rollup.config.js @@ -55,5 +55,11 @@ module.exports = [ input: 'src/runner/index.ts', cjsOutput: 'dist/runner/cjs/index.js', esmOutput: 'dist/runner/esm/index.js' + }), + ...createBuildConfig({ + inputDir: 'src/utils/**/*', + input: 'src/utils/index.ts', + cjsOutput: 'dist/utils/cjs/index.js', + esmOutput: 'dist/utils/esm/index.js' }) ]; diff --git a/packages/bruno-common/src/index.ts b/packages/bruno-common/src/index.ts index c49e79d58..591a710c9 100644 --- a/packages/bruno-common/src/index.ts +++ b/packages/bruno-common/src/index.ts @@ -1,2 +1,4 @@ export { mockDataFunctions } from './utils/faker-functions'; export { default as interpolate } from './interpolate'; + +export * as utils from './utils'; diff --git a/packages/bruno-common/src/utils/index.ts b/packages/bruno-common/src/utils/index.ts new file mode 100644 index 000000000..70c92ea7c --- /dev/null +++ b/packages/bruno-common/src/utils/index.ts @@ -0,0 +1,5 @@ +export { + encodeUrl, + parseQueryParams, + buildQueryString +} from './url'; diff --git a/packages/bruno-requests/src/utils/url/index.spec.ts b/packages/bruno-common/src/utils/url/index.spec.ts similarity index 98% rename from packages/bruno-requests/src/utils/url/index.spec.ts rename to packages/bruno-common/src/utils/url/index.spec.ts index 4a6ecc353..e9815e306 100644 --- a/packages/bruno-requests/src/utils/url/index.spec.ts +++ b/packages/bruno-common/src/utils/url/index.spec.ts @@ -46,7 +46,7 @@ describe('encodeUrl', () => { it('should handle query parameters with empty values', () => { const url = 'https://example.com/api?name=&age=25&active='; - const expected = 'https://example.com/api?name=&age=25&active='; + const expected = 'https://example.com/api?name&age=25&active'; expect(encodeUrl(url)).toBe(expected); }); @@ -196,7 +196,7 @@ describe('buildQueryString', () => { { name: 'name', value: 'john doe' }, { name: 'email', value: 'john@example.com' } ]; - const result = buildQueryString(params); + const result = buildQueryString(params, { encode: true }); expect(result).toBe('name=john%20doe&email=john%40example.com'); }); @@ -206,7 +206,7 @@ describe('buildQueryString', () => { { name: 'sort', value: 'name|asc' }, { name: 'tags', value: 'frontend|backend|api' } ]; - const result = buildQueryString(params); + const result = buildQueryString(params, { encode: true }); expect(result).toBe('filter=status%7Cactive&sort=name%7Casc&tags=frontend%7Cbackend%7Capi'); }); diff --git a/packages/bruno-requests/src/utils/url/index.ts b/packages/bruno-common/src/utils/url/index.ts similarity index 62% rename from packages/bruno-requests/src/utils/url/index.ts rename to packages/bruno-common/src/utils/url/index.ts index 201623100..7b3debebb 100644 --- a/packages/bruno-requests/src/utils/url/index.ts +++ b/packages/bruno-common/src/utils/url/index.ts @@ -11,35 +11,45 @@ interface ExtractQueryParamsOptions { decode?: boolean; } -function buildQueryString(paramsArray: QueryParam[], { encode = true }: BuildQueryStringOptions = {}): string { +function buildQueryString(paramsArray: QueryParam[], { encode = false }: BuildQueryStringOptions = {}): string { return paramsArray .filter(({ name }) => typeof name === 'string' && name.trim().length > 0) .map(({ name, value }) => { const finalName = encode ? encodeURIComponent(name) : name; const finalValue = encode ? encodeURIComponent(value ?? '') : (value ?? ''); - return `${finalName}=${finalValue}`; + return finalValue ? `${finalName}=${finalValue}` : finalName; }) .join('&'); } -function parseQueryParams(queryString: string, { decode = false }: ExtractQueryParamsOptions = {}): QueryParam[] { - const pairs = queryString.split('&'); +function parseQueryParams(query: string, { decode = false }: ExtractQueryParamsOptions = {}): QueryParam[] { + if (!query || !query.length) { + return []; + } - const params = pairs.map(pair => { - const [name, ...valueParts] = pair.split('='); + try { + const [queryString, ...hashParts] = query.split('#'); + const pairs = queryString.split('&'); - if (!name) { - return null; - } + const params = pairs.map(pair => { + const [name, ...valueParts] = pair.split('='); - return { - name: decode ? decodeURIComponent(name) : name, - value: decode ? decodeURIComponent(valueParts.join('=')) : valueParts.join('=') - }; - }).filter((param): param is NonNullable => param !== null); + if (!name) { + return null; + } - return params; + return { + name: decode ? decodeURIComponent(name) : name, + value: decode ? decodeURIComponent(valueParts.join('=')) : valueParts.join('=') + }; + }).filter((param): param is NonNullable => param !== null); + + return params; + } catch (error) { + console.error('Error parsing query params:', error); + return []; + } } const encodeUrl = (url: string): string => { diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index f369d0416..583ff11cd 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -12,7 +12,7 @@ const { ipcMain } = require('electron'); const { each, get, extend, cloneDeep, merge } = require('lodash'); const { NtlmClient } = require('axios-ntlm'); const { VarsRuntime, AssertRuntime, ScriptRuntime, TestRuntime } = require('@usebruno/js'); -const { encodeUrl } = require('@usebruno/requests').utils; +const { encodeUrl } = require('@usebruno/common').utils; const { interpolateString } = require('./interpolate-string'); const { resolveAwsV4Credentials, addAwsV4Interceptor } = require('./awsv4auth-helper'); const { addDigestInterceptor } = require('@usebruno/requests'); diff --git a/packages/bruno-requests/src/utils/cookie-utils.spec.js b/packages/bruno-requests/src/utils/cookie-utils.spec.js new file mode 100644 index 000000000..90e8e74c3 --- /dev/null +++ b/packages/bruno-requests/src/utils/cookie-utils.spec.js @@ -0,0 +1,133 @@ +const { isPotentiallyTrustworthyOrigin } = require('./cookie-utils'); + +describe('isPotentiallyTrustworthyOrigin', () => { + describe('secure schemes', () => { + it('should return true for HTTPS URLs', () => { + expect(isPotentiallyTrustworthyOrigin('https://example.com')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('https://api.github.com/v1/users')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('https://localhost:3000')).toBe(true); + }); + + it('should return true for WSS URLs', () => { + expect(isPotentiallyTrustworthyOrigin('wss://example.com')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('wss://localhost:8080/ws')).toBe(true); + }); + + it('should return true for file URLs', () => { + expect(isPotentiallyTrustworthyOrigin('file:///path/to/file.html')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('file://localhost/path/to/file.html')).toBe(true); + }); + }); + + describe('insecure schemes', () => { + it('should return false for HTTP URLs with non-localhost domains', () => { + expect(isPotentiallyTrustworthyOrigin('http://example.com')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://api.github.com')).toBe(false); + }); + + it('should return false for WS URLs with non-localhost domains', () => { + expect(isPotentiallyTrustworthyOrigin('ws://example.com')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('ws://api.github.com')).toBe(false); + }); + + it('should return false for other schemes', () => { + expect(isPotentiallyTrustworthyOrigin('ftp://example.com')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('ssh://example.com')).toBe(false); + }); + + it('should return true for HTTP/WS URLs with localhost (localhost is always trustworthy)', () => { + expect(isPotentiallyTrustworthyOrigin('http://localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('ws://localhost')).toBe(true); + }); + }); + + describe('loopback addresses', () => { + describe('IPv4 loopback', () => { + it('should return true for 127.0.0.1', () => { + expect(isPotentiallyTrustworthyOrigin('http://127.0.0.1')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://127.0.0.1:3000')).toBe(true); + }); + + it('should return true for other 127.x.x.x addresses', () => { + expect(isPotentiallyTrustworthyOrigin('http://127.0.0.0')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://127.255.255.255')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://127.1.2.3')).toBe(true); + }); + + it('should return false for non-loopback IPv4 addresses', () => { + expect(isPotentiallyTrustworthyOrigin('http://192.168.1.1')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://10.0.0.1')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://172.16.0.1')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://8.8.8.8')).toBe(false); + }); + }); + + describe('IPv6 loopback', () => { + it('should return true for ::1', () => { + expect(isPotentiallyTrustworthyOrigin('http://[::1]')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://[::1]:3000')).toBe(true); + }); + + it('should return false for non-loopback IPv6 addresses', () => { + expect(isPotentiallyTrustworthyOrigin('http://[2001:db8::1]')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://[fe80::1]')).toBe(false); + }); + }); + }); + + describe('localhost hostnames', () => { + it('should return true for localhost and *.localhost domains', () => { + expect(isPotentiallyTrustworthyOrigin('http://localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://localhost:3000')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://app.localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://api.localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://sub.domain.localhost')).toBe(true); + }); + + it('should handle case insensitive localhost', () => { + expect(isPotentiallyTrustworthyOrigin('http://LOCALHOST')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://LocalHost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://APP.LOCALHOST')).toBe(true); + }); + + it('should return false for non-localhost domains', () => { + expect(isPotentiallyTrustworthyOrigin('http://api.example.com')).toBe(false); + expect(isPotentiallyTrustworthyOrigin('http://localhost.example.com')).toBe(false); + }); + }); + + describe('edge cases', () => { + it('should handle trailing dots in hostnames', () => { + expect(isPotentiallyTrustworthyOrigin('http://localhost.')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://app.localhost.')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://example.com.')).toBe(false); + }); + + it('should handle URLs with query parameters and fragments', () => { + expect(isPotentiallyTrustworthyOrigin('https://example.com/path?query=value#fragment')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://localhost/path?query=value#fragment')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://api.example.com/path?query=value#fragment')).toBe(false); + }); + + it('should handle URLs with authentication', () => { + expect(isPotentiallyTrustworthyOrigin('https://user:pass@example.com')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://user:pass@localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('http://user:pass@api.example.com')).toBe(false); + }); + }); + + describe('mixed scenarios', () => { + it('should prioritize secure schemes over hostname checks', () => { + // Even though example.com is not localhost, HTTPS makes it trustworthy + expect(isPotentiallyTrustworthyOrigin('https://example.com')).toBe(true); + + // Even though 192.168.1.1 is not loopback, HTTPS makes it trustworthy + expect(isPotentiallyTrustworthyOrigin('https://192.168.1.1')).toBe(true); + }); + + it('should handle localhost with different schemes', () => { + expect(isPotentiallyTrustworthyOrigin('https://localhost')).toBe(true); + expect(isPotentiallyTrustworthyOrigin('wss://localhost')).toBe(true); + }); + }); +}); diff --git a/packages/bruno-requests/src/utils/index.ts b/packages/bruno-requests/src/utils/index.ts index af511b957..dd94dd186 100644 --- a/packages/bruno-requests/src/utils/index.ts +++ b/packages/bruno-requests/src/utils/index.ts @@ -1,2 +1 @@ export * from './cookie-utils'; -export * from './url';