mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-22 20:25:38 +00:00
chore: reformat
This commit is contained in:
@@ -237,12 +237,12 @@ export default class CodeEditor extends React.Component {
|
||||
this.editor.scrollTo(null, this.props.initialScroll);
|
||||
}
|
||||
|
||||
if (this.props.enableLineWrapping !== prevProps.enableLineWrapping){
|
||||
this.editor.setOption("lineWrapping", this.props.enableLineWrapping);
|
||||
if (this.props.enableLineWrapping !== prevProps.enableLineWrapping) {
|
||||
this.editor.setOption('lineWrapping', this.props.enableLineWrapping);
|
||||
}
|
||||
|
||||
if (this.props.mode !== prevProps.mode){
|
||||
this.editor.setOption("mode", this.props.mode);
|
||||
|
||||
if (this.props.mode !== prevProps.mode) {
|
||||
this.editor.setOption('mode', this.props.mode);
|
||||
}
|
||||
|
||||
this.ignoreChangeEvent = false;
|
||||
|
||||
@@ -18,7 +18,7 @@ const BETA_FEATURES = [
|
||||
{
|
||||
id: 'websocket',
|
||||
label: 'Web Socket Support',
|
||||
description: 'Enable Web Socket request support for making realtime calls to services'
|
||||
description: 'Enable Web Socket request support for making realtime calls to services',
|
||||
},
|
||||
{
|
||||
id: 'nodevm',
|
||||
|
||||
@@ -58,16 +58,18 @@ const ToggleSelector = ({
|
||||
/>
|
||||
</button>
|
||||
{(label || description)
|
||||
&& <div className="flex flex-col">
|
||||
<label className="text-xs font-medium text-gray-900 dark:text-gray-100">
|
||||
{label}
|
||||
</label>
|
||||
{description && (
|
||||
<p className="text-xs text-gray-700 dark:text-gray-400">
|
||||
{description}
|
||||
</p>
|
||||
&& (
|
||||
<div className="flex flex-col">
|
||||
<label className="text-xs font-medium text-gray-900 dark:text-gray-100">
|
||||
{label}
|
||||
</label>
|
||||
{description && (
|
||||
<p className="text-xs text-gray-700 dark:text-gray-400">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,12 +20,12 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important;
|
||||
color: ${props => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${props => props.theme.tabs.active.border} !important;
|
||||
}
|
||||
|
||||
.content-indicator {
|
||||
color: ${(props) => props.theme.text}
|
||||
color: ${props => props.theme.text}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
.inherit-mode-text {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${props => props.theme.colors.text.yellow};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -10,64 +10,64 @@ import StyledWrapper from '../../../Auth/AuthMode/StyledWrapper';
|
||||
const WSAuthMode = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const dropdownTippyRef = useRef();
|
||||
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||
const onDropdownCreate = ref => (dropdownTippyRef.current = ref);
|
||||
const authMode = item.draft ? get(item, 'draft.request.auth.mode') : get(item, 'request.auth.mode');
|
||||
|
||||
const authModes = [
|
||||
{
|
||||
name: 'Basic Auth',
|
||||
mode: 'basic'
|
||||
mode: 'basic',
|
||||
},
|
||||
{
|
||||
name: 'Bearer Token',
|
||||
mode: 'bearer'
|
||||
mode: 'bearer',
|
||||
},
|
||||
{
|
||||
name: 'API Key',
|
||||
mode: 'apikey'
|
||||
mode: 'apikey',
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
mode: 'oauth2'
|
||||
mode: 'oauth2',
|
||||
},
|
||||
{
|
||||
name: 'Inherit',
|
||||
mode: 'inherit'
|
||||
mode: 'inherit',
|
||||
},
|
||||
{
|
||||
name: 'No Auth',
|
||||
mode: 'none'
|
||||
}
|
||||
mode: 'none',
|
||||
},
|
||||
];
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-center auth-mode-label select-none">
|
||||
{humanizeRequestAuthMode(authMode)} <IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
{humanizeRequestAuthMode(authMode)}
|
||||
{' '}
|
||||
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const onModeChange = (value) => {
|
||||
dispatch(
|
||||
updateRequestAuthMode({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
mode: value
|
||||
})
|
||||
);
|
||||
const onModeChange = value => {
|
||||
dispatch(updateRequestAuthMode({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
mode: value,
|
||||
}));
|
||||
};
|
||||
|
||||
const onClickHandler = (mode) => {
|
||||
const onClickHandler = mode => {
|
||||
dropdownTippyRef?.current?.hide();
|
||||
onModeChange(mode);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="inline-flex items-center cursor-pointer auth-mode-selector">
|
||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||
{authModes.map((authMode) => (
|
||||
{authModes.map(authMode => (
|
||||
<div
|
||||
key={authMode.mode}
|
||||
className="dropdown-item"
|
||||
@@ -82,4 +82,4 @@ const WSAuthMode = ({ item, collection }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WSAuthMode;
|
||||
export default WSAuthMode;
|
||||
|
||||
@@ -19,7 +19,7 @@ const WSAuth = ({ item, collection }) => {
|
||||
const authMode = item.draft ? get(item, 'draft.request.auth.mode') : get(item, 'request.auth.mode');
|
||||
const requestTreePath = getTreePathFromCollectionToItem(collection, item);
|
||||
|
||||
const request = item.draft
|
||||
const request = item.draft
|
||||
? get(item, 'draft.request', {})
|
||||
: get(item, 'request', {});
|
||||
|
||||
@@ -30,13 +30,11 @@ const WSAuth = ({ item, collection }) => {
|
||||
// Reset to 'none' if current auth mode is not supported
|
||||
useEffect(() => {
|
||||
if (authMode && !supportedAuthModes.includes(authMode)) {
|
||||
dispatch(
|
||||
updateRequestAuthMode({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
mode: 'none'
|
||||
})
|
||||
);
|
||||
dispatch(updateRequestAuthMode({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
mode: 'none',
|
||||
}));
|
||||
}
|
||||
}, [authMode, collection.uid, dispatch, item.uid]);
|
||||
|
||||
@@ -47,7 +45,7 @@ const WSAuth = ({ item, collection }) => {
|
||||
let effectiveSource = {
|
||||
type: 'collection',
|
||||
name: 'Collection',
|
||||
auth: collectionAuth
|
||||
auth: collectionAuth,
|
||||
};
|
||||
|
||||
// Check folders in reverse to find the closest auth configuration
|
||||
@@ -58,7 +56,7 @@ const WSAuth = ({ item, collection }) => {
|
||||
effectiveSource = {
|
||||
type: 'folder',
|
||||
name: i.name,
|
||||
auth: folderAuth
|
||||
auth: folderAuth,
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -80,22 +78,34 @@ const WSAuth = ({ item, collection }) => {
|
||||
return <ApiKeyAuth collection={collection} item={item} updateAuth={updateAuth} request={request} save={save} />;
|
||||
}
|
||||
case 'oauth2': {
|
||||
return <>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div>OAuth 2 not <strong>yet</strong> supported by WebSockets. Using no auth instead.</div>
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div>
|
||||
OAuth 2 not
|
||||
<strong>yet</strong>
|
||||
{' '}
|
||||
supported by WebSockets. Using no auth instead.
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
// return <OAuth2 collection={collection} item={item} updateAuth={updateAuth} request={request} save={save} />;
|
||||
}
|
||||
case 'inherit': {
|
||||
const source = getEffectiveAuthSource();
|
||||
|
||||
|
||||
// Only show inherited auth if it's one of the supported types
|
||||
if (source && supportedAuthModes.includes(source.auth?.mode)) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div>Auth inherited from {source.name}: </div>
|
||||
<div>
|
||||
Auth inherited from
|
||||
{source.name}
|
||||
:
|
||||
{' '}
|
||||
</div>
|
||||
<div className="inherit-mode-text">{humanizeRequestAuthMode(source.auth?.mode)}</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -126,4 +136,4 @@ const WSAuth = ({ item, collection }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WSAuth;
|
||||
export default WSAuth;
|
||||
|
||||
@@ -15,19 +15,17 @@ import WSSettingsPane from '../WSSettingsPane/index';
|
||||
|
||||
const WSRequestPane = ({ item, collection, handleRun }) => {
|
||||
const dispatch = useDispatch();
|
||||
const tabs = useSelector((state) => state.tabs.tabs);
|
||||
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
||||
const tabs = useSelector(state => state.tabs.tabs);
|
||||
const activeTabUid = useSelector(state => state.tabs.activeTabUid);
|
||||
|
||||
const selectTab = (tab) => {
|
||||
dispatch(
|
||||
updateRequestPaneTab({
|
||||
uid: item.uid,
|
||||
requestPaneTab: tab
|
||||
})
|
||||
);
|
||||
const selectTab = tab => {
|
||||
dispatch(updateRequestPaneTab({
|
||||
uid: item.uid,
|
||||
requestPaneTab: tab,
|
||||
}));
|
||||
};
|
||||
|
||||
const getTabPanel = (tab) => {
|
||||
const getTabPanel = tab => {
|
||||
switch (tab) {
|
||||
case 'body': {
|
||||
return (
|
||||
@@ -62,14 +60,14 @@ const WSRequestPane = ({ item, collection, handleRun }) => {
|
||||
return <div>Something went wrong</div>;
|
||||
}
|
||||
|
||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||
const focusedTab = find(tabs, t => t.uid === activeTabUid);
|
||||
if (!focusedTab || !focusedTab.uid || !focusedTab.requestPaneTab) {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
|
||||
const getTabClassname = (tabName) => {
|
||||
const getTabClassname = tabName => {
|
||||
return classnames(`tab select-none ${tabName}`, {
|
||||
active: tabName === focusedTab.requestPaneTab
|
||||
active: tabName === focusedTab.requestPaneTab,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -78,7 +76,7 @@ const WSRequestPane = ({ item, collection, handleRun }) => {
|
||||
const docs = getPropertyFromDraftOrRequest(item, 'request.docs');
|
||||
const auth = getPropertyFromDraftOrRequest(item, 'request.auth');
|
||||
|
||||
const activeHeadersLength = headers.filter((header) => header.enabled).length;
|
||||
const activeHeadersLength = headers.filter(header => header.enabled).length;
|
||||
|
||||
useEffect(() => {
|
||||
if (!focusedTab?.requestPaneTab) {
|
||||
@@ -110,7 +108,7 @@ const WSRequestPane = ({ item, collection, handleRun }) => {
|
||||
</div>
|
||||
<section
|
||||
className={classnames('flex w-full flex-1 h-full', {
|
||||
'mt-2': !isMultipleContentTab
|
||||
'mt-2': !isMultipleContentTab,
|
||||
})}
|
||||
>
|
||||
<HeightBoundContainer>{getTabPanel(focusedTab.requestPaneTab)}</HeightBoundContainer>
|
||||
|
||||
@@ -4,8 +4,8 @@ const StyledWrapper = styled.div`
|
||||
.single-line-editor-wrapper {
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
border: solid 1px ${(props) => props.theme.input.border};
|
||||
background-color: ${(props) => props.theme.input.bg};
|
||||
border: solid 1px ${props => props.theme.input.border};
|
||||
background-color: ${props => props.theme.input.bg};
|
||||
}
|
||||
|
||||
.tooltip-mod {
|
||||
|
||||
@@ -23,30 +23,26 @@ const getPropertyFromDraftOrRequest = (propertyKey, item) =>
|
||||
const WSSettingsPane = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { storedTheme } = useTheme();
|
||||
const requestPreferences = useSelector((state) => state.app.preferences.request);
|
||||
const requestPreferences = useSelector(state => state.app.preferences.request);
|
||||
|
||||
const { _connectionTimeout, keepAliveInterval = 0 } = getPropertyFromDraftOrRequest('settings', item);
|
||||
|
||||
const connectionTimeout = _connectionTimeout ?? requestPreferences.timeout
|
||||
const connectionTimeout = _connectionTimeout ?? requestPreferences.timeout;
|
||||
|
||||
const onChangeConnectionTimeout = (val) => {
|
||||
dispatch(
|
||||
updateItemSettings({
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item.uid,
|
||||
settings: { connectionTimeout: val }
|
||||
})
|
||||
);
|
||||
const onChangeConnectionTimeout = val => {
|
||||
dispatch(updateItemSettings({
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item.uid,
|
||||
settings: { connectionTimeout: val },
|
||||
}));
|
||||
};
|
||||
|
||||
const onChangeKeepAliveInterval = (val) => {
|
||||
dispatch(
|
||||
updateItemSettings({
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item.uid,
|
||||
settings: { keepAliveInterval: val }
|
||||
})
|
||||
);
|
||||
const onChangeKeepAliveInterval = val => {
|
||||
dispatch(updateItemSettings({
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item.uid,
|
||||
settings: { keepAliveInterval: val },
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -57,13 +53,13 @@ const WSSettingsPane = ({ item, collection }) => {
|
||||
<InfoTip
|
||||
infotipId="setting-connection-timeout"
|
||||
className="tooltip-mod max-w-lg"
|
||||
content={
|
||||
content={(
|
||||
<div>
|
||||
<p>
|
||||
<span>Timeout in milliseconds</span>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -71,7 +67,7 @@ const WSSettingsPane = ({ item, collection }) => {
|
||||
<SingleLineEditor
|
||||
value={connectionTimeout}
|
||||
theme={storedTheme}
|
||||
onChange={(newValue) => onChangeConnectionTimeout(newValue)}
|
||||
onChange={newValue => onChangeConnectionTimeout(newValue)}
|
||||
collection={collection}
|
||||
/>
|
||||
</div>
|
||||
@@ -82,7 +78,7 @@ const WSSettingsPane = ({ item, collection }) => {
|
||||
<InfoTip
|
||||
infotipId="setting-keep-alive"
|
||||
className="tooltip-mod max-w-lg"
|
||||
content={
|
||||
content={(
|
||||
<div>
|
||||
<p>
|
||||
<span>
|
||||
@@ -91,7 +87,7 @@ const WSSettingsPane = ({ item, collection }) => {
|
||||
</p>
|
||||
<p className="mt-2">0 (zero) = off</p>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -99,7 +95,7 @@ const WSSettingsPane = ({ item, collection }) => {
|
||||
<SingleLineEditor
|
||||
value={keepAliveInterval}
|
||||
theme={storedTheme}
|
||||
onChange={(newValue) => onChangeKeepAliveInterval(newValue)}
|
||||
onChange={newValue => onChangeKeepAliveInterval(newValue)}
|
||||
collection={collection}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.selected-body-mode {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${props => props.theme.colors.text.yellow};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,19 +4,19 @@ import Dropdown from 'components/Dropdown';
|
||||
import { humanizeRequestBodyMode } from 'utils/collections';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
|
||||
const WSRequestBodyMode = ({ mode, onModeChange }) => {
|
||||
const dropdownTippyRef = useRef();
|
||||
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||
|
||||
const onDropdownCreate = ref => (dropdownTippyRef.current = ref);
|
||||
|
||||
const Icon = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-center pl-3 py-1 select-none selected-body-mode">
|
||||
{humanizeRequestBodyMode(mode)} <IconCaretDown className="caret ml-2" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-center pl-3 py-1 select-none selected-body-mode">
|
||||
{humanizeRequestBodyMode(mode)}
|
||||
{' '}
|
||||
<IconCaretDown className="caret ml-2" size={14} strokeWidth={2} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
|
||||
@@ -10,7 +10,7 @@ const Wrapper = styled.div`
|
||||
|
||||
.ws-message-header {
|
||||
.font-medium {
|
||||
color: ${(props) => props.theme.text};
|
||||
color: ${props => props.theme.text};
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -40,9 +40,9 @@ const Wrapper = styled.div`
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding-top: 8px;
|
||||
background: ${(props) => props.theme.bg || '#fff'};
|
||||
background: ${props => props.theme.bg || '#fff'};
|
||||
z-index: 15;
|
||||
border-top: 1px solid ${(props) => props.theme.border || 'rgba(0, 0, 0, 0.1)'};
|
||||
border-top: 1px solid ${props => props.theme.border || 'rgba(0, 0, 0, 0.1)'};
|
||||
|
||||
.add-message-btn {
|
||||
width: 100%;
|
||||
@@ -56,4 +56,4 @@ const Wrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
export default Wrapper;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { autoDetectLang } from 'utils/codemirror/lang-detect';
|
||||
const TYPE_BY_DECODER = {
|
||||
base64: 'binary',
|
||||
json: 'json',
|
||||
xml: 'xml'
|
||||
xml: 'xml',
|
||||
};
|
||||
|
||||
const DECODER_BY_TYPE = invert(TYPE_BY_DECODER);
|
||||
@@ -31,11 +31,11 @@ const SingleWSMessage = ({
|
||||
isCollapsed,
|
||||
onToggleCollapse,
|
||||
handleRun,
|
||||
canClientSendMultipleMessages
|
||||
canClientSendMultipleMessages,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const { displayedTheme } = useTheme();
|
||||
const preferences = useSelector((state) => state.app.preferences);
|
||||
const preferences = useSelector(state => state.app.preferences);
|
||||
const body = item.draft ? get(item, 'draft.request.body') : get(item, 'request.body');
|
||||
|
||||
const { name, content, decoder } = message;
|
||||
@@ -51,31 +51,27 @@ const SingleWSMessage = ({
|
||||
type: DECODER_BY_TYPE[type],
|
||||
};
|
||||
|
||||
dispatch(
|
||||
updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
dispatch(updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
const onEdit = (value) => {
|
||||
const onEdit = value => {
|
||||
const currentMessages = [...(body.ws || [])];
|
||||
|
||||
currentMessages[index] = {
|
||||
name: name ? name : `message ${index + 1}`,
|
||||
type: DECODER_BY_TYPE[messageFormat],
|
||||
content: value
|
||||
content: value,
|
||||
};
|
||||
|
||||
dispatch(
|
||||
updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
dispatch(updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
||||
@@ -85,17 +81,15 @@ const SingleWSMessage = ({
|
||||
|
||||
currentMessages.splice(index, 1);
|
||||
|
||||
dispatch(
|
||||
updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
dispatch(updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
const getContainerHeight =
|
||||
canClientSendMultipleMessages && body.ws.length > 1 ? `${isCollapsed ? '' : 'h-80'}` : 'h-full';
|
||||
const getContainerHeight
|
||||
= canClientSendMultipleMessages && body.ws.length > 1 ? `${isCollapsed ? '' : 'h-80'}` : 'h-full';
|
||||
|
||||
let codeType = messageFormat;
|
||||
if (TYPE_BY_DECODER[decoder]) {
|
||||
@@ -105,7 +99,7 @@ const SingleWSMessage = ({
|
||||
const codemirrorMode = {
|
||||
text: 'application/text',
|
||||
xml: 'application/xml',
|
||||
json: 'application/ld+json'
|
||||
json: 'application/ld+json',
|
||||
};
|
||||
|
||||
const onPrettify = () => {
|
||||
@@ -165,7 +159,7 @@ const SingleWSMessage = ({
|
||||
<IconChevronUp size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-center gap-2" onClick={e => e.stopPropagation()}>
|
||||
<WSRequestBodyMode mode={messageFormat} onModeChange={onUpdateMessageType} />
|
||||
<ToolHint text="Prettify" toolhintId={`prettify-msg-${index}`}>
|
||||
<button
|
||||
@@ -209,7 +203,7 @@ const SingleWSMessage = ({
|
||||
};
|
||||
|
||||
const WSBody = ({ item, collection, handleRun }) => {
|
||||
const preferences = useSelector((state) => state.app.preferences);
|
||||
const preferences = useSelector(state => state.app.preferences);
|
||||
const isVerticalLayout = preferences?.layout?.responsePaneOrientation === 'vertical';
|
||||
const dispatch = useDispatch();
|
||||
const [collapsedMessages, setCollapsedMessages] = useState([]);
|
||||
@@ -227,10 +221,10 @@ const WSBody = ({ item, collection, handleRun }) => {
|
||||
}
|
||||
}, [body?.ws?.length]);
|
||||
|
||||
const toggleMessageCollapse = (index) => {
|
||||
setCollapsedMessages((prev) => {
|
||||
const toggleMessageCollapse = index => {
|
||||
setCollapsedMessages(prev => {
|
||||
if (prev.includes(index)) {
|
||||
return prev.filter((i) => i !== index);
|
||||
return prev.filter(i => i !== index);
|
||||
} else {
|
||||
return [...prev, index];
|
||||
}
|
||||
@@ -242,16 +236,14 @@ const WSBody = ({ item, collection, handleRun }) => {
|
||||
|
||||
currentMessages.push({
|
||||
name: `message ${currentMessages.length + 1}`,
|
||||
content: '{}'
|
||||
content: '{}',
|
||||
});
|
||||
|
||||
dispatch(
|
||||
updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
dispatch(updateRequestBody({
|
||||
content: currentMessages,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
if (!body?.ws || !Array.isArray(body.ws)) {
|
||||
|
||||
@@ -4,12 +4,12 @@ const StyledWrapper = styled.div`
|
||||
height: 2.3rem;
|
||||
|
||||
.input-container {
|
||||
background-color: ${(props) => props.theme.requestTabPanel.url.bg};
|
||||
background-color: ${props => props.theme.requestTabPanel.url.bg};
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
|
||||
input {
|
||||
background-color: ${(props) => props.theme.requestTabPanel.url.bg};
|
||||
background-color: ${props => props.theme.requestTabPanel.url.bg};
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
|
||||
@@ -21,12 +21,12 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.method-ws {
|
||||
color: ${(props) => props.theme.request.ws};
|
||||
color: ${props => props.theme.request.ws};
|
||||
}
|
||||
|
||||
.connection-status-strip {
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
background-color: ${(props) => props.theme.colors.text.green};
|
||||
background-color: ${props => props.theme.colors.text.green};
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@@ -60,8 +60,8 @@ const StyledWrapper = styled.div`
|
||||
.infotip-text {
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
background-color: ${(props) => props.theme.requestTabs.active.bg};
|
||||
color: ${(props) => props.theme.text};
|
||||
background-color: ${props => props.theme.requestTabs.active.bg};
|
||||
color: ${props => props.theme.text};
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
@@ -83,7 +83,7 @@ const StyledWrapper = styled.div`
|
||||
margin-left: -4px;
|
||||
border-width: 4px;
|
||||
border-style: solid;
|
||||
border-color: ${(props) => props.theme.requestTabs.active.bg} transparent transparent transparent;
|
||||
border-color: ${props => props.theme.requestTabs.active.bg} transparent transparent transparent;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
@@ -93,7 +93,7 @@ const StyledWrapper = styled.div`
|
||||
.connection-controls {
|
||||
.infotip {
|
||||
&:hover {
|
||||
background-color: ${(props) => props.theme.requestTabPanel.url.errorHoverBg};
|
||||
background-color: ${props => props.theme.requestTabPanel.url.errorHoverBg};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IconArrowRight, IconDeviceFloppy, IconPlugConnected, IconPlugConnectedX } from '@tabler/icons';
|
||||
import { IconWebSocket } from 'components/Icons/Grpc';
|
||||
import classnames from "classnames"
|
||||
import classnames from 'classnames';
|
||||
import SingleLineEditor from 'components/SingleLineEditor/index';
|
||||
import { requestUrlChanged } from 'providers/ReduxStore/slices/collections';
|
||||
import { wsConnectOnly, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
@@ -38,33 +38,31 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
return () => clearInterval(interval);
|
||||
}, [item.uid]);
|
||||
|
||||
const onUrlChange = (value) => {
|
||||
closeWsConnection(item.uid)
|
||||
dispatch(
|
||||
requestUrlChanged({
|
||||
url: value,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
const onUrlChange = value => {
|
||||
closeWsConnection(item.uid);
|
||||
dispatch(requestUrlChanged({
|
||||
url: value,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleCloseConnection = (e) => {
|
||||
const handleCloseConnection = e => {
|
||||
e.stopPropagation();
|
||||
|
||||
closeWsConnection(item.uid)
|
||||
.then(() => {
|
||||
toast.success('WebSocket connection closed');
|
||||
setIsConnectionActive(false);
|
||||
setIsConnecting(false)
|
||||
setIsConnecting(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
console.error('Failed to close WebSocket connection:', err);
|
||||
toast.error('Failed to close WebSocket connection');
|
||||
});
|
||||
};
|
||||
|
||||
const handleRunClick = async (e) => {
|
||||
const handleRunClick = async e => {
|
||||
e.stopPropagation();
|
||||
if (!url) {
|
||||
toast.error('Please enter a valid WebSocket URL');
|
||||
@@ -73,12 +71,12 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
handleRun(e);
|
||||
};
|
||||
|
||||
const handleConnect = (e) => {
|
||||
setIsConnecting(true)
|
||||
dispatch(wsConnectOnly(item, collection.uid));
|
||||
const handleConnect = e => {
|
||||
setIsConnecting(true);
|
||||
dispatch(wsConnectOnly(item, collection.uid));
|
||||
};
|
||||
|
||||
const onSave = (finalValue) => {
|
||||
const onSave = finalValue => {
|
||||
dispatch(saveRequest(item.uid, collection.uid));
|
||||
};
|
||||
|
||||
@@ -91,7 +89,7 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
</div>
|
||||
<SingleLineEditor
|
||||
value={url}
|
||||
onSave={(finalValue) => onSave(finalValue)}
|
||||
onSave={finalValue => onSave(finalValue)}
|
||||
onChange={onUrlChange}
|
||||
placeholder="ws://localhost:8080 or wss://example.com"
|
||||
className="w-full"
|
||||
@@ -101,7 +99,7 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
<div className="flex items-center h-full mr-2 cursor-pointer">
|
||||
<div
|
||||
className="infotip mr-3"
|
||||
onClick={(e) => {
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
if (!item.draft) return;
|
||||
onSave();
|
||||
@@ -114,7 +112,13 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
className={`${item.draft ? 'cursor-pointer' : 'cursor-default'}`}
|
||||
/>
|
||||
<span className="infotip-text text-xs">
|
||||
Save <span className="shortcut">({saveShortcut})</span>
|
||||
Save
|
||||
{' '}
|
||||
<span className="shortcut">
|
||||
(
|
||||
{saveShortcut}
|
||||
)
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -137,8 +141,8 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
|
||||
<div className="infotip" onClick={handleConnect}>
|
||||
<IconPlugConnected
|
||||
className={
|
||||
classnames("cursor-pointer",{
|
||||
"animate-pulse": isConnecting
|
||||
classnames('cursor-pointer', {
|
||||
'animate-pulse': isConnecting,
|
||||
})
|
||||
}
|
||||
color={theme.colors.text.green}
|
||||
|
||||
@@ -258,7 +258,6 @@ const RequestTabPanel = () => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// TODO: reaper, improve selection of panes
|
||||
return (
|
||||
<StyledWrapper
|
||||
@@ -268,11 +267,11 @@ const RequestTabPanel = () => {
|
||||
>
|
||||
<div className="pt-4 pb-3 px-4">
|
||||
{
|
||||
isGrpcRequest
|
||||
?<GrpcQueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
: isWsRequest
|
||||
? <WsQueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
: <QueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
isGrpcRequest
|
||||
? <GrpcQueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
: isWsRequest
|
||||
? <WsQueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
: <QueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||
}
|
||||
</div>
|
||||
<section ref={mainSectionRef} className={`main flex ${isVerticalLayout ? 'flex-col' : ''} flex-grow pb-4 relative overflow-auto`}>
|
||||
@@ -282,11 +281,10 @@ const RequestTabPanel = () => {
|
||||
style={isVerticalLayout ? {
|
||||
height: `${Math.max(topPaneHeight, MIN_TOP_PANE_HEIGHT)}px`,
|
||||
minHeight: `${MIN_TOP_PANE_HEIGHT}px`,
|
||||
width: '100%'
|
||||
|
||||
width: '100%',
|
||||
|
||||
} : {
|
||||
width: `${Math.max(leftPaneWidth, MIN_LEFT_PANE_WIDTH)}px`
|
||||
width: `${Math.max(leftPaneWidth, MIN_LEFT_PANE_WIDTH)}px`,
|
||||
}}
|
||||
>
|
||||
{item.type === 'graphql-request' ? (
|
||||
@@ -299,14 +297,14 @@ const RequestTabPanel = () => {
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.type === 'http-request' ? (
|
||||
{item.type === 'http-request' ? (
|
||||
<HttpRequestPane item={item} collection={collection} />
|
||||
) : null}
|
||||
|
||||
{isGrpcRequest ? (
|
||||
<GrpcRequestPane item={item} collection={collection} handleRun={handleRun} />
|
||||
) : null}
|
||||
|
||||
|
||||
{isWsRequest ? (
|
||||
<WSRequestPane item={item} collection={collection} handleRun={handleRun} />
|
||||
) : null}
|
||||
@@ -325,10 +323,11 @@ const RequestTabPanel = () => {
|
||||
response={item.response}
|
||||
/>
|
||||
) : item.type === 'ws-request' ? (
|
||||
<WSResponsePane
|
||||
item={item}
|
||||
collection={collection}
|
||||
response={item.response} />
|
||||
<WSResponsePane
|
||||
item={item}
|
||||
collection={collection}
|
||||
response={item.response}
|
||||
/>
|
||||
) : (
|
||||
<ResponsePane
|
||||
item={item}
|
||||
|
||||
@@ -69,14 +69,11 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
const getMethodColor = (method = '') => {
|
||||
const colorMap = {
|
||||
...theme.request.methods,
|
||||
...theme.request
|
||||
}
|
||||
...theme.request,
|
||||
};
|
||||
return colorMap[method.toLocaleLowerCase()];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const folder = folderUid ? findItemInCollection(collection, folderUid) : null;
|
||||
if (['collection-settings', 'collection-overview', 'folder-settings', 'variables', 'collection-runner', 'security-settings'].includes(tab.type)) {
|
||||
return (
|
||||
@@ -97,18 +94,18 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
|
||||
const item = findItemInCollection(collection, tab.uid);
|
||||
|
||||
const getMethodText = useCallback((item)=>{
|
||||
if(!item) return
|
||||
const getMethodText = useCallback(item => {
|
||||
if (!item) return;
|
||||
const isGrpc = item.type === 'grpc-request';
|
||||
const isWS = item.type === 'ws-request';
|
||||
if(!isWS && !isGrpc){
|
||||
if (!isWS && !isGrpc) {
|
||||
return item.draft ? get(item, 'draft.request.method') : get(item, 'request.method');
|
||||
}
|
||||
if(isGrpc){
|
||||
return "gRPC"
|
||||
if (isGrpc) {
|
||||
return 'gRPC';
|
||||
}
|
||||
return "WS";
|
||||
},[item])
|
||||
return 'WS';
|
||||
}, [item]);
|
||||
|
||||
if (!item) {
|
||||
return (
|
||||
@@ -129,8 +126,8 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
}
|
||||
|
||||
const isWS = item.type === 'ws-request';
|
||||
const method = getMethodText(item)
|
||||
|
||||
const method = getMethodText(item);
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex items-center justify-between tab-container px-1">
|
||||
{showConfirmClose && (
|
||||
@@ -138,7 +135,7 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
item={item}
|
||||
onCancel={() => setShowConfirmClose(false)}
|
||||
onCloseWithoutSave={() => {
|
||||
isWS && closeWsConnection(item.uid)
|
||||
isWS && closeWsConnection(item.uid);
|
||||
dispatch(
|
||||
deleteRequestDraft({
|
||||
itemUid: item.uid,
|
||||
@@ -182,7 +179,7 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span className="tab-method uppercase" style={{ color:getMethodColor(method), fontSize: 12 }}>
|
||||
<span className="tab-method uppercase" style={{ color: getMethodColor(method), fontSize: 12 }}>
|
||||
{method}
|
||||
</span>
|
||||
<span className="ml-1 tab-name" title={item.name}>
|
||||
@@ -202,8 +199,8 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
className="flex px-2 close-icon-container"
|
||||
onClick={(e) => {
|
||||
if (!item.draft) {
|
||||
isWS && closeWsConnection(item.uid)
|
||||
return handleCloseClick(e)
|
||||
isWS && closeWsConnection(item.uid);
|
||||
return handleCloseClick(e);
|
||||
};
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -3,7 +3,7 @@ import styled from 'styled-components';
|
||||
const StyledWrapper = styled.div`
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: ${(props) => props.theme.bg};
|
||||
background: ${props => props.theme.bg};
|
||||
border-radius: 4px;
|
||||
|
||||
div.tabs {
|
||||
@@ -25,8 +25,8 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important;
|
||||
color: ${props => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${props => props.theme.tabs.active.border} !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,15 +36,15 @@ const StyledWrapper = styled.div`
|
||||
align-items: center;
|
||||
|
||||
&.complete {
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
color: ${props => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
&.cancelled {
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
color: ${props => props.theme.colors.text.danger};
|
||||
}
|
||||
|
||||
&.streaming {
|
||||
color: ${(props) => props.theme.colors.text.blue};
|
||||
color: ${props => props.theme.colors.text.blue};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ const StyledWrapper = styled.div`
|
||||
overflow-y: auto;
|
||||
|
||||
.ws-message.new {
|
||||
background-color: ${({theme}) => theme.table.striped};
|
||||
background-color: ${({ theme }) => theme.table.striped};
|
||||
}
|
||||
|
||||
.ws-message:not(:last-child) {
|
||||
border-bottom: 1px solid ${({theme}) => theme.table.border};
|
||||
border-bottom: 1px solid ${({ theme }) => theme.table.border};
|
||||
}
|
||||
|
||||
.ws-message:not(:last-child).open {
|
||||
@@ -16,13 +16,13 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.ws-incoming {
|
||||
background: ${(props) => props.theme.bg};
|
||||
border-color: ${(props) => props.theme.table.border};
|
||||
background: ${props => props.theme.bg};
|
||||
border-color: ${props => props.theme.table.border};
|
||||
}
|
||||
|
||||
.ws-outgoing {
|
||||
background: ${(props) => props.theme.bg};
|
||||
border-color: ${(props) => props.theme.table.border};
|
||||
background: ${props => props.theme.bg};
|
||||
border-color: ${props => props.theme.table.border};
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
@@ -30,12 +30,12 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.CodeMirror-foldgutter, .CodeMirror-linenumbers, .CodeMirror-lint-markers {
|
||||
background: ${({theme})=> theme.bg};
|
||||
background: ${({ theme }) => theme.bg};
|
||||
}
|
||||
|
||||
div[role='tablist'] {
|
||||
.active {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${props => props.theme.colors.text.yellow};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,38 +10,38 @@ import _ from 'lodash';
|
||||
import { useRef } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const getContentMeta = (content) => {
|
||||
const getContentMeta = content => {
|
||||
if (typeof content === 'object') {
|
||||
return {
|
||||
isJSON: true,
|
||||
content: JSON.stringify(content, null, 0)
|
||||
content: JSON.stringify(content, null, 0),
|
||||
};
|
||||
}
|
||||
try {
|
||||
return {
|
||||
isJSON: true,
|
||||
content: JSON.stringify(JSON.parse(content), null, 0)
|
||||
content: JSON.stringify(JSON.parse(content), null, 0),
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
isJSON: false,
|
||||
content: content
|
||||
content: content,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const parseContent = (content) => {
|
||||
const parseContent = content => {
|
||||
let contentMeta = getContentMeta(content);
|
||||
return {
|
||||
type: contentMeta.isJSON ? 'application/json' : 'text/plain',
|
||||
content: contentMeta.isJSON ? JSON.stringify(JSON.parse(contentMeta.content), null, 2) : contentMeta.content
|
||||
content: contentMeta.isJSON ? JSON.stringify(JSON.parse(contentMeta.content), null, 2) : contentMeta.content,
|
||||
};
|
||||
};
|
||||
|
||||
const getDataTypeText = (type) => {
|
||||
const getDataTypeText = type => {
|
||||
const textMap = {
|
||||
'text/plain': 'RAW',
|
||||
'application/json': 'JSON'
|
||||
'application/json': 'JSON',
|
||||
};
|
||||
return textMap[type] ?? 'RAW';
|
||||
};
|
||||
@@ -52,20 +52,20 @@ const getDataTypeText = (type) => {
|
||||
*/
|
||||
const TypeIcon = ({ type }) => {
|
||||
const commonProps = {
|
||||
size: 18
|
||||
size: 18,
|
||||
};
|
||||
return {
|
||||
incoming: <IconArrowDownLeft {...commonProps} />,
|
||||
outgoing: <IconArrowUpRight {...commonProps} />,
|
||||
info: <IconInfoCircle {...commonProps} />,
|
||||
error: <IconExclamationCircle {...commonProps} />
|
||||
error: <IconExclamationCircle {...commonProps} />,
|
||||
}[type];
|
||||
};
|
||||
|
||||
const WSMessageItem = ({ message, inFocus }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [showHex, setShowHex] = useState(false);
|
||||
const preferences = useSelector((state) => state.app.preferences);
|
||||
const preferences = useSelector(state => state.app.preferences);
|
||||
const { displayedTheme } = useTheme();
|
||||
const [isNew, setIsNew] = useState(false);
|
||||
const notified = useRef(false);
|
||||
@@ -90,43 +90,41 @@ const WSMessageItem = ({ message, inFocus }) => {
|
||||
}
|
||||
}, [message]);
|
||||
|
||||
const canOpenMessage = !isInfo && !isError
|
||||
const canOpenMessage = !isInfo && !isError;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={(node) => {
|
||||
ref={node => {
|
||||
if (!node) return;
|
||||
if (inFocus) node.scrollIntoView();
|
||||
}}
|
||||
className={classnames('ws-message flex flex-col p-2', {
|
||||
'ws-incoming': isIncoming,
|
||||
'ws-outgoing': !isIncoming,
|
||||
open: isOpen,
|
||||
new: isNew
|
||||
'open': isOpen,
|
||||
'new': isNew,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classnames('flex items-center justify-between', {
|
||||
'cursor-pointer': !isInfo,
|
||||
'cursor-not-allowed': isInfo
|
||||
'cursor-not-allowed': isInfo,
|
||||
})}
|
||||
onClick={(e) => {
|
||||
onClick={e => {
|
||||
if (!canOpenMessage) return;
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
>
|
||||
<div className="flex min-w-0 shrink">
|
||||
<span
|
||||
className={classnames(
|
||||
'font-semibold flex items-center gap-1',
|
||||
className={classnames('font-semibold flex items-center gap-1',
|
||||
{
|
||||
'text-green-700': isIncoming,
|
||||
'text-yellow-700': isOutgoing,
|
||||
'text-blue-700': isInfo,
|
||||
'text-red-700': isError,
|
||||
'text-red-700': isError,
|
||||
}
|
||||
)}
|
||||
})}
|
||||
>
|
||||
<TypeIcon type={message.type} />
|
||||
</span>
|
||||
@@ -136,16 +134,16 @@ const WSMessageItem = ({ message, inFocus }) => {
|
||||
{message.timestamp && (
|
||||
<span className="text-xs text-gray-400">{new Date(message.timestamp).toISOString()}</span>
|
||||
)}
|
||||
{canOpenMessage
|
||||
{canOpenMessage
|
||||
? (
|
||||
<span className="text-gray-600">
|
||||
{isOpen ? (
|
||||
<IconChevronDown size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
|
||||
) : (
|
||||
<IconChevronRight size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
<span className="text-gray-600">
|
||||
{isOpen ? (
|
||||
<IconChevronDown size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
|
||||
) : (
|
||||
<IconChevronRight size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
: <span class="w-4"></span>}
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,8 +152,8 @@ const WSMessageItem = ({ message, inFocus }) => {
|
||||
<div className="mt-2 flex justify-end gap-2 text-xs ws-message-toolbar" role="tablist">
|
||||
<div
|
||||
className={classnames('select-none capitalize', {
|
||||
active: showHex,
|
||||
'cursor-pointer': !showHex
|
||||
'active': showHex,
|
||||
'cursor-pointer': !showHex,
|
||||
})}
|
||||
role="tab"
|
||||
onClick={() => setShowHex(true)}
|
||||
@@ -164,8 +162,8 @@ const WSMessageItem = ({ message, inFocus }) => {
|
||||
</div>
|
||||
<div
|
||||
className={classnames('select-none capitalize', {
|
||||
active: !showHex,
|
||||
'cursor-pointer': showHex
|
||||
'active': !showHex,
|
||||
'cursor-pointer': showHex,
|
||||
})}
|
||||
role="tab"
|
||||
onClick={() => setShowHex(false)}
|
||||
|
||||
@@ -3,33 +3,33 @@ import styled from 'styled-components';
|
||||
const StyledWrapper = styled.div`
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: ${(props) => props.theme.bg};
|
||||
background: ${props => props.theme.bg};
|
||||
border-radius: 4px;
|
||||
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
font-family: ${(props) => (props.font === 'default' ? 'monospace' : props.font)};
|
||||
font-size: ${(props) => (props.fontSize ? props.fontSize : '13px')};
|
||||
font-family: ${props => (props.font === 'default' ? 'monospace' : props.font)};
|
||||
font-size: ${props => (props.fontSize ? props.fontSize : '13px')};
|
||||
}
|
||||
|
||||
.accordion-header {
|
||||
background-color: ${(props) => props.theme.requestTabPanel.card.bg};
|
||||
background-color: ${props => props.theme.requestTabPanel.card.bg};
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props) => props.theme.plainGrid.hoverBg};
|
||||
background-color: ${props => props.theme.plainGrid.hoverBg};
|
||||
}
|
||||
|
||||
&.open {
|
||||
background-color: ${(props) => props.theme.plainGrid.hoverBg};
|
||||
background-color: ${props => props.theme.plainGrid.hoverBg};
|
||||
}
|
||||
}
|
||||
|
||||
.error-header {
|
||||
background-color: ${(props) => (props.theme.bg === '#1e1e1e' ? 'rgba(185, 28, 28, 0.1)' : '#fee2e2')};
|
||||
background-color: ${props => (props.theme.bg === '#1e1e1e' ? 'rgba(185, 28, 28, 0.1)' : '#fee2e2')};
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
color: ${props => props.theme.colors.text.danger};
|
||||
}
|
||||
|
||||
div.tabs {
|
||||
@@ -51,8 +51,8 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important;
|
||||
color: ${props => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${props => props.theme.tabs.active.border} !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,15 +62,15 @@ const StyledWrapper = styled.div`
|
||||
align-items: center;
|
||||
|
||||
&.complete {
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
color: ${props => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
&.cancelled {
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
color: ${props => props.theme.colors.text.danger};
|
||||
}
|
||||
|
||||
&.streaming {
|
||||
color: ${(props) => props.theme.colors.text.blue};
|
||||
color: ${props => props.theme.colors.text.blue};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import WSError from '../WSError';
|
||||
|
||||
const WSQueryResult = ({ item, collection }) => {
|
||||
const { displayedTheme } = useTheme();
|
||||
const preferences = useSelector((state) => state.app.preferences);
|
||||
const preferences = useSelector(state => state.app.preferences);
|
||||
const [showErrorMessage, setShowErrorMessage] = useState(true);
|
||||
|
||||
const response = item.response || {};
|
||||
@@ -29,7 +29,7 @@ const WSQueryResult = ({ item, collection }) => {
|
||||
}, [response, hasError]);
|
||||
|
||||
// Format a timestamp to a human-readable format
|
||||
const formatTimestamp = (timestamp) => {
|
||||
const formatTimestamp = timestamp => {
|
||||
if (!timestamp) return 'Unknown time';
|
||||
|
||||
try {
|
||||
@@ -41,7 +41,7 @@ const WSQueryResult = ({ item, collection }) => {
|
||||
};
|
||||
|
||||
// Format JSON for display
|
||||
const formatJSON = (data) => {
|
||||
const formatJSON = data => {
|
||||
try {
|
||||
if (typeof data === 'string') {
|
||||
return JSON.stringify(JSON.parse(data), null, 2);
|
||||
@@ -90,7 +90,11 @@ const WSQueryResult = ({ item, collection }) => {
|
||||
<Accordion.Header index={index} style={{ padding: '8px 12px', minHeight: '40px' }}>
|
||||
<div className="flex justify-between w-full">
|
||||
<div className="font-medium">
|
||||
Response {originalIndex + 1} {index === 0 ? '(Latest)' : ''}
|
||||
Response
|
||||
{' '}
|
||||
{originalIndex + 1}
|
||||
{' '}
|
||||
{index === 0 ? '(Latest)' : ''}
|
||||
</div>
|
||||
</div>
|
||||
</Accordion.Header>
|
||||
|
||||
@@ -22,7 +22,7 @@ const StyledWrapper = styled.div`
|
||||
|
||||
tbody {
|
||||
tr:nth-child(odd) {
|
||||
background-color: ${(props) => props.theme.table.striped};
|
||||
background-color: ${props => props.theme.table.striped};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const WSResponseHeaders = ({ response }) => {
|
||||
const formatHeaders = (headers) => {
|
||||
const formatHeaders = headers => {
|
||||
if (!headers) return [];
|
||||
if (Array.isArray(headers)) return headers;
|
||||
return Object.entries(headers).map(([key, value]) => ({ name: key, value }));
|
||||
|
||||
@@ -2,7 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
font-size: 0.8125rem;
|
||||
color: ${(props) => props.theme.requestTabPanel.responseStatus};
|
||||
color: ${props => props.theme.requestTabPanel.responseStatus};
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -7,23 +7,21 @@ import { wsUpdateResponseSortOrder } from 'providers/ReduxStore/slices/collectio
|
||||
const WSResponseSortOrder = ({ collection, item }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const order = item.response?.sortOrder ?? -1
|
||||
const order = item.response?.sortOrder ?? -1;
|
||||
|
||||
const toggleSortOrder = ()=>{
|
||||
dispatch(
|
||||
wsUpdateResponseSortOrder({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
})
|
||||
);
|
||||
}
|
||||
const toggleSortOrder = () => {
|
||||
dispatch(wsUpdateResponseSortOrder({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid,
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="ml-2 flex items-center">
|
||||
<button onClick={toggleSortOrder} title={order === -1 ? 'Latest Last' : 'Latest First'}>
|
||||
{ order === -1
|
||||
? <IconSortDescending2 size={16} strokeWidth={1.5} />
|
||||
: <IconSortAscending2 size={16} strokeWidth={1.5} />}
|
||||
{ order === -1
|
||||
? <IconSortDescending2 size={16} strokeWidth={1.5} />
|
||||
: <IconSortAscending2 size={16} strokeWidth={1.5} />}
|
||||
</button>
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -7,16 +7,16 @@ const Wrapper = styled.div`
|
||||
align-items: center;
|
||||
|
||||
&.text-ok {
|
||||
color: ${(props) => props.theme.requestTabPanel.responseOk};
|
||||
color: ${props => props.theme.requestTabPanel.responseOk};
|
||||
}
|
||||
|
||||
&.text-pending {
|
||||
color: ${(props) => props.theme.requestTabPanel.responsePending};
|
||||
color: ${props => props.theme.requestTabPanel.responsePending};
|
||||
}
|
||||
|
||||
&.text-error {
|
||||
color: ${(props) => props.theme.requestTabPanel.responseError};
|
||||
color: ${props => props.theme.requestTabPanel.responseError};
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
export default Wrapper;
|
||||
|
||||
@@ -14,7 +14,7 @@ const wsStatusCodePhraseMap = {
|
||||
1012: 'SERVICE_RESTART',
|
||||
1013: 'TRY_AGAIN_LATER',
|
||||
1014: 'BAD_GATEWAY',
|
||||
1015: 'TLS_HANDSHAKE'
|
||||
1015: 'TLS_HANDSHAKE',
|
||||
};
|
||||
|
||||
export default wsStatusCodePhraseMap;
|
||||
export default wsStatusCodePhraseMap;
|
||||
|
||||
@@ -4,15 +4,15 @@ import wsStatusCodePhraseMap from './get-ws-status-code-phrase';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const WSStatusCode = ({ status, text }) => {
|
||||
const getTabClassname = (status) => {
|
||||
const getTabClassname = status => {
|
||||
return classnames('ml-2', {
|
||||
// ok if normal connect and normal closure
|
||||
'text-ok': parseInt(status) === 0 || parseInt(status) === 1000,
|
||||
'text-error': parseInt(status) !== 1000 && parseInt(status) !== 0
|
||||
'text-error': parseInt(status) !== 1000 && parseInt(status) !== 0,
|
||||
});
|
||||
};
|
||||
|
||||
const statusText = text || wsStatusCodePhraseMap[status]
|
||||
const statusText = text || wsStatusCodePhraseMap[status];
|
||||
|
||||
return (
|
||||
<StyledWrapper className={getTabClassname(status)}>
|
||||
@@ -22,4 +22,4 @@ const WSStatusCode = ({ status, text }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default WSStatusCode;
|
||||
export default WSStatusCode;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
border-left: 4px solid ${(props) => props.theme.colors.text.danger};
|
||||
border-left: 4px solid ${props => props.theme.colors.text.danger};
|
||||
border-top: 1px solid transparent;
|
||||
border-right: 1px solid transparent;
|
||||
border-bottom: 1px solid transparent;
|
||||
@@ -10,7 +10,7 @@ const StyledWrapper = styled.div`
|
||||
max-height: 200px;
|
||||
min-height: 70px;
|
||||
overflow-y: auto;
|
||||
background-color: ${(props) => (props.theme.bg === '#1e1e1e' ? 'rgba(40, 40, 40, 0.5)' : 'rgba(250, 250, 250, 0.9)')};
|
||||
background-color: ${props => (props.theme.bg === '#1e1e1e' ? 'rgba(40, 40, 40, 0.5)' : 'rgba(250, 250, 250, 0.9)')};
|
||||
|
||||
.close-button {
|
||||
opacity: 0.7;
|
||||
@@ -21,14 +21,14 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
svg {
|
||||
color: ${(props) => props.theme.text};
|
||||
color: ${props => props.theme.text};
|
||||
}
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.375rem;
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
color: ${props => props.theme.colors.text.danger};
|
||||
}
|
||||
|
||||
.error-message {
|
||||
@@ -37,7 +37,7 @@ const StyledWrapper = styled.div`
|
||||
line-height: 1.25rem;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
color: ${(props) => props.theme.text};
|
||||
color: ${props => props.theme.text};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -28,26 +28,24 @@ const WSResult = ({ response }) => {
|
||||
|
||||
const WSResponsePane = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const tabs = useSelector((state) => state.tabs.tabs);
|
||||
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
||||
const tabs = useSelector(state => state.tabs.tabs);
|
||||
const activeTabUid = useSelector(state => state.tabs.activeTabUid);
|
||||
const isLoading = ['queued', 'sending'].includes(item.requestState);
|
||||
|
||||
const requestTimeline = [...(collection?.timeline || [])].filter((obj) => {
|
||||
const requestTimeline = [...(collection?.timeline || [])].filter(obj => {
|
||||
if (obj.itemUid === item.uid) return true;
|
||||
});
|
||||
|
||||
const selectTab = (tab) => {
|
||||
dispatch(
|
||||
updateResponsePaneTab({
|
||||
uid: item.uid,
|
||||
responsePaneTab: tab
|
||||
})
|
||||
);
|
||||
const selectTab = tab => {
|
||||
dispatch(updateResponsePaneTab({
|
||||
uid: item.uid,
|
||||
responsePaneTab: tab,
|
||||
}));
|
||||
};
|
||||
|
||||
const response = item.response || {};
|
||||
|
||||
const getTabPanel = (tab) => {
|
||||
const getTabPanel = tab => {
|
||||
switch (tab) {
|
||||
case 'response': {
|
||||
return <WSResult response={response} />;
|
||||
@@ -84,7 +82,7 @@ const WSResponsePane = ({ item, collection }) => {
|
||||
return <div>Something went wrong</div>;
|
||||
}
|
||||
|
||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||
const focusedTab = find(tabs, t => t.uid === activeTabUid);
|
||||
if (!focusedTab || !focusedTab.uid || !focusedTab.responsePaneTab) {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
@@ -93,23 +91,23 @@ const WSResponsePane = ({ item, collection }) => {
|
||||
{
|
||||
name: 'response',
|
||||
label: 'Messages',
|
||||
count: Array.isArray(response.responses) ? response.responses.length : 0
|
||||
count: Array.isArray(response.responses) ? response.responses.length : 0,
|
||||
},
|
||||
{
|
||||
name: 'headers',
|
||||
label: 'Headers',
|
||||
count: response.headers ? Object.keys(response.headers).length : 0
|
||||
count: response.headers ? Object.keys(response.headers).length : 0,
|
||||
},
|
||||
{
|
||||
name: 'timeline',
|
||||
label: 'Timeline'
|
||||
}
|
||||
label: 'Timeline',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex flex-col h-full relative">
|
||||
<div className="flex flex-wrap items-center pl-3 pr-4 tabs" role="tablist">
|
||||
{tabConfig.map((tab) => (
|
||||
{tabConfig.map(tab => (
|
||||
<Tab
|
||||
key={tab.name}
|
||||
name={tab.name}
|
||||
|
||||
@@ -15,14 +15,14 @@ const ShareCollection = ({ onClose, collectionUid }) => {
|
||||
const isCollectionLoading = areItemsLoading(collection);
|
||||
|
||||
const hasNonExportableRequestTypes = useMemo(() => {
|
||||
let types = new Set()
|
||||
let types = new Set();
|
||||
const checkItem = (item) => {
|
||||
if (item.type === 'grpc-request') {
|
||||
types.add("gRPC")
|
||||
types.add('gRPC');
|
||||
return true;
|
||||
}
|
||||
if (item.type === 'ws-request') {
|
||||
types.add("WebSocket")
|
||||
types.add('WebSocket');
|
||||
return true;
|
||||
}
|
||||
if (item.items) {
|
||||
@@ -32,8 +32,8 @@ const ShareCollection = ({ onClose, collectionUid }) => {
|
||||
};
|
||||
return {
|
||||
has: collection?.items?.filter(checkItem).length || false,
|
||||
types:[...types],
|
||||
}
|
||||
types: [...types],
|
||||
};
|
||||
}, [collection]);
|
||||
|
||||
const handleExportBrunoCollection = () => {
|
||||
@@ -87,7 +87,12 @@ const ShareCollection = ({ onClose, collectionUid }) => {
|
||||
{hasNonExportableRequestTypes.has && (
|
||||
<div className="px-3 py-2 bg-yellow-50 w-full dark:bg-yellow-900/20 text-yellow-700 dark:text-yellow-400 text-xs border-b border-yellow-100 dark:border-yellow-800/20 flex items-center">
|
||||
<IconAlertTriangle size={16} className="mr-2 flex-shrink-0" />
|
||||
<span>Note: {hasNonExportableRequestTypes.types.join(', ')} requests in this collection will not be exported</span>
|
||||
<span>
|
||||
Note:
|
||||
{hasNonExportableRequestTypes.types.join(', ')}
|
||||
{' '}
|
||||
requests in this collection will not be exported
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center p-3 w-full">
|
||||
|
||||
@@ -38,7 +38,7 @@ const Wrapper = styled.div`
|
||||
color: ${(props) => props.theme.request.grpc};
|
||||
}
|
||||
.method-ws {
|
||||
color: ${(props) => props.theme.request.ws};
|
||||
color: ${props => props.theme.request.ws};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -2,20 +2,19 @@ import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
|
||||
const getMethodFlags = (item) => ({
|
||||
const getMethodFlags = item => ({
|
||||
isGrpc: item.type === 'grpc-request',
|
||||
isWS: item.type === 'ws-request'
|
||||
isWS: item.type === 'ws-request',
|
||||
});
|
||||
|
||||
const getMethodText = (item, { isGrpc, isWS }) =>
|
||||
isGrpc
|
||||
? 'grpc'
|
||||
: isWS
|
||||
? 'ws'
|
||||
: item.request.method.length > 5
|
||||
? item.request.method.substring(0, 3)
|
||||
: item.request.method;
|
||||
? 'ws'
|
||||
: item.request.method.length > 5
|
||||
? item.request.method.substring(0, 3)
|
||||
: item.request.method;
|
||||
|
||||
const getClassname = (method = '', { isGrpc, isWS }) => {
|
||||
method = method.toLocaleLowerCase();
|
||||
@@ -28,11 +27,10 @@ const getClassname = (method = '', { isGrpc, isWS }) => {
|
||||
'method-head': method === 'head',
|
||||
'method-options': method === 'options',
|
||||
'method-grpc': isGrpc,
|
||||
'method-ws': isWS
|
||||
'method-ws': isWS,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const RequestMethod = ({ item }) => {
|
||||
if (!['http-request', 'graphql-request', 'grpc-request', 'ws-request'].includes(item.type)) {
|
||||
return null;
|
||||
|
||||
@@ -176,22 +176,20 @@ const NewRequest = ({ collectionUid, item, isEphemeral, onClose }) => {
|
||||
|
||||
// will need to handle import from grpcurl command when we support it, now it is just for creating new requests
|
||||
} else if (isWsRequest) {
|
||||
dispatch(
|
||||
newWsRequest({
|
||||
requestName: values.requestName,
|
||||
requestMethod: values.requestMethod,
|
||||
filename: values.filename,
|
||||
requestType: values.requestType,
|
||||
requestUrl: values.requestUrl,
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item ? item.uid : null
|
||||
})
|
||||
)
|
||||
dispatch(newWsRequest({
|
||||
requestName: values.requestName,
|
||||
requestMethod: values.requestMethod,
|
||||
filename: values.filename,
|
||||
requestType: values.requestType,
|
||||
requestUrl: values.requestUrl,
|
||||
collectionUid: collection.uid,
|
||||
itemUid: item ? item.uid : null,
|
||||
}))
|
||||
.then(() => {
|
||||
toast.success('New request created!');
|
||||
onClose();
|
||||
})
|
||||
.catch((err) => toast.error(err ? err.message : 'An error occurred while adding the request'));
|
||||
.catch(err => toast.error(err ? err.message : 'An error occurred while adding the request'));
|
||||
} else if (isEphemeral) {
|
||||
const uid = uuid();
|
||||
dispatch(
|
||||
|
||||
@@ -27,7 +27,7 @@ const initialState = {
|
||||
},
|
||||
beta: {
|
||||
grpc: false,
|
||||
websocket: false
|
||||
websocket: false,
|
||||
}
|
||||
},
|
||||
generateCode: {
|
||||
|
||||
@@ -261,19 +261,19 @@ export const wsConnectOnly = (item, collectionUid) => (dispatch, getState) => {
|
||||
|
||||
const globalEnvironmentVariables = getGlobalEnvironmentVariables({
|
||||
globalEnvironments,
|
||||
activeGlobalEnvironmentUid
|
||||
activeGlobalEnvironmentUid,
|
||||
});
|
||||
collectionCopy.globalEnvironmentVariables = globalEnvironmentVariables;
|
||||
|
||||
const environment = findEnvironmentInCollection(collectionCopy, collectionCopy.activeEnvironmentUid);
|
||||
|
||||
connectWS(itemCopy, collectionCopy, environment, collectionCopy.runtimeVariables, { connectOnly: true })
|
||||
.then(resolve)
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
});
|
||||
})
|
||||
}
|
||||
.then(resolve)
|
||||
.catch(err => {
|
||||
toast.error(err.message);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
@@ -327,7 +327,7 @@ export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
|
||||
} else if (isWsRequest) {
|
||||
sendWsRequest(itemCopy, collectionCopy, environment, collectionCopy.runtimeVariables)
|
||||
.then(resolve)
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
toast.error(err.message);
|
||||
});
|
||||
} else {
|
||||
@@ -1085,7 +1085,7 @@ export const newGrpcRequest = (params) => (dispatch, getState) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const newWsRequest = (params) => (dispatch, getState) => {
|
||||
export const newWsRequest = params => (dispatch, getState) => {
|
||||
const { requestName, requestMethod, filename, requestUrl, collectionUid, body, auth, headers, itemUid } = params;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -1109,14 +1109,14 @@ export const newWsRequest = (params) => (dispatch, getState) => {
|
||||
ws: [
|
||||
{
|
||||
name: 'message 1',
|
||||
content: '{}'
|
||||
}
|
||||
]
|
||||
content: '{}',
|
||||
},
|
||||
],
|
||||
},
|
||||
auth: auth ?? {
|
||||
mode: 'inherit'
|
||||
}
|
||||
}
|
||||
mode: 'inherit',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const resolvedFilename = resolveRequestFilename(filename);
|
||||
@@ -1124,21 +1124,19 @@ export const newWsRequest = (params) => (dispatch, getState) => {
|
||||
const { ipcRenderer } = window;
|
||||
|
||||
// Set the seq field for WebSocket requests
|
||||
const items = filter(collection.items, (i) => isItemAFolder(i) || isItemARequest(i));
|
||||
const items = filter(collection.items, i => isItemAFolder(i) || isItemARequest(i));
|
||||
item.seq = items.length + 1;
|
||||
|
||||
ipcRenderer
|
||||
.invoke('renderer:new-request', fullName, item)
|
||||
.then(() => {
|
||||
// task middleware will track this and open the new request in a new tab once request is created
|
||||
dispatch(
|
||||
insertTaskIntoQueue({
|
||||
uid: uuid(),
|
||||
type: 'OPEN_REQUEST',
|
||||
collectionUid,
|
||||
itemPathname: fullName
|
||||
})
|
||||
);
|
||||
dispatch(insertTaskIntoQueue({
|
||||
uid: uuid(),
|
||||
type: 'OPEN_REQUEST',
|
||||
collectionUid,
|
||||
itemPathname: fullName,
|
||||
}));
|
||||
resolve();
|
||||
})
|
||||
.catch(reject);
|
||||
|
||||
@@ -61,7 +61,7 @@ const wsStatusCodes = {
|
||||
1012: 'SERVICE_RESTART',
|
||||
1013: 'TRY_AGAIN_LATER',
|
||||
1014: 'BAD_GATEWAY',
|
||||
1015: 'TLS_HANDSHAKE'
|
||||
1015: 'TLS_HANDSHAKE',
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
@@ -82,7 +82,7 @@ const initiatedGrpcResponse = {
|
||||
isError: false,
|
||||
duration: 0,
|
||||
responses: [],
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
const initiatedWsResponse = {
|
||||
@@ -99,7 +99,7 @@ const initiatedWsResponse = {
|
||||
error: null,
|
||||
errorDetails: null,
|
||||
metadata: [],
|
||||
trailers: []
|
||||
trailers: [],
|
||||
};
|
||||
|
||||
export const collectionsSlice = createSlice({
|
||||
@@ -346,7 +346,7 @@ export const collectionsSlice = createSlice({
|
||||
enabled: true,
|
||||
type: 'text',
|
||||
uid: uuid(),
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -394,8 +394,8 @@ export const collectionsSlice = createSlice({
|
||||
}
|
||||
|
||||
// Ensure timestamp is a number (milliseconds since epoch)
|
||||
const timestamp =
|
||||
item?.requestSent?.timestamp instanceof Date
|
||||
const timestamp
|
||||
= item?.requestSent?.timestamp instanceof Date
|
||||
? item.requestSent.timestamp.getTime()
|
||||
: item?.requestSent?.timestamp || Date.now();
|
||||
|
||||
@@ -409,7 +409,7 @@ export const collectionsSlice = createSlice({
|
||||
data: {
|
||||
request: item.requestSent || item.request,
|
||||
response: action.payload.response,
|
||||
timestamp: timestamp
|
||||
timestamp: timestamp,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -448,7 +448,7 @@ export const collectionsSlice = createSlice({
|
||||
data: {
|
||||
request: eventData || item.requestSent || item.request,
|
||||
timestamp: Date.now(),
|
||||
eventData: eventData
|
||||
eventData: eventData,
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -514,8 +514,8 @@ export const collectionsSlice = createSlice({
|
||||
// Handle error status (non-zero code)
|
||||
if (statusCode !== 0) {
|
||||
updatedResponse.isError = true;
|
||||
updatedResponse.error =
|
||||
statusDetails || `gRPC error with code ${statusCode} (${updatedResponse.statusText})`;
|
||||
updatedResponse.error
|
||||
= statusDetails || `gRPC error with code ${statusCode} (${updatedResponse.statusText})`;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -571,7 +571,7 @@ export const collectionsSlice = createSlice({
|
||||
request: item.requestSent || item.request,
|
||||
response: updatedResponse,
|
||||
eventData: eventData, // Store the original event data
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -1388,8 +1388,7 @@ export const collectionsSlice = createSlice({
|
||||
|
||||
item.draft.request.body.file = filter(
|
||||
item.draft.request.body.file,
|
||||
(p) => p.uid !== action.payload.paramUid
|
||||
);
|
||||
p => p.uid !== action.payload.paramUid);
|
||||
|
||||
if (item.draft.request.body.file.length > 0) {
|
||||
item.draft.request.body.file[0].selected = true;
|
||||
@@ -1773,13 +1772,13 @@ export const collectionsSlice = createSlice({
|
||||
const params = item.draft.request.vars.req;
|
||||
|
||||
item.draft.request.vars.req = updateReorderedItem.map((uid) => {
|
||||
return params.find((param) => param.uid === uid);
|
||||
return params.find(param => param.uid === uid);
|
||||
});
|
||||
} else if (type === 'response') {
|
||||
const params = item.draft.request.vars.res;
|
||||
|
||||
item.draft.request.vars.res = updateReorderedItem.map((uid) => {
|
||||
return params.find((param) => param.uid === uid);
|
||||
return params.find(param => param.uid === uid);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2173,7 +2172,7 @@ export const collectionsSlice = createSlice({
|
||||
name: directoryName,
|
||||
collapsed: true,
|
||||
type: 'folder',
|
||||
items: []
|
||||
items: [],
|
||||
};
|
||||
currentSubItems.push(childItem);
|
||||
}
|
||||
@@ -2650,7 +2649,7 @@ export const collectionsSlice = createSlice({
|
||||
url,
|
||||
credentials,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
});
|
||||
|
||||
collection.oauth2Credentials = filteredOauth2Credentials;
|
||||
@@ -2673,8 +2672,8 @@ export const collectionsSlice = createSlice({
|
||||
url,
|
||||
credentials,
|
||||
credentialsId,
|
||||
debugInfo: debugInfo.data
|
||||
}
|
||||
debugInfo: debugInfo.data,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -2688,8 +2687,7 @@ export const collectionsSlice = createSlice({
|
||||
let collectionOauth2Credentials = cloneDeep(collection.oauth2Credentials);
|
||||
const filteredOauth2Credentials = filter(
|
||||
collectionOauth2Credentials,
|
||||
(creds) => !(creds.url === url && creds.collectionUid === collectionUid)
|
||||
);
|
||||
creds => !(creds.url === url && creds.collectionUid === collectionUid));
|
||||
collection.oauth2Credentials = filteredOauth2Credentials;
|
||||
}
|
||||
},
|
||||
@@ -2699,8 +2697,7 @@ export const collectionsSlice = createSlice({
|
||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||
const oauth2Credential = find(
|
||||
collection?.oauth2Credentials || [],
|
||||
(creds) => creds.url === url && creds.collectionUid === collectionUid && creds.credentialsId === credentialsId
|
||||
);
|
||||
creds => creds.url === url && creds.collectionUid === collectionUid && creds.credentialsId === credentialsId);
|
||||
return oauth2Credential;
|
||||
},
|
||||
|
||||
@@ -2796,8 +2793,8 @@ export const collectionsSlice = createSlice({
|
||||
data: {
|
||||
request: eventData || item.requestSent || item.request,
|
||||
timestamp: Date.now(),
|
||||
eventData: eventData
|
||||
}
|
||||
eventData: eventData,
|
||||
},
|
||||
});
|
||||
},
|
||||
wsResponseReceived: (state, action) => {
|
||||
@@ -2817,40 +2814,40 @@ export const collectionsSlice = createSlice({
|
||||
...currentResponse,
|
||||
isError: false,
|
||||
error: '',
|
||||
duration: Date.now() - (timestamp || Date.now())
|
||||
duration: Date.now() - (timestamp || Date.now()),
|
||||
};
|
||||
|
||||
// Process based on event type
|
||||
switch (eventType) {
|
||||
case 'message':
|
||||
// Add message to responses list
|
||||
updatedResponse.responses = (currentResponse?.responses||[]).concat(eventData)
|
||||
updatedResponse.responses = (currentResponse?.responses || []).concat(eventData);
|
||||
break;
|
||||
|
||||
case 'redirect':
|
||||
updatedResponse.requestHeaders = eventData.headers
|
||||
updatedResponse.responses ||= []
|
||||
updatedResponse.requestHeaders = eventData.headers;
|
||||
updatedResponse.responses ||= [];
|
||||
updatedResponse.responses.push({
|
||||
message: eventData.message,
|
||||
message: eventData.message,
|
||||
type: eventData.type,
|
||||
timestamp: eventData.timestamp,
|
||||
})
|
||||
break
|
||||
|
||||
});
|
||||
break;
|
||||
|
||||
case 'upgrade':
|
||||
updatedResponse.headers = eventData.headers
|
||||
break
|
||||
updatedResponse.headers = eventData.headers;
|
||||
break;
|
||||
|
||||
case 'open':
|
||||
updatedResponse.status = 'CONNECTED';
|
||||
updatedResponse.statusText = 'CONNECTED';
|
||||
updatedResponse.statusCode = 0;
|
||||
updatedResponse.responses ||= []
|
||||
updatedResponse.responses ||= [];
|
||||
updatedResponse.responses.push({
|
||||
message: `Connected to ${eventData.url}`,
|
||||
type: 'info',
|
||||
timestamp: eventData.timestamp
|
||||
})
|
||||
timestamp: eventData.timestamp,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'close':
|
||||
@@ -2861,12 +2858,12 @@ export const collectionsSlice = createSlice({
|
||||
updatedResponse.statusCode = code;
|
||||
updatedResponse.statusText = wsStatusCodes[code] || 'CLOSED';
|
||||
updatedResponse.statusDescription = reason;
|
||||
|
||||
|
||||
updatedResponse.responses.push({
|
||||
type: code !== 1000 ? 'info' : 'error',
|
||||
message: reason.trim().length ? ['Closed:',reason.trim()].join(' ') : 'Closed',
|
||||
message: reason.trim().length ? ['Closed:', reason.trim()].join(' ') : 'Closed',
|
||||
timestamp,
|
||||
})
|
||||
});
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
@@ -2880,7 +2877,7 @@ export const collectionsSlice = createSlice({
|
||||
type: 'error',
|
||||
message: errorDetails || 'WebSocket error occurred',
|
||||
timestamp,
|
||||
})
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
@@ -2901,8 +2898,8 @@ export const collectionsSlice = createSlice({
|
||||
item.response.sortOrder = item.response.sortOrder ? -item.response.sortOrder : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
@@ -3032,7 +3029,7 @@ export const {
|
||||
updateActiveConnections,
|
||||
runWsRequestEvent,
|
||||
wsResponseReceived,
|
||||
wsUpdateResponseSortOrder
|
||||
wsUpdateResponseSortOrder,
|
||||
} = collectionsSlice.actions;
|
||||
|
||||
export default collectionsSlice.reducer;
|
||||
|
||||
@@ -81,8 +81,8 @@ export const tabsSlice = createSlice({
|
||||
type: type || 'request',
|
||||
...(uid ? { folderUid: uid } : {}),
|
||||
preview: preview !== undefined
|
||||
? preview
|
||||
: !nonReplaceableTabTypes.includes(type)
|
||||
? preview
|
||||
: !nonReplaceableTabTypes.includes(type),
|
||||
});
|
||||
state.activeTabUid = uid;
|
||||
},
|
||||
|
||||
@@ -103,14 +103,14 @@ const darkTheme = {
|
||||
head: '#d69956'
|
||||
},
|
||||
grpc: '#6366f1',
|
||||
ws: '#f59e0b'
|
||||
ws: '#f59e0b',
|
||||
},
|
||||
|
||||
requestTabPanel: {
|
||||
url: {
|
||||
bg: '#3D3D3D',
|
||||
icon: 'rgb(204, 204, 204)',
|
||||
errorHoverBg: '#4a2a2a'
|
||||
errorHoverBg: '#4a2a2a',
|
||||
},
|
||||
dragbar: {
|
||||
border: '#444',
|
||||
@@ -264,7 +264,7 @@ const darkTheme = {
|
||||
border: '#373737',
|
||||
placeholder: {
|
||||
color: '#a2a2a2',
|
||||
opacity: 0.5
|
||||
opacity: 0.5,
|
||||
},
|
||||
gutter: {
|
||||
bg: '#262626'
|
||||
@@ -308,7 +308,7 @@ const darkTheme = {
|
||||
tooltip: {
|
||||
bg: '#1f1f1f',
|
||||
color: '#ffffff',
|
||||
shortcutColor: '#f59e0b'
|
||||
shortcutColor: '#f59e0b',
|
||||
},
|
||||
|
||||
infoTip: {
|
||||
|
||||
@@ -103,14 +103,14 @@ const lightTheme = {
|
||||
head: '#ca7811'
|
||||
},
|
||||
grpc: '#6366f1',
|
||||
ws: '#f59e0b'
|
||||
ws: '#f59e0b',
|
||||
},
|
||||
|
||||
requestTabPanel: {
|
||||
url: {
|
||||
bg: '#f3f3f3',
|
||||
icon: '#515151',
|
||||
errorHoverBg: '#fef2f2'
|
||||
errorHoverBg: '#fef2f2',
|
||||
},
|
||||
dragbar: {
|
||||
border: '#efefef',
|
||||
@@ -310,7 +310,7 @@ const lightTheme = {
|
||||
tooltip: {
|
||||
bg: '#374151',
|
||||
color: '#ffffff',
|
||||
shortcutColor: '#f59e0b'
|
||||
shortcutColor: '#f59e0b',
|
||||
},
|
||||
|
||||
infoTip: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* @param {string} snippet
|
||||
* @param {string} snippet
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isXML(snippet){
|
||||
return /<\/?[a-z][\s\S]*>/i.test(snippet)
|
||||
export function isXML(snippet) {
|
||||
return /<\/?[a-z][\s\S]*>/i.test(snippet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} snippet
|
||||
* @param {string} snippet
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isJSON(snippet) {
|
||||
@@ -20,15 +20,15 @@ export function isJSON(snippet) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} snippet
|
||||
* @param {string} snippet
|
||||
* @returns {string}
|
||||
*/
|
||||
export function autoDetectLang(snippet) {
|
||||
if (isJSON(snippet)) {
|
||||
return 'json';
|
||||
}
|
||||
if(isXML(snippet)){
|
||||
return 'xml'
|
||||
if (isXML(snippet)) {
|
||||
return 'xml';
|
||||
}
|
||||
return 'text'
|
||||
return 'text';
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ export const areItemsLoading = (folder) => {
|
||||
export const getItemsLoadStats = (folder) => {
|
||||
let loadingCount = 0;
|
||||
let flattenedItems = flattenItems(folder.items);
|
||||
flattenedItems?.forEach((i) => {
|
||||
flattenedItems?.forEach(i => {
|
||||
if (i?.loading) {
|
||||
loadingCount += 1;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
multipartForm: copyMultipartFormParams(si.request.body.multipartForm),
|
||||
file: copyFileParams(si.request.body.file),
|
||||
grpc: si.request.body.grpc,
|
||||
ws: si.request.body.ws
|
||||
ws: si.request.body.ws,
|
||||
},
|
||||
script: si.request.script,
|
||||
vars: si.request.vars,
|
||||
@@ -337,7 +337,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
autoFetchToken: get(si.request, 'auth.oauth2.autoFetchToken', true),
|
||||
autoRefreshToken: get(si.request, 'auth.oauth2.autoRefreshToken', true),
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {})
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {}),
|
||||
};
|
||||
break;
|
||||
case 'authorization_code':
|
||||
@@ -358,7 +358,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
autoFetchToken: get(si.request, 'auth.oauth2.autoFetchToken', true),
|
||||
autoRefreshToken: get(si.request, 'auth.oauth2.autoRefreshToken', true),
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {})
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {}),
|
||||
};
|
||||
break;
|
||||
case 'implicit':
|
||||
@@ -374,7 +374,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
tokenHeaderPrefix: get(si.request, 'auth.oauth2.tokenHeaderPrefix', 'Bearer'),
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
autoFetchToken: get(si.request, 'auth.oauth2.autoFetchToken', true),
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {})
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {}),
|
||||
};
|
||||
break;
|
||||
case 'client_credentials':
|
||||
@@ -392,7 +392,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
tokenQueryKey: get(si.request, 'auth.oauth2.tokenQueryKey', ''),
|
||||
autoFetchToken: get(si.request, 'auth.oauth2.autoFetchToken', true),
|
||||
autoRefreshToken: get(si.request, 'auth.oauth2.autoRefreshToken', true),
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {})
|
||||
additionalParameters: get(si.request, 'auth.oauth2.additionalParameters', {}),
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -428,7 +428,7 @@ export const transformCollectionToSaveToExportAsFile = (collection, options = {}
|
||||
if (di.request.body.mode === 'ws') {
|
||||
di.request.body.ws = di.request.body.ws.map(({ name, content }, index) => ({
|
||||
name: name ? name : `message ${index + 1}`,
|
||||
content: replaceTabsWithSpaces(content)
|
||||
content: replaceTabsWithSpaces(content),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -669,8 +669,8 @@ export const transformRequestToSaveToFilesystem = (item) => {
|
||||
ws: itemToSave.request.body.ws.map(({ name, content, type }, index) => ({
|
||||
name: name ? name : `message ${index + 1}`,
|
||||
type,
|
||||
content: replaceTabsWithSpaces(content)
|
||||
}))
|
||||
content: replaceTabsWithSpaces(content),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -702,9 +702,9 @@ export const deleteItemInCollectionByPathname = (pathname, collection) => {
|
||||
|
||||
export const isItemARequest = (item) => {
|
||||
return (
|
||||
item.hasOwnProperty('request') &&
|
||||
['http-request', 'graphql-request', 'grpc-request', 'ws-request'].includes(item.type) &&
|
||||
!item.items
|
||||
item.hasOwnProperty('request')
|
||||
&& ['http-request', 'graphql-request', 'grpc-request', 'ws-request'].includes(item.type)
|
||||
&& !item.items
|
||||
);
|
||||
};
|
||||
|
||||
@@ -895,7 +895,7 @@ export const getDefaultRequestPaneTab = (item) => {
|
||||
|
||||
export const getGlobalEnvironmentVariables = ({ globalEnvironments, activeGlobalEnvironmentUid }) => {
|
||||
let variables = {};
|
||||
const environment = globalEnvironments?.find((env) => env?.uid === activeGlobalEnvironmentUid);
|
||||
const environment = globalEnvironments?.find(env => env?.uid === activeGlobalEnvironmentUid);
|
||||
if (environment) {
|
||||
each(environment.variables, (variable) => {
|
||||
if (variable.name && variable.enabled) {
|
||||
@@ -907,7 +907,7 @@ export const getGlobalEnvironmentVariables = ({ globalEnvironments, activeGlobal
|
||||
};
|
||||
|
||||
export const getGlobalEnvironmentVariablesMasked = ({ globalEnvironments, activeGlobalEnvironmentUid }) => {
|
||||
const environment = globalEnvironments?.find((env) => env?.uid === activeGlobalEnvironmentUid);
|
||||
const environment = globalEnvironments?.find(env => env?.uid === activeGlobalEnvironmentUid);
|
||||
|
||||
if (environment && Array.isArray(environment.variables)) {
|
||||
return environment.variables
|
||||
@@ -997,7 +997,7 @@ export const getAllVariables = (collection, item) => {
|
||||
...envVariables,
|
||||
...folderVariables,
|
||||
...requestVariables,
|
||||
...runtimeVariables
|
||||
...runtimeVariables,
|
||||
};
|
||||
|
||||
const maskedEnvVariables = getEnvironmentVariablesMasked(collection) || [];
|
||||
@@ -1009,7 +1009,7 @@ export const getAllVariables = (collection, item) => {
|
||||
const uniqueMaskedVariables = [...new Set([...filteredMaskedEnvVariables, ...filteredMaskedGlobalEnvVariables])];
|
||||
|
||||
const oauth2CredentialVariables = getFormattedCollectionOauth2Credentials({
|
||||
oauth2Credentials: collection?.oauth2Credentials
|
||||
oauth2Credentials: collection?.oauth2Credentials,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -1151,7 +1151,7 @@ export const getReorderedItemsInTargetDirectory = ({ items, targetItemUid, dragg
|
||||
const draggedItem = findItem(itemsWithFixedSequences, draggedItemUid);
|
||||
const targetSequence = targetItem?.seq;
|
||||
const draggedSequence = draggedItem?.seq;
|
||||
itemsWithFixedSequences?.forEach((item) => {
|
||||
itemsWithFixedSequences?.forEach(item => {
|
||||
const isDraggedItem = item?.uid === draggedItemUid;
|
||||
const isBetween = isItemBetweenSequences(item?.seq, draggedSequence, targetSequence);
|
||||
if (isBetween) {
|
||||
@@ -1163,16 +1163,12 @@ export const getReorderedItemsInTargetDirectory = ({ items, targetItemUid, dragg
|
||||
}
|
||||
});
|
||||
// only return items that have been reordered
|
||||
return itemsWithFixedSequences.filter(
|
||||
(item) => items?.find((originalItem) => originalItem?.uid === item?.uid)?.seq !== item?.seq
|
||||
);
|
||||
return itemsWithFixedSequences.filter(item => items?.find(originalItem => originalItem?.uid === item?.uid)?.seq !== item?.seq);
|
||||
};
|
||||
|
||||
export const getReorderedItemsInSourceDirectory = ({ items }) => {
|
||||
const itemsWithFixedSequences = resetSequencesInFolder(cloneDeep(items));
|
||||
return itemsWithFixedSequences.filter(
|
||||
(item) => items?.find((originalItem) => originalItem?.uid === item?.uid)?.seq !== item?.seq
|
||||
);
|
||||
return itemsWithFixedSequences.filter(item => items?.find(originalItem => originalItem?.uid === item?.uid)?.seq !== item?.seq);
|
||||
};
|
||||
|
||||
export const calculateDraggedItemNewPathname = ({ draggedItem, targetItem, dropType, collectionPathname }) => {
|
||||
@@ -1195,10 +1191,10 @@ export const calculateDraggedItemNewPathname = ({ draggedItem, targetItem, dropT
|
||||
export const getUniqueTagsFromItems = (items = []) => {
|
||||
const allTags = new Set();
|
||||
const getTags = (items) => {
|
||||
items.forEach((item) => {
|
||||
items.forEach(item => {
|
||||
if (isItemARequest(item)) {
|
||||
const tags = item.draft ? get(item, 'draft.tags', []) : get(item, 'tags', []);
|
||||
tags.forEach((tag) => allTags.add(tag));
|
||||
tags.forEach(tag => allTags.add(tag));
|
||||
}
|
||||
if (item.items) {
|
||||
getTags(item.items);
|
||||
@@ -1215,7 +1211,7 @@ export const getRequestItemsForCollectionRun = ({ recursive, items = [], tags })
|
||||
if (recursive) {
|
||||
requestItems = flattenItems(items);
|
||||
} else {
|
||||
each(items, (item) => {
|
||||
each(items, item => {
|
||||
if (item.request) {
|
||||
requestItems.push(item);
|
||||
}
|
||||
@@ -1223,7 +1219,7 @@ export const getRequestItemsForCollectionRun = ({ recursive, items = [], tags })
|
||||
}
|
||||
|
||||
const requestTypes = ['http-request', 'graphql-request'];
|
||||
requestItems = requestItems.filter((request) => requestTypes.includes(request.type));
|
||||
requestItems = requestItems.filter(request => requestTypes.includes(request.type));
|
||||
|
||||
if (tags && tags.include && tags.exclude) {
|
||||
const includeTags = tags.include ? tags.include : [];
|
||||
|
||||
@@ -78,7 +78,7 @@ export const transformItemsInCollection = (collection) => {
|
||||
if (isGrpcRequest) {
|
||||
delete item.request.params;
|
||||
}
|
||||
|
||||
|
||||
if (isWSRequest) {
|
||||
delete item.request.params;
|
||||
delete item.request.method;
|
||||
|
||||
@@ -27,7 +27,7 @@ export const sendNetworkRequest = async (item, collection, environment, runtimeV
|
||||
|
||||
export const sendGrpcRequest = async (item, collection, environment, runtimeVariables) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
startGrpcRequest(item, collection, environment, runtimeVariables)
|
||||
startGrpcRequest(item, collection, environment, runtimeVariables)
|
||||
.then((initialState) => {
|
||||
// Return an initial state object to update the UI
|
||||
// The real response data will be handled by event listeners
|
||||
@@ -103,7 +103,7 @@ export const startGrpcRequest = async (item, collection, environment, runtimeVar
|
||||
export const sendGrpcMessage = async (item, collectionUid, message) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { ipcRenderer } = window;
|
||||
ipcRenderer.invoke('grpc:send-message', item.uid, collectionUid, message)
|
||||
ipcRenderer.invoke('grpc:send-message', item.uid, collectionUid, message)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
@@ -215,15 +215,15 @@ export const generateGrpcSampleMessage = async (methodPath, existingMessage = nu
|
||||
export const connectWS = async (item, collection, environment, runtimeVariables, options) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
startWsConnection(item, collection, environment, runtimeVariables, options)
|
||||
.then((initialState) => {
|
||||
.then(initialState => {
|
||||
// Return an initial state object to update the UI
|
||||
// The real response data will be handled by event listeners
|
||||
resolve({
|
||||
...initialState,
|
||||
timeline: []
|
||||
timeline: [],
|
||||
});
|
||||
})
|
||||
.catch((err) => reject(err));
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -237,14 +237,14 @@ export const sendWsRequest = (item, collection, environment, runtimeVariables) =
|
||||
};
|
||||
const { request } = item.draft ? item.draft : item;
|
||||
queueWsMessage(item, collection.uid, request.body.ws[0].content)
|
||||
.then((initialState) => {
|
||||
.then(initialState => {
|
||||
// Return an initial state object to update the UI
|
||||
// The real response data will be handled by event listeners
|
||||
resolve({
|
||||
...initialState,
|
||||
});
|
||||
})
|
||||
.catch((err) => reject(err));
|
||||
.catch(err => reject(err));
|
||||
await ensureConnection();
|
||||
});
|
||||
};
|
||||
@@ -262,12 +262,12 @@ export const startWsConnection = async (item, collection, environment, runtimeVa
|
||||
environment,
|
||||
runtimeVariables,
|
||||
settings,
|
||||
options
|
||||
options,
|
||||
})
|
||||
.then(() => {
|
||||
resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
@@ -305,7 +305,7 @@ export const sendWsMessage = async (item, collectionUid, message) => {
|
||||
* @param {string} requestId - The request ID to close
|
||||
* @returns {Promise<Object>} - The result of the close operation
|
||||
*/
|
||||
export const closeWsConnection = async (requestId) => {
|
||||
export const closeWsConnection = async requestId => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { ipcRenderer } = window;
|
||||
ipcRenderer.invoke('ws:close-connection', requestId).then(resolve).catch(reject);
|
||||
@@ -317,7 +317,7 @@ export const closeWsConnection = async (requestId) => {
|
||||
* @param {string} requestId - The request ID to check
|
||||
* @returns {Promise<boolean>} - Whether the connection is active
|
||||
*/
|
||||
export const isWsConnectionActive = async (requestId) => {
|
||||
export const isWsConnectionActive = async requestId => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { ipcRenderer } = window;
|
||||
ipcRenderer.invoke('ws:is-connection-active', requestId).then(resolve).catch(reject);
|
||||
|
||||
@@ -17,102 +17,84 @@ const useWsEventListeners = () => {
|
||||
|
||||
// Handle WebSocket requestSent event
|
||||
const removeWsRequestSentListener = ipcRenderer.on('ws:request', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
runWsRequestEvent({
|
||||
eventType: 'request',
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
requestUid: requestId,
|
||||
eventData
|
||||
})
|
||||
);
|
||||
dispatch(runWsRequestEvent({
|
||||
eventType: 'request',
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
requestUid: requestId,
|
||||
eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
|
||||
const removeWsUpgradeListener = ipcRenderer.on('ws:upgrade', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'upgrade',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'upgrade',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
const removeWsRedirectListener = ipcRenderer.on('ws:redirect', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'redirect',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'redirect',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
// Handle WebSocket message event
|
||||
const removeWsMessageListener = ipcRenderer.on('ws:message', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'message',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'message',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
// Handle WebSocket open event
|
||||
const removeWsOpenListener = ipcRenderer.on('ws:open', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'open',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'open',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
// Handle WebSocket close event
|
||||
const removeWsCloseListener = ipcRenderer.on('ws:close', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'close',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'close',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
// Handle WebSocket error event
|
||||
const removeWsErrorListener = ipcRenderer.on('ws:error', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'error',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'error',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
// Handle WebSocket connecting event
|
||||
const removeWsConnectingListener = ipcRenderer.on('ws:connecting', (requestId, collectionUid, eventData) => {
|
||||
dispatch(
|
||||
wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'connecting',
|
||||
eventData: eventData
|
||||
})
|
||||
);
|
||||
dispatch(wsResponseReceived({
|
||||
itemUid: requestId,
|
||||
collectionUid: collectionUid,
|
||||
eventType: 'connecting',
|
||||
eventData: eventData,
|
||||
}));
|
||||
});
|
||||
|
||||
const removeWsConnectionsChangedListener = ipcRenderer.on('ws:connections-changed', (data) => {
|
||||
const removeWsConnectionsChangedListener = ipcRenderer.on('ws:connections-changed', data => {
|
||||
dispatch(updateActiveConnectionsInStore(data));
|
||||
});
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ const runSingleRequest = async function (
|
||||
cookies[name.trim()] = rest.join('=').trim();
|
||||
}
|
||||
return cookies;
|
||||
}, {});
|
||||
}, {});
|
||||
|
||||
const mergedCookies = {
|
||||
...parseCookies(existingCookieString),
|
||||
@@ -400,7 +400,7 @@ const runSingleRequest = async function (
|
||||
try {
|
||||
let axiosInstance = makeAxiosInstance({
|
||||
requestMaxRedirects: requestMaxRedirects,
|
||||
disableCookies: options.disableCookies
|
||||
disableCookies: options.disableCookies,
|
||||
});
|
||||
if (request.ntlmConfig) {
|
||||
axiosInstance = NtlmClient(request.ntlmConfig, axiosInstance.defaults);
|
||||
@@ -411,10 +411,8 @@ const runSingleRequest = async function (
|
||||
// todo: make this happen in prepare-request.js
|
||||
// interpolate the aws v4 config
|
||||
request.awsv4config.accessKeyId = interpolateString(request.awsv4config.accessKeyId, interpolationOptions);
|
||||
request.awsv4config.secretAccessKey = interpolateString(
|
||||
request.awsv4config.secretAccessKey,
|
||||
interpolationOptions
|
||||
);
|
||||
request.awsv4config.secretAccessKey = interpolateString(request.awsv4config.secretAccessKey,
|
||||
interpolationOptions);
|
||||
request.awsv4config.sessionToken = interpolateString(request.awsv4config.sessionToken, interpolationOptions);
|
||||
request.awsv4config.service = interpolateString(request.awsv4config.service, interpolationOptions);
|
||||
request.awsv4config.region = interpolateString(request.awsv4config.region, interpolationOptions);
|
||||
@@ -441,7 +439,7 @@ const runSingleRequest = async function (
|
||||
responseTime = response.headers.get('request-duration');
|
||||
response.headers.delete('request-duration');
|
||||
|
||||
//save cookies if enabled
|
||||
// save cookies if enabled
|
||||
if (!options.disableCookies) {
|
||||
saveCookies(request.url, response.headers);
|
||||
}
|
||||
@@ -459,13 +457,13 @@ const runSingleRequest = async function (
|
||||
console.log(chalk.red(stripExtension(relativeItemPathname)) + chalk.dim(` (${err.message})`));
|
||||
return {
|
||||
test: {
|
||||
filename: relativeItemPathname
|
||||
filename: relativeItemPathname,
|
||||
},
|
||||
request: {
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
headers: request.headers,
|
||||
data: request.data
|
||||
data: request.data,
|
||||
},
|
||||
response: {
|
||||
status: 'error',
|
||||
@@ -473,16 +471,16 @@ const runSingleRequest = async function (
|
||||
headers: null,
|
||||
data: null,
|
||||
url: null,
|
||||
responseTime: 0
|
||||
responseTime: 0,
|
||||
},
|
||||
error: err?.message || err?.errors?.map((e) => e?.message)?.at(0) || err?.code || 'Request Failed!',
|
||||
error: err?.message || err?.errors?.map(e => e?.message)?.at(0) || err?.code || 'Request Failed!',
|
||||
status: 'error',
|
||||
assertionResults: [],
|
||||
testResults: [],
|
||||
preRequestTestResults,
|
||||
postResponseTestResults,
|
||||
nextRequestName: nextRequestName,
|
||||
shouldStopRunnerExecution
|
||||
shouldStopRunnerExecution,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ const collectionBruToJson = (bru) => {
|
||||
const sequence = _.get(json, 'meta.seq');
|
||||
if (json?.meta) {
|
||||
transformedJson.meta = {
|
||||
name: json.meta.name
|
||||
name: json.meta.name,
|
||||
};
|
||||
|
||||
if (sequence) {
|
||||
@@ -101,9 +101,9 @@ const bruToJson = (bru) => {
|
||||
grpc: [
|
||||
{
|
||||
name: 'message 1',
|
||||
content: '{}'
|
||||
}
|
||||
]
|
||||
content: '{}',
|
||||
},
|
||||
],
|
||||
});
|
||||
} else if (requestType === 'ws-request') {
|
||||
transformedJson.request.auth.mode = _.get(json, 'ws.auth', 'none');
|
||||
|
||||
@@ -24,7 +24,7 @@ const {
|
||||
safeStringifyJSON,
|
||||
safeParseJSON,
|
||||
parseDataFromResponse,
|
||||
parseDataFromRequest
|
||||
parseDataFromRequest,
|
||||
} = require('../../utils/common');
|
||||
const { chooseFileToSave, writeBinaryFile, writeFile } = require('../../utils/filesystem');
|
||||
const { addCookieToJar, getDomainsWithCookies, getCookieStringForUrl } = require('../../utils/cookies');
|
||||
@@ -36,13 +36,13 @@ const {
|
||||
getEnvVars,
|
||||
getTreePathFromCollectionToItem,
|
||||
mergeVars,
|
||||
sortByNameThenSequence
|
||||
sortByNameThenSequence,
|
||||
} = require('../../utils/collection');
|
||||
const {
|
||||
getOAuth2TokenUsingAuthorizationCode,
|
||||
getOAuth2TokenUsingClientCredentials,
|
||||
getOAuth2TokenUsingPasswordCredentials,
|
||||
getOAuth2TokenUsingImplicitGrant
|
||||
getOAuth2TokenUsingImplicitGrant,
|
||||
} = require('../../utils/oauth2');
|
||||
const { preferencesUtil } = require('../../store/preferences');
|
||||
const { getProcessEnvVars } = require('../../store/process-env');
|
||||
@@ -132,7 +132,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid, certsAndProxyConfig }));
|
||||
request.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -140,7 +140,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
collectionUid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header' && credentials?.access_token) {
|
||||
request.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials.access_token}`.trim();
|
||||
@@ -158,7 +158,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingImplicitGrant({ request: requestCopy, collectionUid }));
|
||||
request.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -166,7 +166,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
collectionUid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header') {
|
||||
request.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
|
||||
@@ -184,7 +184,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid, certsAndProxyConfig }));
|
||||
request.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -192,7 +192,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
collectionUid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header' && credentials?.access_token) {
|
||||
request.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials.access_token}`.trim();
|
||||
@@ -210,7 +210,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid, certsAndProxyConfig }));
|
||||
request.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -218,7 +218,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
collectionUid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header' && credentials?.access_token) {
|
||||
request.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials.access_token}`.trim();
|
||||
@@ -249,11 +249,11 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
if (preferencesUtil.shouldSendCookies()) {
|
||||
const cookieString = getCookieStringForUrl(request.url);
|
||||
if (cookieString && typeof cookieString === 'string' && cookieString.length) {
|
||||
const existingCookieHeaderName = Object.keys(request.headers).find((name) => name.toLowerCase() === 'cookie');
|
||||
const existingCookieHeaderName = Object.keys(request.headers).find(name => name.toLowerCase() === 'cookie');
|
||||
const existingCookieString = existingCookieHeaderName ? request.headers[existingCookieHeaderName] : '';
|
||||
|
||||
// Helper function to parse cookies into an object
|
||||
const parseCookies = (str) =>
|
||||
const parseCookies = str =>
|
||||
str.split(';').reduce((cookies, cookie) => {
|
||||
const [name, ...rest] = cookie.split('=');
|
||||
if (name && name.trim()) {
|
||||
@@ -264,7 +264,7 @@ const configureRequest = async (collectionUid, request, envVars, runtimeVariable
|
||||
|
||||
const mergedCookies = {
|
||||
...parseCookies(existingCookieString),
|
||||
...parseCookies(cookieString)
|
||||
...parseCookies(cookieString),
|
||||
};
|
||||
|
||||
const combinedCookieString = Object.entries(mergedCookies)
|
||||
@@ -381,12 +381,12 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
channel, // 'main:run-request-event' | 'main:run-folder-event'
|
||||
basePayload, // request-level or runner-level identifiers
|
||||
scriptType, // 'pre-request' | 'post-response' | 'test'
|
||||
error // optional Error
|
||||
error, // optional Error
|
||||
}) => {
|
||||
mainWindow.webContents.send(channel, {
|
||||
type: `${scriptType}-script-execution`,
|
||||
...basePayload,
|
||||
errorMessage: error ? error.message || `An error occurred in ${scriptType.replace('-', ' ')} script` : null
|
||||
errorMessage: error ? error.message || `An error occurred in ${scriptType.replace('-', ' ')} script` : null,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -578,7 +578,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
envVars,
|
||||
processEnvVars,
|
||||
runtimeVariables,
|
||||
runInBackground = false
|
||||
runInBackground = false,
|
||||
}) => {
|
||||
const collectionUid = collection.uid;
|
||||
const collectionPath = collection.pathname;
|
||||
@@ -600,7 +600,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
envVars,
|
||||
processEnvVars,
|
||||
runtimeVariables,
|
||||
runInBackground: true
|
||||
runInBackground: true,
|
||||
});
|
||||
resolve(res);
|
||||
}
|
||||
@@ -608,14 +608,14 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
};
|
||||
|
||||
!runInBackground &&
|
||||
mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'request-queued',
|
||||
requestUid,
|
||||
collectionUid,
|
||||
itemUid: item.uid,
|
||||
cancelTokenUid
|
||||
});
|
||||
!runInBackground
|
||||
&& mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'request-queued',
|
||||
requestUid,
|
||||
collectionUid,
|
||||
itemUid: item.uid,
|
||||
cancelTokenUid,
|
||||
});
|
||||
|
||||
const abortController = new AbortController();
|
||||
const request = await prepareRequest(item, collection, abortController);
|
||||
@@ -657,13 +657,13 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
}
|
||||
|
||||
!runInBackground &&
|
||||
notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'pre-request',
|
||||
error: preRequestError
|
||||
});
|
||||
!runInBackground
|
||||
&& notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'pre-request',
|
||||
error: preRequestError,
|
||||
});
|
||||
|
||||
if (preRequestError) {
|
||||
return Promise.reject(preRequestError);
|
||||
@@ -686,15 +686,15 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
dataBuffer: requestDataBuffer
|
||||
};
|
||||
|
||||
!runInBackground &&
|
||||
mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'request-sent',
|
||||
requestSent,
|
||||
collectionUid,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
cancelTokenUid
|
||||
});
|
||||
!runInBackground
|
||||
&& mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'request-sent',
|
||||
requestSent,
|
||||
collectionUid,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
cancelTokenUid,
|
||||
});
|
||||
|
||||
if (request?.oauth2Credentials) {
|
||||
mainWindow.webContents.send('main:credentials-update', {
|
||||
@@ -705,7 +705,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
...(request?.oauth2Credentials?.folderUid
|
||||
? { folderUid: request.oauth2Credentials.folderUid }
|
||||
: { itemUid: item.uid }),
|
||||
debugInfo: request?.oauth2Credentials?.debugInfo
|
||||
debugInfo: request?.oauth2Credentials?.debugInfo,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -801,13 +801,13 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
}
|
||||
|
||||
!runInBackground &&
|
||||
notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'post-response',
|
||||
error: postResponseError
|
||||
});
|
||||
!runInBackground
|
||||
&& notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'post-response',
|
||||
error: postResponseError,
|
||||
});
|
||||
|
||||
// run assertions
|
||||
const assertions = get(request, 'assertions');
|
||||
@@ -822,14 +822,14 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
processEnvVars
|
||||
);
|
||||
|
||||
!runInBackground &&
|
||||
mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'assertion-results',
|
||||
results: results,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
collectionUid
|
||||
});
|
||||
!runInBackground
|
||||
&& mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'assertion-results',
|
||||
results: results,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
collectionUid,
|
||||
});
|
||||
}
|
||||
|
||||
const testFile = get(request, 'tests');
|
||||
@@ -870,14 +870,14 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
}
|
||||
}
|
||||
|
||||
!runInBackground &&
|
||||
mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'test-results',
|
||||
results: testResults.results,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
collectionUid
|
||||
});
|
||||
!runInBackground
|
||||
&& mainWindow.webContents.send('main:run-request-event', {
|
||||
type: 'test-results',
|
||||
results: testResults.results,
|
||||
itemUid: item.uid,
|
||||
requestUid,
|
||||
collectionUid,
|
||||
});
|
||||
|
||||
mainWindow.webContents.send('main:script-environment-update', {
|
||||
envVariables: testResults.envVariables,
|
||||
@@ -897,13 +897,13 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
|
||||
collection.globalEnvironmentVariables = testResults.globalEnvironmentVariables;
|
||||
|
||||
!runInBackground &&
|
||||
notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'test',
|
||||
error: testError
|
||||
});
|
||||
!runInBackground
|
||||
&& notifyScriptExecution({
|
||||
channel: 'main:run-request-event',
|
||||
basePayload: { requestUid, collectionUid, itemUid: item.uid },
|
||||
scriptType: 'test',
|
||||
error: testError,
|
||||
});
|
||||
|
||||
const domainsWithCookiesTest = await getDomainsWithCookies();
|
||||
mainWindow.webContents.send('main:cookies-update', safeParseJSON(safeStringifyJSON(domainsWithCookiesTest)));
|
||||
@@ -1000,7 +1000,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
envVars,
|
||||
processEnvVars,
|
||||
runtimeVariables,
|
||||
runInBackground: true
|
||||
runInBackground: true,
|
||||
});
|
||||
resolve(res);
|
||||
}
|
||||
@@ -1136,10 +1136,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
|
||||
const domainsWithCookiesPreRequest = await getDomainsWithCookies();
|
||||
mainWindow.webContents.send(
|
||||
'main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesPreRequest))
|
||||
);
|
||||
mainWindow.webContents.send('main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesPreRequest)));
|
||||
|
||||
if (preRequestError) {
|
||||
throw preRequestError;
|
||||
@@ -1207,7 +1205,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
...(request?.oauth2Credentials?.folderUid
|
||||
? { folderUid: request.oauth2Credentials.folderUid }
|
||||
: { itemUid: item.uid }),
|
||||
debugInfo: request?.oauth2Credentials?.debugInfo
|
||||
debugInfo: request?.oauth2Credentials?.debugInfo,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1260,9 +1258,9 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
timeline: response.timeline,
|
||||
url: response.request
|
||||
? response.request.protocol + '//' + response.request.host + response.request.path
|
||||
: null
|
||||
: null,
|
||||
},
|
||||
...eventData
|
||||
...eventData,
|
||||
});
|
||||
} catch (error) {
|
||||
// Skip further processing if request was cancelled
|
||||
@@ -1287,7 +1285,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
size: Buffer.byteLength(dataBuffer),
|
||||
data: error.response.data,
|
||||
responseTime: error.response.responseTime,
|
||||
timeline: error.response.timeline
|
||||
timeline: error.response.timeline,
|
||||
};
|
||||
|
||||
// if we get a response from the server, we consider it as a success
|
||||
@@ -1334,10 +1332,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
|
||||
const domainsWithCookiesPostResponse = await getDomainsWithCookies();
|
||||
mainWindow.webContents.send(
|
||||
'main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesPostResponse))
|
||||
);
|
||||
mainWindow.webContents.send('main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesPostResponse)));
|
||||
|
||||
if (postResponseScriptResult?.nextRequestName !== undefined) {
|
||||
nextRequestName = postResponseScriptResult.nextRequestName;
|
||||
@@ -1445,10 +1441,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
|
||||
const domainsWithCookiesTest = await getDomainsWithCookies();
|
||||
mainWindow.webContents.send(
|
||||
'main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesTest))
|
||||
);
|
||||
mainWindow.webContents.send('main:cookies-update',
|
||||
safeParseJSON(safeStringifyJSON(domainsWithCookiesTest)));
|
||||
}
|
||||
} catch (error) {
|
||||
mainWindow.webContents.send('main:run-folder-event', {
|
||||
|
||||
@@ -12,13 +12,13 @@ const {
|
||||
mergeScripts,
|
||||
mergeVars,
|
||||
mergeAuth,
|
||||
getFormattedCollectionOauth2Credentials
|
||||
getFormattedCollectionOauth2Credentials,
|
||||
} = require('../../utils/collection');
|
||||
const { getProcessEnvVars } = require('../../store/process-env');
|
||||
const {
|
||||
getOAuth2TokenUsingPasswordCredentials,
|
||||
getOAuth2TokenUsingClientCredentials,
|
||||
getOAuth2TokenUsingAuthorizationCode
|
||||
getOAuth2TokenUsingAuthorizationCode,
|
||||
} = require('../../utils/oauth2');
|
||||
const { interpolateString } = require('./interpolate-string');
|
||||
const path = require('node:path');
|
||||
@@ -29,13 +29,13 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
const collectionRoot = collection?.draft ? get(collection, 'draft', {}) : get(collection, 'root', {});
|
||||
const headers = {};
|
||||
|
||||
each(get(collectionRoot, 'request.headers', []), (h) => {
|
||||
each(get(collectionRoot, 'request.headers', []), h => {
|
||||
if (h.enabled && h.name?.toLowerCase() === 'content-type') {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
each(get(request, 'headers', []), (h) => {
|
||||
each(get(request, 'headers', []), h => {
|
||||
if (h.enabled) {
|
||||
headers[h.name] = h.value;
|
||||
}
|
||||
@@ -58,7 +58,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
folderVariables: request.folderVariables,
|
||||
requestVariables: request.requestVariables,
|
||||
globalEnvironmentVariables: request.globalEnvironmentVariables,
|
||||
oauth2CredentialVariables: request.oauth2CredentialVariables
|
||||
oauth2CredentialVariables: request.oauth2CredentialVariables,
|
||||
};
|
||||
|
||||
wsRequest = setAuthHeaders(wsRequest, request, collection);
|
||||
@@ -75,11 +75,11 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingAuthorizationCode({
|
||||
request: requestCopy,
|
||||
collectionUid: collection.uid,
|
||||
certsAndProxyConfig
|
||||
certsAndProxyConfig,
|
||||
}));
|
||||
wsRequest.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -87,7 +87,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
collectionUid: collection.uid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header') {
|
||||
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
|
||||
@@ -105,11 +105,11 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingClientCredentials({
|
||||
request: requestCopy,
|
||||
collectionUid: collection.uid,
|
||||
certsAndProxyConfig
|
||||
certsAndProxyConfig,
|
||||
}));
|
||||
wsRequest.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -117,7 +117,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
collectionUid: collection.uid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header') {
|
||||
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
|
||||
@@ -135,11 +135,11 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
credentials,
|
||||
url: oauth2Url,
|
||||
credentialsId,
|
||||
debugInfo
|
||||
debugInfo,
|
||||
} = await getOAuth2TokenUsingPasswordCredentials({
|
||||
request: requestCopy,
|
||||
collectionUid: collection.uid,
|
||||
certsAndProxyConfig
|
||||
certsAndProxyConfig,
|
||||
}));
|
||||
wsRequest.oauth2Credentials = {
|
||||
credentials,
|
||||
@@ -147,7 +147,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables,
|
||||
collectionUid: collection.uid,
|
||||
credentialsId,
|
||||
debugInfo,
|
||||
folderUid: request.oauth2Credentials?.folderUid
|
||||
folderUid: request.oauth2Credentials?.folderUid,
|
||||
};
|
||||
if (tokenPlacement == 'header') {
|
||||
wsRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
|
||||
@@ -173,7 +173,7 @@ let wsClient;
|
||||
/**
|
||||
* Register IPC handlers for WebSocket
|
||||
*/
|
||||
const registerWsEventHandlers = (window) => {
|
||||
const registerWsEventHandlers = window => {
|
||||
const sendEvent = (eventName, ...args) => {
|
||||
if (window && window.webContents) {
|
||||
window.webContents.send(eventName, ...args);
|
||||
@@ -184,13 +184,12 @@ const registerWsEventHandlers = (window) => {
|
||||
|
||||
wsClient = new WsClient(sendEvent);
|
||||
|
||||
ipcMain.handle('ws:connections-changed', (event) => {
|
||||
ipcMain.handle('ws:connections-changed', event => {
|
||||
sendEvent('ws:connections-changed', event);
|
||||
});
|
||||
|
||||
// Start a new WebSocket connection
|
||||
ipcMain.handle(
|
||||
'ws:start-connection',
|
||||
ipcMain.handle('ws:start-connection',
|
||||
async (event, { request, collection, environment, runtimeVariables, settings, options = {} }) => {
|
||||
try {
|
||||
const requestCopy = cloneDeep(request);
|
||||
@@ -201,13 +200,13 @@ const registerWsEventHandlers = (window) => {
|
||||
url: preparedRequest.url,
|
||||
headers: preparedRequest.headers,
|
||||
body: preparedRequest.body,
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
if (!connectOnly) {
|
||||
const hasMessages = preparedRequest.body.ws.some((msg) => msg.content.length);
|
||||
const hasMessages = preparedRequest.body.ws.some(msg => msg.content.length);
|
||||
if (hasMessages) {
|
||||
preparedRequest.body.ws.forEach((message) => {
|
||||
preparedRequest.body.ws.forEach(message => {
|
||||
wsClient.queueMessage(preparedRequest.uid, collection.uid, message.content);
|
||||
});
|
||||
}
|
||||
@@ -220,8 +219,8 @@ const registerWsEventHandlers = (window) => {
|
||||
options: {
|
||||
timeout: settings.connectionTimeout,
|
||||
keepAlive: settings.keepAliveInterval > 0 ? true : false,
|
||||
keepAliveInterval: settings.keepAliveInterval
|
||||
}
|
||||
keepAliveInterval: settings.keepAliveInterval,
|
||||
},
|
||||
});
|
||||
|
||||
sendEvent('ws:request', preparedRequest.uid, collection.uid, requestSent);
|
||||
@@ -236,7 +235,7 @@ const registerWsEventHandlers = (window) => {
|
||||
...(preparedRequest.oauth2Credentials?.folderUid
|
||||
? { folderUid: preparedRequest.oauth2Credentials.folderUid }
|
||||
: { itemUid: preparedRequest.uid }),
|
||||
debugInfo: preparedRequest.oauth2Credentials.debugInfo
|
||||
debugInfo: preparedRequest.oauth2Credentials.debugInfo,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -249,11 +248,10 @@ const registerWsEventHandlers = (window) => {
|
||||
sendEvent('ws:error', request.uid, collection.uid, { error: error.message });
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Get all active connection IDs
|
||||
ipcMain.handle('ws:get-active-connections', (event) => {
|
||||
ipcMain.handle('ws:get-active-connections', event => {
|
||||
try {
|
||||
const activeConnectionIds = wsClient.getActiveConnectionIds();
|
||||
return { success: true, activeConnectionIds };
|
||||
@@ -309,5 +307,5 @@ const registerWsEventHandlers = (window) => {
|
||||
|
||||
module.exports = {
|
||||
registerWsEventHandlers,
|
||||
wsClient
|
||||
wsClient,
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ export const bruRequestToJson = (data: string | any, parsed: boolean = false): a
|
||||
const urlPath: Record<typeof requestType, string> = {
|
||||
'grpc-request': 'grpc.url',
|
||||
'ws-request': 'ws.url',
|
||||
default: 'http.url'
|
||||
'default': 'http.url',
|
||||
};
|
||||
const transformedJson = {
|
||||
type: requestType,
|
||||
@@ -192,9 +192,9 @@ export const jsonRequestToBru = (json: any): string => {
|
||||
ws: _.get(json, 'request.body.ws', [
|
||||
{
|
||||
name: 'message 1',
|
||||
content: '{}'
|
||||
}
|
||||
])
|
||||
content: '{}',
|
||||
},
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -283,16 +283,16 @@ const mapPairListToKeyValPair = (pairList = []) => {
|
||||
* @param {Record<unknown,unknown>} obj
|
||||
* @returns {(key:string, opts?:{fallback: number })=>number|undefined}
|
||||
*/
|
||||
const createGetNumFromRecord =
|
||||
(obj) =>
|
||||
(key, { fallback } = {}) => {
|
||||
if (!(key in obj)) return fallback;
|
||||
const asNumber = typeof obj[key] === 'number' ? obj[key] : Number(obj[key]);
|
||||
if (isNaN(asNumber)) {
|
||||
return fallback;
|
||||
}
|
||||
return asNumber;
|
||||
};
|
||||
const createGetNumFromRecord
|
||||
= obj =>
|
||||
(key, { fallback } = {}) => {
|
||||
if (!(key in obj)) return fallback;
|
||||
const asNumber = typeof obj[key] === 'number' ? obj[key] : Number(obj[key]);
|
||||
if (isNaN(asNumber)) {
|
||||
return fallback;
|
||||
}
|
||||
return asNumber;
|
||||
};
|
||||
|
||||
const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
BruFile(tags) {
|
||||
@@ -434,12 +434,12 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
const getNumFromRecord = createGetNumFromRecord(settings);
|
||||
const keepAliveInterval = getNumFromRecord('keepAliveInterval');
|
||||
const connectionTimeout = getNumFromRecord('connectionTimeout');
|
||||
|
||||
|
||||
if (keepAliveInterval || connectionTimeout) {
|
||||
result.settings.keepAliveInterval = keepAliveInterval;
|
||||
result.settings.connectionTimeout = connectionTimeout;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
},
|
||||
grpc(_1, dictionary) {
|
||||
@@ -449,7 +449,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
},
|
||||
ws(_1, dictionary) {
|
||||
return {
|
||||
ws: mapPairListToKeyValPair(dictionary.ast)
|
||||
ws: mapPairListToKeyValPair(dictionary.ast),
|
||||
};
|
||||
},
|
||||
get(_1, dictionary) {
|
||||
@@ -991,10 +991,10 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
grpc: [
|
||||
{
|
||||
name: messageName,
|
||||
content: '{}'
|
||||
}
|
||||
]
|
||||
}
|
||||
content: '{}',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1004,10 +1004,10 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
grpc: [
|
||||
{
|
||||
name: messageName,
|
||||
content: messageContent
|
||||
}
|
||||
]
|
||||
}
|
||||
content: messageContent,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,11 +2,11 @@ const _ = require('lodash');
|
||||
|
||||
const { indentString, getValueString } = require('./utils');
|
||||
|
||||
const enabled = (items = [], key = 'enabled') => items.filter((item) => item[key]);
|
||||
const disabled = (items = [], key = 'enabled') => items.filter((item) => !item[key]);
|
||||
const enabled = (items = [], key = 'enabled') => items.filter(item => item[key]);
|
||||
const disabled = (items = [], key = 'enabled') => items.filter(item => !item[key]);
|
||||
const quoteKey = (key) => {
|
||||
const quotableChars = [':', '"', '{', '}', ' '];
|
||||
return quotableChars.some((char) => key.includes(char)) ? '"' + key.replaceAll('"', '\\"') + '"' : key;
|
||||
return quotableChars.some(char => key.includes(char)) ? ('"' + key.replaceAll('"', '\\"') + '"') : key;
|
||||
};
|
||||
|
||||
// remove the last line if two new lines are found
|
||||
@@ -17,7 +17,8 @@ const stripLastLine = (text) => {
|
||||
};
|
||||
|
||||
const jsonToBru = (json) => {
|
||||
const { meta, http, grpc, ws, params, headers, metadata, auth, body, script, tests, vars, assertions, settings, docs } = json;
|
||||
const { meta, http, grpc, params, headers, metadata, auth, body, script, tests, vars, assertions, settings, docs } = json;
|
||||
|
||||
|
||||
let bru = '';
|
||||
|
||||
@@ -97,35 +98,6 @@ const jsonToBru = (json) => {
|
||||
`;
|
||||
}
|
||||
|
||||
if (ws && ws.url) {
|
||||
bru += `ws {
|
||||
url: ${ws.url}`;
|
||||
|
||||
if (ws.method && ws.method.length) {
|
||||
bru += `
|
||||
method: ${ws.method}`;
|
||||
}
|
||||
|
||||
if (ws.body && ws.body.length) {
|
||||
bru += `
|
||||
body: ${ws.body}`;
|
||||
}
|
||||
|
||||
if (ws.auth && ws.auth.length) {
|
||||
bru += `
|
||||
auth: ${ws.auth}`;
|
||||
}
|
||||
|
||||
if (ws.methodType && ws.methodType.length) {
|
||||
bru += `
|
||||
methodType: ${ws.methodType}`;
|
||||
}
|
||||
|
||||
bru += `
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (params && params.length) {
|
||||
const queryParams = params.filter((param) => param.type === 'query');
|
||||
@@ -277,14 +249,10 @@ ${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header'
|
||||
? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`)
|
||||
: ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header'
|
||||
? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`)
|
||||
: ''
|
||||
}
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`auto_fetch_token: ${(auth?.oauth2?.autoFetchToken ?? true).toString()}`)}
|
||||
${indentString(`auto_refresh_token: ${(auth?.oauth2?.autoRefreshToken ?? false).toString()}`)}
|
||||
}
|
||||
@@ -306,14 +274,10 @@ ${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header'
|
||||
? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`)
|
||||
: ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header'
|
||||
? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`)
|
||||
: ''
|
||||
}
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`auto_fetch_token: ${(auth?.oauth2?.autoFetchToken ?? true).toString()}`)}
|
||||
${indentString(`auto_refresh_token: ${(auth?.oauth2?.autoRefreshToken ?? false).toString()}`)}
|
||||
}
|
||||
@@ -331,14 +295,10 @@ ${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`credentials_placement: ${auth?.oauth2?.credentialsPlacement || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header'
|
||||
? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`)
|
||||
: ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header'
|
||||
? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`)
|
||||
: ''
|
||||
}
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`auto_fetch_token: ${(auth?.oauth2?.autoFetchToken ?? true).toString()}`)}
|
||||
${indentString(`auto_refresh_token: ${(auth?.oauth2?.autoRefreshToken ?? false).toString()}`)}
|
||||
}
|
||||
@@ -355,14 +315,10 @@ ${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
|
||||
${indentString(`credentials_id: ${auth?.oauth2?.credentialsId || ''}`)}
|
||||
${indentString(`token_placement: ${auth?.oauth2?.tokenPlacement || ''}`)}${
|
||||
auth?.oauth2?.tokenPlacement == 'header'
|
||||
? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`)
|
||||
: ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header'
|
||||
? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`)
|
||||
: ''
|
||||
}
|
||||
auth?.oauth2?.tokenPlacement == 'header' ? '\n' + indentString(`token_header_prefix: ${auth?.oauth2?.tokenHeaderPrefix || ''}`) : ''
|
||||
}${
|
||||
auth?.oauth2?.tokenPlacement !== 'header' ? '\n' + indentString(`token_query_key: ${auth?.oauth2?.tokenQueryKey || ''}`) : ''
|
||||
}
|
||||
${indentString(`auto_fetch_token: ${(auth?.oauth2?.autoFetchToken ?? true).toString()}`)}
|
||||
}
|
||||
|
||||
@@ -371,111 +327,96 @@ ${indentString(`auto_fetch_token: ${(auth?.oauth2?.autoFetchToken ?? true).toStr
|
||||
}
|
||||
|
||||
if (auth?.oauth2?.additionalParameters) {
|
||||
const {
|
||||
authorization: authorizationParams,
|
||||
token: tokenParams,
|
||||
refresh: refreshParams
|
||||
} = auth?.oauth2?.additionalParameters;
|
||||
const authorizationHeaders = authorizationParams?.filter((p) => p?.sendIn == 'headers');
|
||||
const { authorization: authorizationParams, token: tokenParams, refresh: refreshParams } = auth?.oauth2?.additionalParameters;
|
||||
const authorizationHeaders = authorizationParams?.filter(p => p?.sendIn == 'headers');
|
||||
if (authorizationHeaders?.length) {
|
||||
bru += `auth:oauth2:additional_params:auth_req:headers {
|
||||
${indentString(
|
||||
authorizationHeaders
|
||||
.filter((item) => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.filter(item => item?.name?.length)
|
||||
.map(item => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const authorizationQueryParams = authorizationParams?.filter((p) => p?.sendIn == 'queryparams');
|
||||
const authorizationQueryParams = authorizationParams?.filter(p => p?.sendIn == 'queryparams');
|
||||
if (authorizationQueryParams?.length) {
|
||||
bru += `auth:oauth2:additional_params:auth_req:queryparams {
|
||||
${indentString(
|
||||
authorizationQueryParams
|
||||
.filter((item) => item?.name?.length)
|
||||
.filter(item => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const tokenHeaders = tokenParams?.filter((p) => p?.sendIn == 'headers');
|
||||
const tokenHeaders = tokenParams?.filter(p => p?.sendIn == 'headers');
|
||||
if (tokenHeaders?.length) {
|
||||
bru += `auth:oauth2:additional_params:access_token_req:headers {
|
||||
${indentString(
|
||||
tokenHeaders
|
||||
.filter((item) => item?.name?.length)
|
||||
${indentString(tokenHeaders
|
||||
.filter(item => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const tokenQueryParams = tokenParams?.filter((p) => p?.sendIn == 'queryparams');
|
||||
const tokenQueryParams = tokenParams?.filter(p => p?.sendIn == 'queryparams');
|
||||
if (tokenQueryParams?.length) {
|
||||
bru += `auth:oauth2:additional_params:access_token_req:queryparams {
|
||||
${indentString(
|
||||
tokenQueryParams
|
||||
.filter((item) => item?.name?.length)
|
||||
.filter(item => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const tokenBodyValues = tokenParams?.filter((p) => p?.sendIn == 'body');
|
||||
const tokenBodyValues = tokenParams?.filter(p => p?.sendIn == 'body');
|
||||
if (tokenBodyValues?.length) {
|
||||
bru += `auth:oauth2:additional_params:access_token_req:body {
|
||||
${indentString(
|
||||
tokenBodyValues
|
||||
.filter((item) => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.filter(item => item?.name?.length)
|
||||
.map(item => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const refreshHeaders = refreshParams?.filter((p) => p?.sendIn == 'headers');
|
||||
const refreshHeaders = refreshParams?.filter(p => p?.sendIn == 'headers');
|
||||
if (refreshHeaders?.length) {
|
||||
bru += `auth:oauth2:additional_params:refresh_token_req:headers {
|
||||
${indentString(
|
||||
refreshHeaders
|
||||
.filter((item) => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.filter(item => item?.name?.length)
|
||||
.map(item => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const refreshQueryParams = refreshParams?.filter((p) => p?.sendIn == 'queryparams');
|
||||
const refreshQueryParams = refreshParams?.filter(p => p?.sendIn == 'queryparams');
|
||||
if (refreshQueryParams?.length) {
|
||||
bru += `auth:oauth2:additional_params:refresh_token_req:queryparams {
|
||||
${indentString(
|
||||
refreshQueryParams
|
||||
.filter((item) => item?.name?.length)
|
||||
${indentString(refreshQueryParams
|
||||
.filter(item => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
const refreshBodyValues = refreshParams?.filter((p) => p?.sendIn == 'body');
|
||||
const refreshBodyValues = refreshParams?.filter(p => p?.sendIn == 'body');
|
||||
if (refreshBodyValues?.length) {
|
||||
bru += `auth:oauth2:additional_params:refresh_token_req:body {
|
||||
${indentString(
|
||||
refreshBodyValues
|
||||
.filter((item) => item?.name?.length)
|
||||
.map((item) => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}
|
||||
${indentString(refreshBodyValues
|
||||
.filter(item => item?.name?.length)
|
||||
.map(item => `${item.enabled ? '' : '~'}${item.name}: ${item.value}`)
|
||||
.join('\n'))}
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -585,8 +526,8 @@ ${indentString(body.sparql)}
|
||||
files
|
||||
.map((item) => {
|
||||
const selected = item.selected ? '' : '~';
|
||||
const contentType =
|
||||
item.contentType && item.contentType !== '' ? ' @contentType(' + item.contentType + ')' : '';
|
||||
const contentType
|
||||
= item.contentType && item.contentType !== '' ? ' @contentType(' + item.contentType + ')' : '';
|
||||
const filePath = item.filePath || '';
|
||||
const value = `@file(${filePath})`;
|
||||
const itemName = 'file';
|
||||
|
||||
@@ -28,15 +28,15 @@ module.exports = [
|
||||
peerDepsExternal(),
|
||||
nodeResolve({
|
||||
extensions: ['.js', '.ts', '.tsx', '.json', '.css'],
|
||||
dedupe: ['@grpc/grpc-js', 'ws'],
|
||||
preferBuiltins: true
|
||||
dedupe: ['@grpc/grpc-js'],
|
||||
preferBuiltins: true,
|
||||
}),
|
||||
json(),
|
||||
commonjs({
|
||||
transformMixedEsModules: true
|
||||
}),
|
||||
typescript({ tsconfig: './tsconfig.json' }),
|
||||
terser()
|
||||
terser(),
|
||||
],
|
||||
external: ['axios', 'qs', 'ws']
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const safeJsonParse = (jsonString, context = 'JSON string') => {
|
||||
const errorMessage = `Failed to parse ${context}: ${error.message}`;
|
||||
console.error(errorMessage, {
|
||||
originalString: jsonString,
|
||||
parseError: error
|
||||
parseError: error,
|
||||
});
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
@@ -26,8 +26,8 @@ const safeJsonParse = (jsonString, context = 'JSON string') => {
|
||||
* @param {string} url - The WebSocket URL
|
||||
* @returns {Object} Parsed URL object with protocol, host, path
|
||||
*/
|
||||
const getParsedWsUrlObject = (url) => {
|
||||
const addProtocolIfMissing = (str) => {
|
||||
const getParsedWsUrlObject = url => {
|
||||
const addProtocolIfMissing = str => {
|
||||
if (str.includes('://')) return str;
|
||||
|
||||
// For localhost, default to insecure (grpc://) for local development
|
||||
@@ -39,7 +39,7 @@ const getParsedWsUrlObject = (url) => {
|
||||
return `wss://${str}`;
|
||||
};
|
||||
|
||||
const removeTrailingSlash = (str) => (str.endsWith('/') ? str.slice(0, -1) : str);
|
||||
const removeTrailingSlash = str => (str.endsWith('/') ? str.slice(0, -1) : str);
|
||||
|
||||
if (!url) return { host: '', path: '' };
|
||||
|
||||
@@ -50,13 +50,13 @@ const getParsedWsUrlObject = (url) => {
|
||||
host: urlObj.host,
|
||||
path: removeTrailingSlash(urlObj.pathname),
|
||||
search: urlObj.search,
|
||||
fullUrl: urlObj.href
|
||||
fullUrl: urlObj.href,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error({ err });
|
||||
return {
|
||||
host: '',
|
||||
path: ''
|
||||
path: '',
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -91,7 +91,7 @@ class WsClient {
|
||||
const wsConnection = new ws.WebSocket(parsedUrl.fullUrl, {
|
||||
headers,
|
||||
handshakeTimeout: timeout,
|
||||
followRedirects: true
|
||||
followRedirects: true,
|
||||
});
|
||||
|
||||
// Set up event handlers
|
||||
@@ -107,7 +107,7 @@ class WsClient {
|
||||
} catch (error) {
|
||||
console.error('Error creating WebSocket connection:', error);
|
||||
this.eventCallback('ws:error', requestId, collectionUid, {
|
||||
error: error.message
|
||||
error: error.message,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ class WsClient {
|
||||
}
|
||||
|
||||
// Send the message
|
||||
connection.send(JSON.stringify(messageToSend), (error) => {
|
||||
connection.send(JSON.stringify(messageToSend), error => {
|
||||
if (error) {
|
||||
this.eventCallback('ws:error', requestId, collectionUid, { error });
|
||||
} else {
|
||||
@@ -171,14 +171,14 @@ class WsClient {
|
||||
message: messageToSend,
|
||||
messageHexdump: hexdump(JSON.stringify(messageToSend)),
|
||||
type: 'outgoing',
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const error = new Error('WebSocket connection not available or not open');
|
||||
this.eventCallback('ws:error', requestId, collectionUid, {
|
||||
error: error.message
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class WsClient {
|
||||
clearAllConnections() {
|
||||
const connectionIds = this.getActiveConnectionIds();
|
||||
|
||||
this.activeConnections.forEach((connection) => {
|
||||
this.activeConnections.forEach(connection => {
|
||||
if (connection.readyState === WebSocket.OPEN) {
|
||||
connection.close(1000, 'Client clearing all connections');
|
||||
}
|
||||
@@ -233,7 +233,7 @@ class WsClient {
|
||||
if (connectionIds.length > 0) {
|
||||
this.eventCallback('ws:connections-changed', {
|
||||
type: 'cleared',
|
||||
activeConnectionIds: []
|
||||
activeConnectionIds: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -264,37 +264,37 @@ class WsClient {
|
||||
|
||||
this.eventCallback('ws:open', requestId, collectionUid, {
|
||||
timestamp: Date.now(),
|
||||
url: ws.url
|
||||
url: ws.url,
|
||||
});
|
||||
});
|
||||
|
||||
ws.on('redirect', (url, req) => {
|
||||
const headerNames = req.getHeaderNames();
|
||||
const headers = Object.fromEntries(headerNames.map((d) => [d, req.getHeader(d)]));
|
||||
const headers = Object.fromEntries(headerNames.map(d => [d, req.getHeader(d)]));
|
||||
this.eventCallback('ws:redirect', requestId, collectionUid, {
|
||||
message: `Redirected to ${url}`,
|
||||
type: 'info',
|
||||
timestamp: Date.now(),
|
||||
headers: headers
|
||||
headers: headers,
|
||||
});
|
||||
});
|
||||
|
||||
ws.on('upgrade', (response) => {
|
||||
ws.on('upgrade', response => {
|
||||
this.eventCallback('ws:upgrade', requestId, collectionUid, {
|
||||
type: 'info',
|
||||
timestamp: Date.now(),
|
||||
headers: { ...response.headers }
|
||||
headers: { ...response.headers },
|
||||
});
|
||||
});
|
||||
|
||||
ws.on('message', (data) => {
|
||||
ws.on('message', data => {
|
||||
try {
|
||||
const message = JSON.parse(data.toString());
|
||||
this.eventCallback('ws:message', requestId, collectionUid, {
|
||||
message,
|
||||
messageHexdump: hexdump(Buffer.from(data)),
|
||||
type: 'incoming',
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
} catch (error) {
|
||||
// If parsing fails, send as raw data
|
||||
@@ -302,7 +302,7 @@ class WsClient {
|
||||
message: data.toString(),
|
||||
messageHexdump: hexdump(data),
|
||||
type: 'incoming',
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -311,15 +311,15 @@ class WsClient {
|
||||
this.eventCallback('ws:close', requestId, collectionUid, {
|
||||
code,
|
||||
reason: Buffer.from(reason).toString(),
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
this.#removeConnection(requestId);
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
ws.on('error', error => {
|
||||
this.eventCallback('ws:error', requestId, collectionUid, {
|
||||
error: error.message,
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -337,7 +337,7 @@ class WsClient {
|
||||
this.eventCallback('ws:connections-changed', {
|
||||
type: 'added',
|
||||
requestId,
|
||||
activeConnectionIds: this.getActiveConnectionIds()
|
||||
activeConnectionIds: this.getActiveConnectionIds(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ class WsClient {
|
||||
this.eventCallback('ws:connections-changed', {
|
||||
type: 'removed',
|
||||
requestId,
|
||||
activeConnectionIds: this.getActiveConnectionIds()
|
||||
activeConnectionIds: this.getActiveConnectionIds(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user