@mcc you don't need a wrapper in recent Node - "top level await" is a thing
Several approaches here https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/
@mcc it's a mind set shift to 'import' but worth taking
@falken In my own programs, I always use import exclusively. However this is partially because my own programs exclusively use TypeScript, which (because it has had import for longer than the web platform has supported it) actually has the capacity to compile mjs "into" cjs (and I think vice versa), and therefore has perfect cross compatibility when you try to mix the two in a single program.
Node, in my experience, is not perfectly cross compatible. To put it mildly.
@falken I didn't write this program, so switching on mjs when it did not previously use mjs seems like, in the Node environment, you're creating a high risk of Problems. So I have made a decision not to do that when I'm already in a debugging phase…
@mcc it is a bit all or nothing, don't mix in a single project, at least for me
@falken Yeah, I agree. There's this trick where you can mix in one project by actually naming the files .cjs and .mjs, and I've got this to work *exactly* once, and it was such a weird process it made me want to never try it again
@mcc@mastodon.social @falken@qoto.org If you want to mix CJS and ESM in Node.js, you need to understand the Resolution Algorithm first (warning: it's not for the faint of heart): https://nodejs.org/dist/latest-v20.x/docs/api/esm.html#resolution-algorithm-specification
@mcc@mastodon.social @falken@qoto.org We were forced to move a project to ESM because some dependencies decided to switch to pure ESM and completely remove CJS support (see: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c ), and since other dependencies were still CJS-only, we had to mix both. The biggest issues we faced:
1. We thought we were using ESM in TypeScript because our code had import ... from ... instead of const ... = require(...), but it turns out TypeScript will emit CJS by default and we were never using ESM at runtime. Just open any emitted .js file and see for yourself. The correct way to use ESM is to set "module":"node16" in tsconfig.json
2. There are packages with wrong exports field in package.json. For example, giving the path to a CJS file but claiming it's an ESM file.
3. There are packages where the TypeScript definitions match the CJS files but not the ESM files.
4. TypeScript tries to paper over broken packages using some workarounds (esModuleInterop, allowSyntheticDefaultImports, etc). These will mostly work if you're emitting CJS, but will cause hard to debug runtime import errors if you emit ESM. We ended up disabling them and either fixing the broken packages upstream or adding our own package-specific workarounds.
Sorry if the above sounds like a rant, but I've had a terrible experience and wish to warn others of the pitfalls.
@falken "SyntaxError: await is only valid in async functions and the top level bodies of modules"
I think this is because I must declare my project to be mjs rather than cjs, but I'm already importing with require…