Our CLI can be run from anywhere on the system but we have a critical error. The script is trying to find a data.json
file that is relative to where it is being called. This will throw an error if you aren't actually in the script directory.
The fix for this in an ECMAScript project like we are in is to use a import.meta.url
variable that will give use the directory that the script is executed in. We can append our data.json
to this path and call that throughout our script and we've fixed our error!
Instructor: [0:00] Running QuizMe outside of our projects directory is failing, because it's trying to open a relative path. How can we make sure that we're always going to get data.json? [0:11] If we're using CommonJS, we would have a variable __dirname, which tells us the directory that contains the currently executing script. We could use that __dirname then to make a path to our data file. But we're using ES6, which means we don't have this out of the box. Instead, we have import.meta.url, which gives us a URL representing the file that is currently executing.
[0:42] If I console.log(import.meta.url) and just do process.exit here so we can see that, we get a URL that's representing the location of the currently executed file. I can use a function which will get the file path. Import { fileURLToPath } -- and that's a new URL package -- and use that to wrap our import.meta.url, and I'll get the path to the file.
[1:17] In CommonJS, we got this for free at the variable __filename, but in using ECMAScript modules, using module mode, we need to do a little bit of work to get it back again. What we really need is that special variable, __dirname.
[1:33] To get that, we're going to need to get something from our path, which is to get the __dirname, which is in the path library. Then, we're going to wrap what we got here as the __dirname. Now we have the directory where that's being executed.
[1:47] Next, we want to use the path.join to. Let's stop console logging this, and let's call it __dirname. Our data file is going to be find by joining the __dirname with the other.JSON.
[2:05] The reason we use join rather than typing the file path in manually is because different operating systems use backslashes or forward slashes to be able to denote transition directory. Join from path manages all of that complexity for us. On my system, I know I'm going to see forward slashes to represent directory changes. On your system, if you're on Windows, you'll expect backslashes.
[2:30] Now I've got my data file. I can now replace anywhere where I've got this relative file import, I'm going to replace that with data file. In this directory, which is in my project directory, I'm going to run QuizMe and I'm getting the question, I'm answering my question, and it's writing it to my file.
There's an easier way according to the docs: const dataFile = new URL("./data.json", import.meta.url); see: https://nodejs.org/api/esm.html#importmetaurl (correct me if I'm wrong, trying learn)