Repository: nwutils/nw-builder (JavaScript)

Issue:
Symlinks are copied as files on decompress
### Issue Type

- [x] Bug Report
- [ ] Feature Request
- [ ] Other

### Current/Missing Behaviour

- Symbolic link is copied as a file and the link is lost. More info [here](https://github.com/nwutils/nw-builder/issues/923).

### Expected/Proposed Behaviour

- Symbolic links are recognised.
- Remove `unzip` package from MacOS runner image.

### Additional Info

There is an [PR](https://github.com/node-modules/compressing/pull/31) addressing this issue. Should manually test and see if it resolves issue and speed up review process

Workaround: Do not use symlinks.

- Package version: 4.3.9 onward
- Operating System: MacOS
- Node version: 20.5.0
- NW.js version: 0.79.1



Discussion: Good work!

I'll test this on our build server asap
Still doesn't work. These are files instead of symlinks

static:nwjs Framework.framework distiller$ ls -al
total 32
drwxr-xr-x 7 distiller staff 224 Aug 25 07:34 .
drwxr-xr-x 3 distiller staff 96 Aug 25 07:34 ..
-rwxr-xr-x 1 distiller staff 24 Aug 25 07:34 Helpers
-rwxr-xr-x 1 distiller staff 26 Aug 25 07:34 Libraries
-rwxr-xr-x 1 distiller staff 26 Aug 25 07:34 Resources
drwxr-xr-x 4 distiller staff 128 Aug 25 07:34 Versions
-rwxr-xr-x 1 distiller staff 31 Aug 25 07:34 nwjs Framework

Looking into this
@zkrige Could you share your CircleCI env info? I'll add that in to the `compresssing` bug report.
```
Executor / Resource Class
MacOS / M1 Large

declare -x BASH_ENV="/tmp/.bash_env-651a5b86a505136c253fc4f5-0-build"
declare -x BASH_SILENCE_DEPRECATION_WARNING="1"
declare -x CI="true"
declare -x CIRCLECI="true"
declare -x CIRCLE_BRANCH="release"
declare -x CIRCLE_BUILD_NUM="2687"
declare -x CIRCLE_BUILD_URL="<REDACTED>"
declare -x CIRCLE_INTERNAL_SCRATCH="/var/folders/m9/0kvw7_5j71j5w0ft56m7ryt00000gn/T/circleci-3896768221"
declare -x CIRCLE_INTERNAL_TASK_DATA="/tmp/.circleci-task-data-651a5b86a505136c253fc4f5-0-build"
declare -x CIRCLE_JOB="build_mac_snapplify"
declare -x CIRCLE_NODE_INDEX="0"
declare -x CIRCLE_NODE_TOTAL="1"
declare -x CIRCLE_OIDC_TOKEN="<REDACTED>"
declare -x CIRCLE_OIDC_TOKEN_V2="<REDACTED>"
declare -x CIRCLE_PLUGIN_TEST="2023-10-02T05:57:00Z"
declare -x CIRCLE_PROJECT_REPONAME="<REDACTED>"
declare -x CIRCLE_PROJECT_USERNAME="<REDACTED>"
declare -x CIRCLE_REPOSITORY_URL="<REDACTED>"
declare -x CIRCLE_SHA1="<REDACTED>"
declare -x CIRCLE_SHELL_ENV="/tmp/.bash_env-651a5b86a505136c253fc4f5-0-build"
declare -x CIRCLE_USERNAME="zkrige"
declare -x CIRCLE_WORKFLOW_ID="<REDACTED>"
declare -x CIRCLE_WORKFLOW_JOB_ID="<REDACTED>"
declare -x CIRCLE_WORKFLOW_WORKSPACE_ID="f30ea1dd-83c3-48ef-80ce-1b13a3548c3c"
declare -x CIRCLE_WORKING_DIRECTORY="~"
declare -x CLIENT_SECRET="<REDACTED>"
declare -x HOME="/Users/distiller"
declare -x HOMEBREW_CELLAR="/opt/homebrew/Cellar"
declare -x HOMEBREW_PREFIX="/opt/homebrew"
declare -x HOMEBREW_REPOSITORY="/opt/homebrew"
declare -x INFOPATH="/opt/homebrew/share/info:/opt/homebrew/share/info:"
declare -x LANG="en_US.UTF-8"
declare -x LC_ALL="en_US.UTF-8"
declare -x LOGNAME="distiller"
declare -x MAIL="/var/mail/distiller"
declare -x MANPATH="/opt/homebrew/share/man:/usr/share/man:/usr/local/share/man:/Users/distiller/.nvm/versions/node/v18.16.0/share/man:/opt/homebrew/share/man::"
declare -x NVM_BIN="/Users/distiller/.nvm/versions/node/v18.16.0/bin"
declare -x NVM_CD_FLAGS=""
declare -x NVM_DIR="/Users/distiller/.nvm"
declare -x NVM_INC="/Users/distiller/.nvm/versions/node/v18.16.0/include/node"
declare -x OLDPWD
declare -x PATH="/Users/distiller/.pyenv/shims:/Users/distiller/.rbenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
declare -x PWD="/Users/distiller"
declare -x PYENV_SHELL="bash"
declare -x RBENV_SHELL="bash"
declare -x SHELL="/bin/bash"
declare -x SHLVL="4"
declare -x SSH_AUTH_SOCK="/var/folders/m9/0kvw7_5j71j5w0ft56m7ryt00000gn/T/circleci-3896768221/ssh_auth_sock"
declare -x SSH_CLIENT="<REDACTED>"
declare -x SSH_CONNECTION="<REDACTED>"
declare -x TENANT_ID="eb49673e-7aab-4b56-866e-bc74ca0cf6c2"
declare -x TERM="xterm-256color"
declare -x TMPDIR="/var/folders/m9/0kvw7_5j71j5w0ft56m7ryt00000gn/T/"
declare -x USER="distiller"
declare -x accessKeyId="<REDACTED>"
declare -x certs="<REDACTED>"
declare -x secretAccessKey="<REDACTED>"
```

is there anything else you need?
Thanks! Not currently but I will let you know if I do
@zkrige Please test the branch again. I've used `yauzl-promise` which should (claims to) preserve symlinks
@ayushmanchhabra I'll get to this ASAP. Probably early next week
@zkrige gentle ping



Fix (patch):
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c430e95b..3cdaa92c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,9 +7,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [4.5.1] - 2023-12-19
+
+### Changed
+
+- Manually create symbolic links for MacOS builds.
+
+## [4.5.0] - 2023-12-18
+
+## Added
+
+- Use `unzipper` to decompress ZIP files.
+
 ## Changed
 
 - Use `tar` to extract tarballs.
+- Disable `options.nativeAddon`.
 
 ### Removed
 
diff --git a/package.json b/package.json
index ff7e81e12..7120c81d0 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
   "scripts": {
     "lint": "eslint src/get.js",
     "docs": "jsdoc -d docs ./src/get.js ./src/run.js ./src/bld.js",
-    "test": "node test/index.js",
+    "test": "node test/get.pre.js && node --test test/get.test.js",
     "demo": "cd test/fixture && node demo.js"
   },
   "devDependencies": {
diff --git a/src/get.js b/src/get.js
index c071d79c2..455d9f7c8 100644
--- a/src/get.js
+++ b/src/get.js
@@ -84,6 +84,9 @@ import util from "./util.js";
  * });
  */
 async function get(options) {
+  if (fs.existsSync(options.cacheDir) === false) {
+    await fsm.mkdir(options.cacheDir, { recursive: true });
+  }
   await getNwjs(options);
   if (options.ffmpeg === true) {
     await getFfmpeg(options);
@@ -123,7 +126,12 @@ const getNwjs = async (options) => {
       });
     } else {
       fs.createReadStream(out)
-        .pipe(unzipper.Extract({ path: options.cacheDir }));
+        .pipe(unzipper.Extract({ path: options.cacheDir }))
+        .on("finish", async () => {
+          if (options.platform === "osx") {
+            await createSymlinks(options);
+          }
+        });
     }
     return;
   }
@@ -194,7 +202,12 @@ const getNwjs = async (options) => {
     });
   } else {
     fs.createReadStream(out)
-      .pipe(unzipper.Extract({ path: options.cacheDir }));
+      .pipe(unzipper.Extract({ path: options.cacheDir }))
+      .on("finish", async () => {
+        if (options.platform === "osx") {
+          await createSymlinks(options);
+        }
+      });
   }
 }
 
@@ -346,4 +359,20 @@ const getNodeHeaders = async (options) => {
   );
 }
 
+const createSymlinks = async (options) => {
+  const frameworksPath = path.join(process.cwd(), options.cacheDir, `nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${options.platform}-${options.arch}`, "nwjs.app", "Contents", "Frameworks", "nwjs Framework.framework");
+  const symlinks = [
+    path.join(frameworksPath, "Helpers"),
+    path.join(frameworksPath, "Libraries"),
+    path.join(frameworksPath, "nwjs Framework"),
+    path.join(frameworksPath, "Resources"),
+    path.join(frameworksPath, "Versions", "Current"),
+  ];
+  for await (const symlink of symlinks) {
+    const link = String(await fsm.readFile(symlink));
+    await fsm.rm(symlink);
+    await fsm.symlink(link, symlink);
+  }
+};
+
 export default get;