diff --git a/.changeset/tasty-windows-remain.md b/.changeset/tasty-windows-remain.md new file mode 100644 index 0000000..7738c27 --- /dev/null +++ b/.changeset/tasty-windows-remain.md @@ -0,0 +1,6 @@ +--- +'@msw-devtools/extension': patch +'@msw-devtools/core': patch +--- + +Passthrough support diff --git a/README.md b/README.md index 562c741..e0e475e 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,31 @@ Switch seamlessly between multiple JSON configurations within the same host envi -### Edit json config in the DevTools - +### 🚀 Pass-Through Mode +Enable pass-through mode to bypass MSW and send requests directly to the server +even if configurations are uploaded. -### Pause/Resume mode - + + + +## Roadmap Features 🚧 + +### Edit json config in the DevTools + +Currently, you can only upload JSON files, but you can't edit them in the DevTools. + +### Upload multiple JSON config at once + +Currently, you can only upload one JSON file at a time, because +it simplifies the process of validation. + +### Multi window support + +Currently, you can use multi tabs with different configurations per host, but only one browser window is supported. + +### Early request interception + +Currently, requests sent before the extension is initialized are not intercepted by JSON handlers. ## Motivation 💡 diff --git a/media/extension/multi-configs.png b/media/extension/multi-configs.png index 2de7f51..4162fd2 100644 Binary files a/media/extension/multi-configs.png and b/media/extension/multi-configs.png differ diff --git a/media/extension/passthrough-mode.png b/media/extension/passthrough-mode.png new file mode 100644 index 0000000..3c6d1c8 Binary files /dev/null and b/media/extension/passthrough-mode.png differ diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 1e0780b..ece59c9 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -100,12 +100,18 @@ export type BackgroundResponseMessage = hasHandle: boolean hasConfig: boolean activeConfig?: LocalStorageConfigKey - configNames: Record< - string, - { - key: LocalStorageConfigKey - } - > + configNames: ( + | { + name: string + passthrough?: false + key: LocalStorageConfigKey + } + | { + name: string + passthrough: true + key: `host=${string}&name=__mswde_passthrough_config&jsonConfig=1` + } + )[] } } )) diff --git a/packages/extension/src/background/activeMswResolvers.ts b/packages/extension/src/background/activeMswResolvers.ts index 589e7cc..fa6d995 100644 --- a/packages/extension/src/background/activeMswResolvers.ts +++ b/packages/extension/src/background/activeMswResolvers.ts @@ -3,6 +3,7 @@ import Tab = chrome.tabs.Tab type IndexInfo = { tabId: number host?: string + windowId?: number } export const activeMswResolvers = { diff --git a/packages/extension/src/background/messages.ts b/packages/extension/src/background/messages.ts index bc09e38..5de80f6 100644 --- a/packages/extension/src/background/messages.ts +++ b/packages/extension/src/background/messages.ts @@ -40,6 +40,7 @@ const messages: HandlersMap = { [MessageType.HandleInitialized]: async ({ type, host }, sender) => { activeMswResolvers.add({ tabId: sender.tab!.id!, + windowId: sender.tab!.windowId!, host }) @@ -95,11 +96,10 @@ const messages: HandlersMap = { let hasConfig = false let currentConfig: Awaited> = null - let configNames: Awaited> = {} + let configNames: Awaited> = [] try { currentConfig = await getJsonConfig(host) - configNames = await getJsonConfigNames(host) hasConfig = !!currentConfig } catch (e) { diff --git a/packages/extension/src/background/storage.ts b/packages/extension/src/background/storage.ts index 6dfb9c8..c520fb3 100644 --- a/packages/extension/src/background/storage.ts +++ b/packages/extension/src/background/storage.ts @@ -39,20 +39,24 @@ export const getJsonConfigNames = async ( (memo, [key, config]) => { if (!config) return memo - memo[config.name] = { + memo.push({ + name: config.name, key: key as LocalStorageConfigKey - } + }) + return memo }, - {} as Extract< - BackgroundResponseMessage, - { - type: MessageType.Status - payload: any - } - >['payload']['configNames'] + [] as Awaited> ) + if (names.length) { + names.push({ + name: 'passthrough', + passthrough: true, + key: `host=${host}&name=__mswde_passthrough_config&jsonConfig=1` + }) + } + return names } diff --git a/packages/extension/src/popup/App.tsx b/packages/extension/src/popup/App.tsx index be8b689..568d19d 100644 --- a/packages/extension/src/popup/App.tsx +++ b/packages/extension/src/popup/App.tsx @@ -131,9 +131,13 @@ export const App = () => { {(() => { switch (configStatus) { case 'success': - return <>JSON config has been detected + return <>Active JSON config has been detected default: - return <>JSON config hasn't been detected + return !status?.configNames.length ? ( + <>JSON config hasn't been detected + ) : ( + <>Active JSON config hasn't been detected + ) } })()} diff --git a/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.module.css b/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.module.css index 79167e2..0738ab3 100644 --- a/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.module.css +++ b/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.module.css @@ -31,8 +31,9 @@ max-width: 100%; overflow: hidden; text-overflow: ellipsis; + line-height: 1.5em; - &:last-child { + &:not(&:first-child) { padding-left: 5px; padding-right: 5px; flex-shrink: 0; @@ -41,4 +42,9 @@ &:hover { background-color: #404040; } + + &:disabled&:hover { + cursor: not-allowed; + background: inherit; + } } \ No newline at end of file diff --git a/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.tsx b/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.tsx index 3230a75..756243c 100644 --- a/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.tsx +++ b/packages/extension/src/popup/ConfigListButtons/ConfigListButtons.tsx @@ -1,55 +1,66 @@ import React, { FC } from 'react' import { clsx } from 'clsx' -import { - BackgroundResponseMessage, - LocalStorageConfigKey, - MessageType -} from '@msw-devtools/core' +import { BackgroundResponseMessage, MessageType } from '@msw-devtools/core' import TrashIcon from './trash.svg' +import PausedIcon from './pause.svg' +import PlayIcon from './play.svg' import styles from './ConfigListButtons.module.css' +type ConfigNames = Extract< + BackgroundResponseMessage, + { type: MessageType.Status; payload: any } +>['payload']['configNames'] + export const ConfigListButtons: FC<{ - list?: Extract< - BackgroundResponseMessage, - { type: MessageType.Status; payload: any } - >['payload']['configNames'] - activeKey?: LocalStorageConfigKey - onRemove: (key: LocalStorageConfigKey) => void - onSetActive: (key: LocalStorageConfigKey) => void + list?: ConfigNames + activeKey?: ConfigNames[0]['key'] + onRemove: (key: ConfigNames[0]['key']) => void + onSetActive: (key: ConfigNames[0]['key']) => void }> = ({ list, onSetActive, activeKey, onRemove }) => { - if (!list) return - - const listEntries = Object.entries(list) - if (!listEntries.length) return + if (!list?.length) return return (
- {listEntries.map(([name, { key }], index) => ( -
- - -
- ))} + + +
+ ) + })} ) } diff --git a/packages/extension/src/popup/ConfigListButtons/pause.svg b/packages/extension/src/popup/ConfigListButtons/pause.svg new file mode 100644 index 0000000..c634f89 --- /dev/null +++ b/packages/extension/src/popup/ConfigListButtons/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/extension/src/popup/ConfigListButtons/play.svg b/packages/extension/src/popup/ConfigListButtons/play.svg new file mode 100644 index 0000000..7845308 --- /dev/null +++ b/packages/extension/src/popup/ConfigListButtons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/extension/src/popup/ConfigListButtons/trash.svg b/packages/extension/src/popup/ConfigListButtons/trash.svg index d11a680..a8b856b 100644 --- a/packages/extension/src/popup/ConfigListButtons/trash.svg +++ b/packages/extension/src/popup/ConfigListButtons/trash.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/packages/extension/src/popup/utils.ts b/packages/extension/src/popup/utils.ts index 499558b..214d327 100644 --- a/packages/extension/src/popup/utils.ts +++ b/packages/extension/src/popup/utils.ts @@ -93,7 +93,7 @@ export const getStatus = async (host: string) => { BackgroundResponseMessage, { type: MessageType.Status; payload: any } >['payload'] - >((resolve, reject) => { + >((resolve) => { sendMessage< Extract >( @@ -112,7 +112,7 @@ export const getStatus = async (host: string) => { host, hasHandle: false, hasConfig: false, - configNames: {} + configNames: [] }) } }, @@ -123,17 +123,25 @@ export const getStatus = async (host: string) => { hasHandle: true, hasConfig: true, activeConfig: 'host=localhost&name=production&jsonConfig=1', - configNames: { - production: { + configNames: [ + { + name: 'production', key: 'host=localhost&name=production&jsonConfig=1' }, - development: { + { + name: 'development', key: 'host=localhost&name=development&jsonConfig=1' }, - staging: { + { + name: 'staging', key: 'host=localhost&name=staging&jsonConfig=1' + }, + { + name: 'passthrough', + passthrough: true, + key: `host=${host}&name=__mswde_passthrough_config&jsonConfig=1` } - }, + ], host: window.location.host } } diff --git a/tsconfig.json b/tsconfig.json index 30bb160..7dedd36 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,5 +10,9 @@ "skipLibCheck": true }, "include": ["packages/*/src/**/*", "packages/*/*.d.ts", "declaration.d.ts"], - "exclude": ["node_modules", "dist"] + "exclude": [ + "node_modules", + "packages/*/dist/**/*", + "packages/*/node_modules/**/*" + ] }