Import WSDL to collection (#5015)

* Import WSDL to bruno collection

* feat(wsdl-import): remove unused code and minor refactor

---------

Co-authored-by: Bijin Bruno <bijin@usebruno.com>
This commit is contained in:
Anton
2025-10-25 11:50:18 +02:00
committed by GitHub
parent 77bb8f40fe
commit a538b27f24
44 changed files with 1826 additions and 135 deletions

View File

@@ -45,7 +45,7 @@ const CollectionSettings = ({ collection }) => {
const authMode = get(collection, 'root.request.auth', {}).mode || 'none';
const presets = get(collection, 'brunoConfig.presets', []);
const hasPresets = presets && presets.requestUrl !== "";
const hasPresets = presets && presets.requestUrl !== '';
const proxyConfig = get(collection, 'brunoConfig.proxy', {});
const proxyEnabled = proxyConfig.hostname ? true : false;
@@ -167,7 +167,7 @@ const CollectionSettings = ({ collection }) => {
</div>
<div className={getTabClassname('presets')} role="tab" onClick={() => setTab('presets')}>
Presets
{hasPresets && <StatusDot />}
{hasPresets && <StatusDot />}
</div>
<div className={getTabClassname('proxy')} role="tab" onClick={() => setTab('proxy')}>
Proxy

View File

@@ -13,7 +13,7 @@ import {
IconChevronDown,
IconTerminal2,
IconNetwork,
IconDashboard,
IconDashboard
} from '@tabler/icons';
import {
closeConsole,

View File

@@ -5,7 +5,7 @@ const StyledWrapper = styled.div`
height: 100%;
display: flex;
flex-direction: column;
background: ${props => props.theme.console.bg};
background: ${(props) => props.theme.console.bg};
}
.tab-content-area {
@@ -30,19 +30,19 @@ const StyledWrapper = styled.div`
.section-header {
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid ${props => props.theme.console.border};
border-bottom: 1px solid ${(props) => props.theme.console.border};
h3 {
margin: 0 0 4px 0;
font-size: 16px;
font-weight: 600;
color: ${props => props.theme.console.titleColor};
color: ${(props) => props.theme.console.titleColor};
}
p {
margin: 0;
font-size: 13px;
color: ${props => props.theme.console.textMuted};
color: ${(props) => props.theme.console.textMuted};
}
}
@@ -53,7 +53,7 @@ const StyledWrapper = styled.div`
margin: 0 0 8px 0;
font-size: 14px;
font-weight: 600;
color: ${props => props.theme.console.titleColor};
color: ${(props) => props.theme.console.titleColor};
}
}
@@ -65,8 +65,8 @@ const StyledWrapper = styled.div`
}
.resource-card {
background: ${props => props.theme.console.headerBg};
border: 1px solid ${props => props.theme.console.border};
background: ${(props) => props.theme.console.headerBg};
border: 1px solid ${(props) => props.theme.console.border};
border-radius: 4px;
padding: 8px;
}
@@ -76,7 +76,7 @@ const StyledWrapper = styled.div`
align-items: center;
gap: 6px;
margin-bottom: 6px;
color: ${props => props.theme.console.titleColor};
color: ${(props) => props.theme.console.titleColor};
}
.resource-title {
@@ -87,13 +87,13 @@ const StyledWrapper = styled.div`
.resource-value {
font-size: 18px;
font-weight: 600;
color: ${props => props.theme.console.titleColor};
color: ${(props) => props.theme.console.titleColor};
margin-bottom: 2px;
}
.resource-subtitle {
font-size: 11px;
color: ${props => props.theme.console.buttonColor};
color: ${(props) => props.theme.console.buttonColor};
}
.resource-trend {
@@ -112,7 +112,7 @@ const StyledWrapper = styled.div`
}
&.stable {
color: ${props => props.theme.console.buttonColor};
color: ${(props) => props.theme.console.buttonColor};
}
}
`;

View File

@@ -6,13 +6,13 @@ import {
IconDatabase,
IconClock,
IconServer,
IconChartLine,
IconChartLine
} from '@tabler/icons';
const Performance = () => {
const { systemResources } = useSelector(state => state.performance);
const { systemResources } = useSelector((state) => state.performance);
const formatBytes = bytes => {
const formatBytes = (bytes) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
@@ -20,7 +20,7 @@ const Performance = () => {
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const formatUptime = seconds => {
const formatUptime = (seconds) => {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);

View File

@@ -17,7 +17,7 @@ import NTLMAuth from 'components/RequestPane/Auth/NTLMAuth';
import WsseAuth from 'components/RequestPane/Auth/WsseAuth';
import ApiKeyAuth from 'components/RequestPane/Auth/ApiKeyAuth';
import AwsV4Auth from 'components/RequestPane/Auth/AwsV4Auth';
import { humanizeRequestAuthMode, getTreePathFromCollectionToItem } from 'utils/collections/index';
import { humanizeRequestAuthMode, getTreePathFromCollectionToItem } from 'utils/collections/index';
const GrantTypeComponentMap = ({ collection, folder }) => {
const dispatch = useDispatch();
@@ -48,8 +48,6 @@ const Auth = ({ collection, folder }) => {
let request = get(folder, 'root.request', {});
const authMode = get(folder, 'root.request.auth.mode');
const getEffectiveAuthSource = () => {
if (authMode !== 'inherit') return null;

View File

@@ -18,7 +18,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const addButtonRef = useRef(null);
const { globalEnvironments, activeGlobalEnvironmentUid } = useSelector(state => state.globalEnvironments);
const { globalEnvironments, activeGlobalEnvironmentUid } = useSelector((state) => state.globalEnvironments);
let _collection = cloneDeep(collection);

View File

@@ -74,7 +74,7 @@ const GlobalSearchModal = ({ isOpen, onClose }) => {
if (isItemARequest(item)) {
// add an optional check for the item name to prevent a crash if it doesnt exist.
const nameMatch = searchTerms.every(term => (item.name || '').toLowerCase().includes(term));
const nameMatch = searchTerms.every((term) => (item.name || '').toLowerCase().includes(term));
const urlMatch = searchTerms.every(term => (item.request?.url || '').toLowerCase().includes(term));
const pathMatch = enablePathMatch && searchTerms.every(term => itemPathLower.includes(term));

View File

@@ -251,7 +251,6 @@ function RequestTabMenu({ onDropdownCreate, collectionRequestTabs, tabIndex, col
} catch (err) {}
}
function handleRevertChanges(event) {
event.stopPropagation();
dropdownTippyRef.current.hide();
@@ -263,12 +262,10 @@ function RequestTabMenu({ onDropdownCreate, collectionRequestTabs, tabIndex, col
try {
const item = findItemInCollection(collection, currentTabUid);
if (item.draft) {
dispatch(
deleteRequestDraft({
itemUid: item.uid,
collectionUid: collection.uid
})
);
dispatch(deleteRequestDraft({
itemUid: item.uid,
collectionUid: collection.uid
}));
}
} catch (err) {}
}
@@ -340,7 +337,7 @@ function RequestTabMenu({ onDropdownCreate, collectionRequestTabs, tabIndex, col
>
Clone Request
</button>
<button
<button
className="dropdown-item w-full"
onClick={handleRevertChanges}
disabled={!currentTabItem?.draft}

View File

@@ -5,14 +5,21 @@ import Modal from 'components/Modal';
import jsyaml from 'js-yaml';
import { postmanToBruno, isPostmanCollection } from 'utils/importers/postman-collection';
import { convertInsomniaToBruno, isInsomniaCollection } from 'utils/importers/insomnia-collection';
import { isOpenApiSpec, convertOpenapiToBruno } from 'utils/importers/openapi-collection';
import { convertOpenapiToBruno, isOpenApiSpec } from 'utils/importers/openapi-collection';
import { isWSDLCollection } from 'utils/importers/wsdl-collection';
import { processBrunoCollection } from 'utils/importers/bruno-collection';
import { wsdlToBruno } from '@usebruno/converters';
import ImportSettings from 'components/Sidebar/ImportSettings';
import FullscreenLoader from './FullscreenLoader/index';
const convertFileToObject = async (file) => {
const text = await file.text();
// Handle WSDL files - return as plain text
if (file.name.endsWith('.wsdl') || file.type === 'text/xml' || file.type === 'application/xml') {
return text;
}
try {
if (file.type === 'application/json' || file.name.endsWith('.json')) {
return JSON.parse(text);
@@ -79,8 +86,9 @@ const ImportCollection = ({ onClose, handleSubmit }) => {
}
let collection;
if (isPostmanCollection(data)) {
if (isWSDLCollection(data)) {
collection = await wsdlToBruno(data);
} else if (isPostmanCollection(data)) {
collection = await postmanToBruno(data);
} else if (isInsomniaCollection(data)) {
collection = convertInsomniaToBruno(data);
@@ -120,7 +128,17 @@ const ImportCollection = ({ onClose, handleSubmit }) => {
return <FullscreenLoader isLoading={isLoading} />;
}
const acceptedFileTypes = ['.json', '.yaml', '.yml', 'application/json', 'application/yaml', 'application/x-yaml'];
const acceptedFileTypes = [
'.json',
'.yaml',
'.yml',
'.wsdl',
'application/json',
'application/yaml',
'application/x-yaml',
'text/xml',
'application/xml'
];
if (showImportSettings) {
return (
@@ -170,7 +188,7 @@ const ImportCollection = ({ onClose, handleSubmit }) => {
</button>
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Supports Bruno, Postman, Insomnia, and OpenAPI v3 formats
Supports Bruno, Postman, Insomnia, OpenAPI v3, and WSDL formats
</p>
</div>
</div>