How do I do process.argv[1] === fileURLToPath(import.meta.url) in ES6 Node.js?

Following up from my previous question where I asked how to know if the current module is being run via comandline vs being imported, I’m now trying to do it via ES6.

If you take a look at this StackOverflow answer, they’re suggesting you import fileURLToPath, and use import.meta.url in it to see it matches what’s passed to your commandline arguments via process.args[1].

So I switched my package.json to type module, my bsconfig to es6-module, put

%raw(`import { fileURLToPath } from "url"`)

up top, and

if %raw(`fileURLToPath(import.meta.url) === process.argv[1]`) {

at the bottom, but it doesn’t work because the ES6 module has the import compiled like:

((import { fileURLToPath } from "url"));

Soooooo plan B:

  1. make a JavaScript file:
import { fileURLToPath } from "url"

export const isMain = path =>
    fileURLToPath(path) === process.argv[1]
  1. Make a ReScript wrapper module:
@module("./isMainUtil.mjs") external isMain: string => bool = "isMain"
  1. To use open IsMain up top and at the bottom of my file go:
if isMain(%raw(`import.meta.url`)) {

It works, but… my god, what a pain. This seems like an oversight in ES6 modules in Node.js implementation. Is there an easier way to do this in ReScript that doesn’t require so many moving parts?

I suppose if you have a small codebase that doesn’t have files named the same, then this will work as a single line of code:

if (%raw(`process.argv[1].split('/')[process.argv[1].split('/').length - 1] === import.meta.url.split('/')[import.meta.url.split('/').length - 1]`)) {

:sweat_smile: “The horror… the horror…”

There are probably a few ways to do this, but maybe something like this would work for you?

@module("url") external fileURLToPath: string => string = "fileURLToPath"
@val external importMetaUrl: string = "import.meta.url"

let isMain = () => {
  Node.Process.argv[1] === fileURLToPath(importMetaUrl)
}
1 Like

This is exactly what the ReScript creator suggests :slightly_smiling_face: Need help with bindings for nested class constructor - #3 by Hongbo

2 Likes

Ah, I was missing the @val technique, super helpful, thank you! I also had no idea Node was a top level module, where the heck is that in the docs hahah!?