Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/insomnia/src/entry.preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const main: Window['main'] = {
insecureReadFile: options => ipcRenderer.invoke('insecureReadFile', options),
insecureReadFileWithEncoding: options => ipcRenderer.invoke('insecureReadFileWithEncoding', options),
secureReadFile: options => ipcRenderer.invoke('secureReadFile', options),
parseImport: options => ipcRenderer.invoke('parseImport', options),
parseImport: (...args) => ipcRenderer.invoke('parseImport', ...args),
Copy link
Contributor

@jackkav jackkav Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for looking at this bug could you share a repro. notice the structure in this file? @ZxBing0066
its a convention... happy to discuss

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jackkav I use ...args here because parseImport needs more than one argument. If we want to use only the options, we need to declare more interfaces, more glue code, and it is easy to cause bugs since we need to transform the args.

With only options

interface BridgeAPI {
  parseImport: ({
    importEntry: ImportEntry,
    options?: { importerId?: string }
  }) => Return<typeof convert>
}
ipcMainHandle('parseImport', async (_, options: {
    importEntry: ImportEntry,
    options: { importerId?: string }
  }) => {
  return convert(options.importEntry, options.options);
});

With ...args

interface BridgeAPI {
  parseImport: typeof convert
}
ipcMainHandle('parseImport', async (_, ...args) => {
  return convert(...args);
});

Less code means fewer bugs and fewer dependencies. And it could avoid inconsistent calls the the same functionality. Like in the render process we need to call with one options, but in the main process, we need to call with multiple parameters. It looks like chaos.

And these codes are all boilerplate code, we can even simplify them to:

const BridgeAPIMap = {
  parseImport,
  writeFile,
};
export type BridgeAPI = typeof BridgeAPIMap;
for (const action in BridgeAPIMap) {
  ipcMainHandle(action, async (_, ...args) => {
    return BridgeAPIMap[action](...args);
  });
}

No need to declare them one by one. It's also easy to understand that all the interfaces are the same when we call them from the render process or from the main process.

Copy link
Contributor

@jackkav jackkav Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use ...args here because parseImport needs more than one argument.

thats exactly why we use options so its type safe

named arguments are safer than ordered arguments. since we didn't have a safe way to type it previously this is the compromise we landed on. If you have a suggestion to improve the convention I'm curious to hear about it and see a spike showing me how it works.
This is better discussed face to face where possible as I don't want there to be misunderstandings.

readDir: options => ipcRenderer.invoke('readDir', options),
lintSpec: options => ipcRenderer.invoke('lintSpec', options),
on: (channel, listener) => {
Expand Down
14 changes: 12 additions & 2 deletions packages/insomnia/src/main/importers/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,19 @@ export interface ConvertResult {
};
}

export const convert = async (importEntry: ImportEntry) => {
const importers = (await import('./importers')).importers;
export const convert = async (
importEntry: ImportEntry,
{
importerId,
}: {
importerId?: string;
} = {},
) => {
let importers = (await import('./importers')).importers;
const errMsgList: string[] = [];
if (importerId) {
importers = importers.filter(i => i.id === importerId);
}
for (const importer of importers) {
let resources;
if (importer.acceptFilePath === true) {
Expand Down
6 changes: 3 additions & 3 deletions packages/insomnia/src/main/ipc/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export interface RendererToMainBridgeAPI {
cancelAuthorizationInDefaultBrowser: typeof cancelAuthorizationInDefaultBrowser;
setMenuBarVisibility: (visible: boolean) => void;
installPlugin: typeof installPlugin;
parseImport: (options: { contentStr: string }) => Promise<{ data: { resources: models.BaseModel[] } }>;
parseImport: typeof convert;
writeFile: (options: { path: string; content: string }) => Promise<string>;
secureReadFile: (options: { path: string }) => Promise<string>;
insecureReadFile: (options: { path: string }) => Promise<string>;
Expand Down Expand Up @@ -162,8 +162,8 @@ export function registerMainHandlers() {
return cancelAuthorizationInDefaultBrowser(options);
},
);
ipcMainHandle('parseImport', async (_, options: { contentStr: string }) => {
return convert(options);
ipcMainHandle('parseImport', async (_, ...args: Parameters<typeof convert>) => {
return convert(...args);
});
ipcMainHandle('writeFile', async (_, options: { path: string; content: string }) => {
try {
Expand Down
24 changes: 18 additions & 6 deletions packages/insomnia/src/ui/components/modals/paste-curl-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ export const PasteCurlModal = ({
useEffect(() => {
async function parseCurlToRequest() {
try {
const { data } = await window.main.parseImport({
contentStr: defaultValue || '',
});
const { data } = await window.main.parseImport(
{
contentStr: defaultValue || '',
},
{
importerId: 'curl',
},
);
const { resources } = data;
const importedRequest = resources[0];
setIsValid(true);
Expand Down Expand Up @@ -53,12 +58,19 @@ export const PasteCurlModal = ({
defaultValue={defaultValue}
onChange={async value => {
if (!value) {
setIsValid(false);
setReq({});
return;
}
try {
const { data } = await window.main.parseImport({
contentStr: value,
});
const { data } = await window.main.parseImport(
{
contentStr: value,
},
{
importerId: 'curl',
},
);
const { resources } = data;
const importedRequest = resources[0];
setIsValid(true);
Expand Down
Loading