Skip to content

Commit 415414c

Browse files
committed
Add WebSocketRequest to sidebar and update types (#5048)
1 parent c800ece commit 415414c

File tree

12 files changed

+111
-59
lines changed

12 files changed

+111
-59
lines changed

packages/insomnia/src/models/helpers/request-operations.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { GrpcRequest, isGrpcRequest, isGrpcRequestId } from '../grpc-request';
22
import * as models from '../index';
33
import { Request } from '../request';
4+
import { isWebSocketRequest, WebSocketRequest } from '../websocket-request';
45

56
export function getById(requestId: string): Promise<Request | GrpcRequest | null> {
67
return isGrpcRequestId(requestId)
78
? models.grpcRequest.getById(requestId)
89
: models.request.getById(requestId);
910
}
1011

11-
export function remove(request: Request | GrpcRequest) {
12-
return isGrpcRequest(request)
13-
? models.grpcRequest.remove(request)
14-
: models.request.remove(request);
12+
export function remove(request: Request | GrpcRequest | WebSocketRequest) {
13+
if (isGrpcRequest(request)) {
14+
return models.grpcRequest.remove(request);
15+
}
16+
if (isWebSocketRequest(request)) {
17+
return models.websocketRequest.remove(request);
18+
} else {
19+
return models.request.remove(request);
20+
}
1521
}
1622

1723
export function update<T extends object>(request: T, patch: Partial<T> = {}): Promise<T> {

packages/insomnia/src/models/websocket-request.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ export const canSync = false;
1414
export interface BaseWebSocketRequest {
1515
name: string;
1616
url: string;
17+
metaSortKey: number;
1718
}
1819

19-
export type WebSocketRequest = BaseWebSocketRequest & BaseModel;
20+
export type WebSocketRequest = BaseModel & BaseWebSocketRequest & { type: typeof type };
2021

2122
export const isWebSocketRequest = (model: Pick<BaseModel, 'type'>): model is WebSocketRequest => (
2223
model.type === type
@@ -25,6 +26,7 @@ export const isWebSocketRequest = (model: Pick<BaseModel, 'type'>): model is Web
2526
export const init = (): BaseWebSocketRequest => ({
2627
name: 'New WebSocket Request',
2728
url: '',
29+
metaSortKey: -1 * Date.now(),
2830
});
2931

3032
export const migrate = (doc: WebSocketRequest) => doc;

packages/insomnia/src/ui/components/dropdowns/auth-dropdown.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '../../../common/constants';
1818
import * as models from '../../../models';
1919
import { update } from '../../../models/helpers/request-operations';
20+
import { isRequest } from '../../../models/request';
2021
import { selectActiveRequest } from '../../redux/selectors';
2122
import { Dropdown } from '../base/dropdown/dropdown';
2223
import { DropdownButton } from '../base/dropdown/dropdown-button';
@@ -46,8 +47,7 @@ export const AuthDropdown: FC = () => {
4647
return;
4748
}
4849

49-
if (!('authentication' in activeRequest)) {
50-
// gRPC Requests don't have `authentication`
50+
if (!isRequest(activeRequest)) {
5151
return;
5252
}
5353

@@ -86,7 +86,7 @@ export const AuthDropdown: FC = () => {
8686
if (!activeRequest) {
8787
return false;
8888
}
89-
if (!('authentication' in activeRequest)) {
89+
if (!isRequest(activeRequest)) {
9090
return false;
9191
}
9292
return type === (activeRequest.authentication.type || AUTH_NONE);

packages/insomnia/src/ui/components/dropdowns/content-type-dropdown.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
CONTENT_TYPE_YAML,
1616
getContentTypeName,
1717
} from '../../../common/constants';
18+
import { isWebSocketRequest } from '../../../models/websocket-request';
1819
import { selectActiveRequest } from '../../redux/selectors';
1920
import { Dropdown } from '../base/dropdown/dropdown';
2021
import { DropdownButton } from '../base/dropdown/dropdown-button';
@@ -38,7 +39,9 @@ const MimeTypeItem: FC<{
3839
mimeType,
3940
onChange,
4041
}) => {
41-
const activeRequest = useSelector(selectActiveRequest);
42+
const request = useSelector(selectActiveRequest);
43+
const activeRequest = request && !isWebSocketRequest(request) ? request : null;
44+
4245
const handleChangeMimeType = useCallback(async (mimeType: string | null) => {
4346
if (!activeRequest) {
4447
return;
@@ -91,7 +94,8 @@ const MimeTypeItem: FC<{
9194
MimeTypeItem.displayName = DropdownItem.name;
9295

9396
export const ContentTypeDropdown: FC<Props> = ({ onChange }) => {
94-
const activeRequest = useSelector(selectActiveRequest);
97+
const request = useSelector(selectActiveRequest);
98+
const activeRequest = request && !isWebSocketRequest(request) ? request : null;
9599

96100
if (!activeRequest) {
97101
return null;

packages/insomnia/src/ui/components/sidebar/dnd.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import * as models from '../../../models';
77
import { GrpcRequest } from '../../../models/grpc-request';
88
import { Request } from '../../../models/request';
99
import { RequestGroup } from '../../../models/request-group';
10+
import { WebSocketRequest } from '../../../models/websocket-request';
1011

1112
export type DnDDragProps = ReturnType<typeof sourceCollect>;
1213
export type DnDDropProps = ReturnType<typeof targetCollect>;
1314
export type DnDProps = DnDDragProps & DnDDropProps;
1415

1516
export interface DragObject {
16-
item?: GrpcRequest | Request | RequestGroup;
17+
item?: GrpcRequest | Request | WebSocketRequest | RequestGroup;
1718
}
1819

1920
export const sourceCollect = (connect: DragSourceConnector, monitor: DragSourceMonitor) => ({

packages/insomnia/src/ui/components/sidebar/sidebar-children.tsx

+36-21
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import React, { FC, Fragment } from 'react';
22
import ReactDOM from 'react-dom';
33
import { useSelector } from 'react-redux';
44

5-
import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
5+
import { GrpcRequest } from '../../../models/grpc-request';
66
import * as models from '../../../models/index';
7-
import { isRequest, Request } from '../../../models/request';
8-
import type { RequestGroup } from '../../../models/request-group';
7+
import { Request } from '../../../models/request';
8+
import { isRequestGroup, RequestGroup } from '../../../models/request-group';
9+
import { WebSocketRequest } from '../../../models/websocket-request';
910
import { updateRequestMetaByParentId } from '../../hooks/create-request';
1011
import { selectActiveRequest, selectActiveWorkspaceMeta } from '../../redux/selectors';
1112
import { selectSidebarChildren } from '../../redux/sidebar-selectors';
@@ -14,7 +15,7 @@ import { SidebarRequestGroupRow } from './sidebar-request-group-row';
1415
import { SidebarRequestRow } from './sidebar-request-row';
1516

1617
export interface Child {
17-
doc: Request | GrpcRequest | RequestGroup;
18+
doc: Request | GrpcRequest | WebSocketRequest | RequestGroup;
1819
children: Child[];
1920
collapsed: boolean;
2021
hidden: boolean;
@@ -50,16 +51,37 @@ export const SidebarChildren: FC<Props> = ({
5051
updateRequestMetaByParentId(requestId, { lastActive: Date.now() });
5152
};
5253

53-
const RecursiveSidebarRows: FC<RecursiveSidebarRowsProps> = ({ rows, isInPinnedList }) => {
54+
const RecursiveSidebarRows: FC<RecursiveSidebarRowsProps> = ({
55+
rows,
56+
isInPinnedList,
57+
}) => {
5458
const activeRequest = useSelector(selectActiveRequest);
5559
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
5660

5761
return (
5862
<>
59-
{rows.map(row => (!isInPinnedList && row.hidden)
60-
? null
61-
: (isRequest(row.doc) || isGrpcRequest(row.doc))
62-
? (
63+
{rows
64+
.filter(row => !(!isInPinnedList && row.hidden))
65+
.map(row => {
66+
if (isRequestGroup(row.doc)) {
67+
return (
68+
<SidebarRequestGroupRow
69+
key={row.doc._id}
70+
filter={filter || ''}
71+
isActive={hasActiveChild(row.children, activeRequestId)}
72+
isCollapsed={row.collapsed}
73+
requestGroup={row.doc}
74+
>
75+
{row.children.filter(Boolean).length > 0 ? (
76+
<RecursiveSidebarRows
77+
isInPinnedList={isInPinnedList}
78+
rows={row.children}
79+
/>
80+
) : null}
81+
</SidebarRequestGroupRow>
82+
);
83+
}
84+
return (
6385
<SidebarRequestRow
6486
key={row.doc._id}
6587
filter={isInPinnedList ? '' : filter || ''}
@@ -70,19 +92,12 @@ export const SidebarChildren: FC<Props> = ({
7092
disableDragAndDrop={isInPinnedList}
7193
request={row.doc}
7294
/>
73-
) : (
74-
<SidebarRequestGroupRow
75-
key={row.doc._id}
76-
filter={filter || ''}
77-
isActive={hasActiveChild(row.children, activeRequestId)}
78-
isCollapsed={row.collapsed}
79-
requestGroup={row.doc}
80-
>
81-
{row.children.filter(Boolean).length > 0 ? <RecursiveSidebarRows isInPinnedList={isInPinnedList} rows={row.children} /> : null}
82-
</SidebarRequestGroupRow>
83-
))}
84-
</>);
95+
);
96+
})}
97+
</>
98+
);
8599
};
100+
86101
const { all, pinned } = sidebarChildren;
87102
const showSeparator = sidebarChildren.pinned.length > 0;
88103
const contextMenuPortal = ReactDOM.createPortal(

packages/insomnia/src/ui/components/sidebar/sidebar-request-row.tsx

+29-20
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import { CONTENT_TYPE_GRAPHQL } from '../../../common/constants';
77
import { getMethodOverrideHeader } from '../../../common/misc';
88
import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
99
import * as requestOperations from '../../../models/helpers/request-operations';
10-
import { Request } from '../../../models/request';
10+
import { isRequest, Request } from '../../../models/request';
1111
import { RequestGroup } from '../../../models/request-group';
12+
import { isWebSocketRequest, WebSocketRequest } from '../../../models/websocket-request';
1213
import { useNunjucks } from '../../context/nunjucks/use-nunjucks';
1314
import { createRequest } from '../../hooks/create-request';
1415
import { selectActiveEnvironment, selectActiveProject, selectActiveWorkspace } from '../../redux/selectors';
@@ -21,6 +22,7 @@ import { showModal } from '../modals/index';
2122
import { RequestSettingsModal } from '../modals/request-settings-modal';
2223
import { GrpcTag } from '../tags/grpc-tag';
2324
import { MethodTag } from '../tags/method-tag';
25+
import { WebSocketTag } from '../tags/websocket-tag';
2426
import { DnDProps, DragObject, dropHandleCreator, hoverHandleCreator, sourceCollect, targetCollect } from './dnd';
2527

2628
interface RawProps {
@@ -30,7 +32,7 @@ interface RawProps {
3032
handleDuplicateRequest: Function;
3133
isActive: boolean;
3234
isPinned: boolean;
33-
request?: Request | GrpcRequest;
35+
request?: Request | GrpcRequest | WebSocketRequest;
3436
requestGroup?: RequestGroup;
3537
}
3638

@@ -138,7 +140,7 @@ export const _SidebarRequestRow: FC<Props> = forwardRef(({
138140
return;
139141
}
140142

141-
if (isGrpcRequest(request)) {
143+
if (!isRequest(request)) {
142144
return;
143145
}
144146

@@ -203,12 +205,17 @@ export const _SidebarRequestRow: FC<Props> = forwardRef(({
203205
</li>
204206
);
205207
} else {
206-
const methodTag =
207-
isGrpcRequest(request) ? (
208-
<GrpcTag />
209-
) : (
210-
<MethodTag method={request.method} override={methodOverrideValue} />
211-
);
208+
209+
let methodTag = null;
210+
211+
if (isGrpcRequest(request)) {
212+
methodTag = <GrpcTag />;
213+
} else if (isWebSocketRequest(request)) {
214+
methodTag = <WebSocketTag />;
215+
} else if (isRequest(request)) {
216+
methodTag = <MethodTag method={request.method} override={methodOverrideValue} />;
217+
}
218+
212219
node = (
213220
<li ref={nodeRef} className={classes}>
214221
<div
@@ -243,17 +250,19 @@ export const _SidebarRequestRow: FC<Props> = forwardRef(({
243250
</div>
244251
</button>
245252
<div className="sidebar__actions">
246-
<RequestActionsDropdown
247-
right
248-
ref={requestActionsDropdown}
249-
handleDuplicateRequest={handleDuplicateRequest}
250-
handleShowSettings={handleShowRequestSettings}
251-
request={request}
252-
isPinned={isPinned}
253-
requestGroup={requestGroup}
254-
activeEnvironment={activeEnvironment}
255-
activeProject={activeProject}
256-
/>
253+
{!isWebSocketRequest(request) && (
254+
<RequestActionsDropdown
255+
right
256+
ref={requestActionsDropdown}
257+
handleDuplicateRequest={handleDuplicateRequest}
258+
handleShowSettings={handleShowRequestSettings}
259+
request={request}
260+
isPinned={isPinned}
261+
requestGroup={requestGroup}
262+
activeEnvironment={activeEnvironment}
263+
activeProject={activeProject}
264+
/>
265+
)}
257266
</div>
258267
{isPinned && (
259268
<div className="sidebar__item__icon-pin">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react';
2+
3+
export const WebSocketTag = () => (
4+
<div className="tag tag--no-bg tag--small">
5+
<span className="tag__inner">WS</span>
6+
</div>
7+
);

packages/insomnia/src/ui/containers/app.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { isNotDefaultProject } from '../../models/project';
2929
import { Request, updateMimeType } from '../../models/request';
3030
import { type RequestGroupMeta } from '../../models/request-group-meta';
3131
import { getByParentId as getRequestMetaByParentId } from '../../models/request-meta';
32+
import { isWebSocketRequest, WebSocketRequest } from '../../models/websocket-request';
3233
import { isWorkspace } from '../../models/workspace';
3334
import * as plugins from '../../plugins';
3435
import * as themes from '../../plugins/misc';
@@ -266,7 +267,7 @@ class App extends PureComponent<AppProps, State> {
266267
];
267268
}
268269

269-
_requestDuplicate(request?: Request | GrpcRequest) {
270+
_requestDuplicate(request?: Request | GrpcRequest | WebSocketRequest) {
270271
if (!request) {
271272
return;
272273
}
@@ -353,6 +354,11 @@ class App extends PureComponent<AppProps, State> {
353354
return null;
354355
}
355356

357+
if (isWebSocketRequest(this.props.activeRequest)) {
358+
console.warn('Tried to update request mime-type on WebSocket request');
359+
return null;
360+
}
361+
356362
const requestMeta = await models.requestMeta.getOrCreateByParentId(
357363
this.props.activeRequest._id,
358364
);

packages/insomnia/src/ui/context/nunjucks/use-nunjucks.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useCallback } from 'react';
22
import { useSelector } from 'react-redux';
33

44
import { getRenderContext, getRenderContextAncestors, HandleGetRenderContext, HandleRender, render } from '../../../common/render';
5+
import { isWebSocketRequest } from '../../../models/websocket-request';
56
import { NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME } from '../../../templating';
67
import { getKeys } from '../../../templating/utils';
78
import { selectActiveEnvironment, selectActiveRequest, selectActiveWorkspace } from '../../redux/selectors';
@@ -19,7 +20,8 @@ initializeNunjucksRenderPromiseCache();
1920
*/
2021
export const useNunjucks = () => {
2122
const environmentId = useSelector(selectActiveEnvironment)?._id;
22-
const request = useSelector(selectActiveRequest);
23+
const activeRequest = useSelector(selectActiveRequest);
24+
const request = activeRequest && isWebSocketRequest(activeRequest) ? null : activeRequest;
2325
const workspace = useSelector(selectActiveWorkspace);
2426

2527
const fetchRenderContext = useCallback(async () => {

packages/insomnia/src/ui/hooks/use-active-request.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { useCallback } from 'react';
22
import { useSelector } from 'react-redux';
33

44
import * as models from '../../models';
5-
import { isGrpcRequest } from '../../models/grpc-request';
6-
import { Request } from '../../models/request';
5+
import { isRequest, Request } from '../../models/request';
76
import { selectActiveRequest } from '../redux/selectors';
87

98
export const useActiveRequest = () => {
@@ -13,8 +12,8 @@ export const useActiveRequest = () => {
1312
throw new Error('Tried to load null request');
1413
}
1514

16-
if (isGrpcRequest(activeRequest)) {
17-
throw new Error('Loaded GrpcRequest, expected to load Request');
15+
if (!isRequest(activeRequest)) {
16+
throw new Error('Expected to load Request');
1817
}
1918

2019
const patchRequest = useCallback(async (patch: Partial<Request>) => {

packages/insomnia/src/ui/redux/sidebar-selectors.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { BaseModel } from '../../models';
66
import { GrpcRequest, isGrpcRequest } from '../../models/grpc-request';
77
import { isRequest, Request } from '../../models/request';
88
import { isRequestGroup, RequestGroup } from '../../models/request-group';
9+
import { isWebSocketRequest } from '../../models/websocket-request';
910
import {
1011
selectActiveWorkspace,
1112
selectActiveWorkspaceMeta,
@@ -17,7 +18,7 @@ import {
1718
type SidebarModel = Request | GrpcRequest | RequestGroup;
1819

1920
export const shouldShowInSidebar = (model: BaseModel): boolean =>
20-
isRequest(model) || isGrpcRequest(model) || isRequestGroup(model);
21+
isRequest(model) || isWebSocketRequest(model) || isGrpcRequest(model) || isRequestGroup(model);
2122

2223
export const shouldIgnoreChildrenOf = (model: SidebarModel): boolean =>
2324
isRequest(model) || isGrpcRequest(model);

0 commit comments

Comments
 (0)