Well, generally it is not a problem to call a sync method within async method.
You are actualy doing this in more then few instances (GetExtension, NewGuild, ToString, etc...)
But if you have an async method available it would be shame to not use it.
Which you have - IFormFile.CopyToAsync().
using (var bits = new FileStream(path, FileMode.Create))
Since this is an async function, it seems likely the caller may want to know when it's done and if it succeeded. To do that, you need to reject upon error. That means rethrow after logging inside your catch. This allows the error to get back to the caller as a rejected promise.
Simplify by changing config.archives.reduce() to config....
Tips for JS code optimization:
Give your variables meaningful names:
const r1 = await dialog.showOpenDialog(...) can be renamed to dirs or dirList (representing selected directories)
const r2 = await fsp.readFile('./config.json', 'utf8'), config = JSON.parse(r2), where r2 is supposed to be a config file path. Let's rename it to say const ...
can drop the parens.
etc., and all of your methods, should be in lower_snake_case instead of camelCase, by convention.
PEP484 allows you to turn this
def hasTokens(self) -> bool:
and likewise ...