Repository: nwutils/nw-builder (JavaScript)

Issue:
manifest.json not being downloaded due to inexistent cache directory
### Issue Type

- [X] Bug Fix
- [ ] Feature
- [ ] Other

### Current/Missing Behaviour
Currently, the `cache` directory is not created when running the nwbuild CLI, resulting in the error below:
![image](https://user-images.githubusercontent.com/50509793/212564596-7bf8ead1-3284-49b7-bc9c-cd1aef7c0e66.png)

### Expected/Proposed Behaviour
Add a step to create the cache directory if it doesn't exist.

### Additional Info

- Operating System: Ubuntu 22.04
- Node version: v18.13.0
- NW.js version: 4.0.7


Discussion: Create cache code:
https://github.com/nwutils/nw-builder/blob/d39a6d345edead51ca74c726f44560d554697c2c/src/nwbuild.js#L147-L156

Get release info code:
https://github.com/nwutils/nw-builder/blob/d39a6d345edead51ca74c726f44560d554697c2c/src/nwbuild.js#L138-L142

Looks like the create cache dir code is after the `getReleaseInfo` info command which leads to this error. 
hmm, but if the cache dir is not created before the `getManifest` function call, the `manifest.json` and SDK are never downloaded. 

I opened PR #771 creating the cache dir before knowing this info, but you can close it if it's wrong.

what do you suggest?
> Create cache code:
> 
> https://github.com/nwutils/nw-builder/blob/d39a6d345edead51ca74c726f44560d554697c2c/src/nwbuild.js#L147-L156
> 
> Get release info code:
> 
> https://github.com/nwutils/nw-builder/blob/d39a6d345edead51ca74c726f44560d554697c2c/src/nwbuild.js#L138-L142
> 
> Looks like the create cache dir code is after the `getReleaseInfo` info command which leads to this error.

I guess my intuition was wrong. Something weird is going on. I'll dig into this.
> hmm, but if the cache dir is not created before the `getManifest` function call, the `manifest.json` and SDK are never downloaded.
> 
> I opened PR #771 creating the cache dir before knowing this info, but you can close it if it's wrong.
> 
> what do you suggest?

This also does not seem to work:

```shell
ayushmxn@Tau:~/tharatau/nw/nw-builder$ npm run demo:nix

> nw-builder@4.0.7 demo:nix
> cd ./test/e2e && node nix.js

[ DEBUG ] 2023-01-15T20:45:44.469Z nwbuild property is not defined in package.json
[ DEBUG ] 2023-01-15T20:45:44.470Z Cache directory does not exist locally
[ DEBUG ] 2023-01-15T20:45:44.470Z Creating cache directory /home/ayushmxn/tharatau/nw/nw-builder/test/e2e/cache
[ DEBUG ] 2023-01-15T20:45:44.471Z Manifest file does not exist locally
[ DEBUG ] 2023-01-15T20:45:44.471Z Downloading latest manifest file under /home/ayushmxn/tharatau/nw/nw-builder/test/e2e/cache
[ DEBUG ] 2023-01-15T20:45:45.051Z Succesfully cached manifest metadata
[ DEBUG ] 2023-01-15T20:45:45.053Z Store manifest metadata in memory
[ DEBUG ] 2023-01-15T20:45:45.055Z Search for latest specific release data
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[Error: ENOENT: no such file or directory, scandir './build/nix'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'scandir',
  path: './build/nix'
}

Node.js v18.13.0
```



Fix (patch):
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 7b18db739..389ade3c1 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -3,7 +3,9 @@ Fixes: #
 - [ ] Format
 - [ ] Lint
 - [ ] Test
+- [ ] Docs
 - [ ] Add name to AUTHORS (first time contributors)
 - [ ] Update CHANGELOG
+- [ ] Version bump
 
 ### Description
diff --git a/CHANGELOG-4.md b/CHANGELOG-4.md
index 3db759789..a8bb898db 100644
--- a/CHANGELOG-4.md
+++ b/CHANGELOG-4.md
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [4.0.8] - 2023-01-15
+
+### Added
+
+- Flag to check if specific `nw` release is cached. [#772](https://github.com/nwutils/nw-builder/pull/772)
+
+### Changed
+
+- Create `cacheDir`, `outDir` before getting release info. [#772](https://github.com/nwutils/nw-builder/pull/772)
+
 ## [4.0.7] - 2023-01-14
 
 ### Changed
@@ -87,4 +97,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 - MacOS support. [#685](https://github.com/nwutils/nw-builder/pull/685)
 
-- Check for `nwbuild` object in `package.json`. [#684](https://github.com/nwutils/nw-builder/pull/684)
\ No newline at end of file
+- Check for `nwbuild` object in `package.json`. [#684](https://github.com/nwutils/nw-builder/pull/684)
diff --git a/package.json b/package.json
index c4957fe3f..5d6d4acbd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nw-builder",
-  "version": "4.0.7",
+  "version": "4.0.8",
   "description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
   "keywords": [
     "NW.js",
diff --git a/src/get/getReleaseInfo.js b/src/get/getReleaseInfo.js
index 5025151b3..fb8805159 100644
--- a/src/get/getReleaseInfo.js
+++ b/src/get/getReleaseInfo.js
@@ -34,8 +34,6 @@ export const getReleaseInfo = async (version, cacheDir, manifestUrl) => {
     releaseData = manifest.versions.find(
       (release) => release.version === `v${version}`,
     );
-
-    releaseData.version = version;
   }
   return releaseData;
 };
diff --git a/src/nwbuild.js b/src/nwbuild.js
index 4aa641929..1c0d0e4be 100644
--- a/src/nwbuild.js
+++ b/src/nwbuild.js
@@ -80,54 +80,55 @@ import { log } from "./log.js";
 const nwbuild = async (options) => {
   let nwDir = "";
   let cached;
+  let nwCached;
   let built;
   let releaseInfo = {};
 
   notify();
 
   try {
-
     const { opts, files, nwPkg } = await getOptions(options);
     options = opts;
 
-    // Parse options, set required values to undefined and flags with default values unless specified by user
+    // Parse options
     options = await parse(options, nwPkg);
 
-    // Validate options.version here
-    // We need to do this to get the version specific release info
+    // Create cacheDir if it does not exist
+    cached = await isCached(options.cacheDir);
+    if (cached === false) {
+      await mkdir(options.cacheDir, { recursive: true });
+    }
+
+    // Create outDir if it does not exist
+    built = await isCached(options.outDir);
+    if (built === false) {
+      await mkdir(options.outDir, { recursive: true });
+    }
+
+    // Validate options.version to get the version specific release info
     releaseInfo = await getReleaseInfo(
       options.version,
       options.cacheDir,
       options.manifestUrl,
     );
-    options.version = releaseInfo.version;
+    // Remove leading "v" from version string
+    options.version = releaseInfo.version.slice(1);
 
-    validate(options, releaseInfo);
+    await validate(options, releaseInfo);
 
     // Variable to store nwDir file path
     nwDir = `${options.cacheDir}/nwjs${
       options.flavor === "sdk" ? "-sdk" : ""
     }-v${options.version}-${options.platform}-${options.arch}`;
 
-    // Create cacheDir if it does not exist
-    cached = await isCached(nwDir);
-    if (cached === false) {
-      await mkdir(nwDir, { recursive: true });
-    }
-
-    // Create outDir if it does not exist
-    built = await isCached(options.outDir);
-    if (built === false) {
-      await mkdir(options.outDir, { recursive: true });
-    }
-
+    nwCached = await isCached(nwDir);
     // Remove cached NW binary
-    if (options.cache === false && cached === true) {
+    if (options.cache === false && nwCached === true) {
       log.debug("Remove cached NW binary");
       await rm(nwDir, { force: true, recursive: true });
     }
     // Download relevant NW.js binaries
-    if (cached === false) {
+    if (nwCached === false) {
       log.debug("Download relevant NW.js binaries");
       await download(
         options.version,
diff --git a/src/util/cache.js b/src/util/cache.js
index 60ce44726..3dd6d962c 100644
--- a/src/util/cache.js
+++ b/src/util/cache.js
@@ -3,8 +3,8 @@ import { access, constants } from "node:fs/promises";
 /**
  * Check if NW binaries are cached
  *
- * @param  {string}           nwDir  Path to cached NW binaries
- * @return {Promise<boolean>}        Boolean value to denote if cache exists or not
+ * @param  {string}  nwDir  Path to cached NW binaries
+ * @return {boolean}        Boolean value to denote if cache exists or not
  */
 export const isCached = async (nwDir) => {
   let exists = true;
diff --git a/src/util/notify.js b/src/util/notify.js
index 79f4405a4..806b1b3ee 100644
--- a/src/util/notify.js
+++ b/src/util/notify.js
@@ -1,14 +1,13 @@
-import { createRequire } from 'node:module';
+import { createRequire } from "node:module";
 const require = createRequire(import.meta.url);
 
 import updateNotifier from "update-notifier";
 
-
 /**
  * Notify the user if there is a new version of the package available.
-*
-* @return {Promise<void>}
-*/
+ *
+ * @return {Promise<void>}
+ */
 export const notify = async () => {
   const packageJson = require("../../package.json");
   updateNotifier({ pkg: packageJson }).notify();
diff --git a/src/util/validate.js b/src/util/validate.js
index b393c4132..6ba5dc2ea 100644
--- a/src/util/validate.js
+++ b/src/util/validate.js
@@ -3,9 +3,9 @@ import { readdir } from "node:fs/promises";
 /**
  * Validate options
  *
- * @param  {object}    options      Options
- * @param  {object}    releaseInfo  Version specific NW release info
- * @return {undefined}              True if options are valid. False otherwise
+ * @param  {object}             options      Options
+ * @param  {object}             releaseInfo  Version specific NW release info
+ * @return {Promise<undefined>}              True if options are valid. False otherwise
  */
 export const validate = async (options, releaseInfo) => {
   if (options.srcDir === "") {