nw-builder 4.1.0 → 4.1.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,10 +7,20 @@ Build [NW.js](https://github.com/nwjs/nw.js) applications for Mac, Windows and L
7
7
 
8
8
  > Before using `nw-builder`, please go through how to [write an NW.js application](https://nwjs.readthedocs.io/en/latest/For%20Users/Getting%20Started/).
9
9
 
10
+ ## Major Features
11
+
12
+ - Build for Linux, MacOS, and Windows
13
+ - Support downloading [from](https://npm.taobao.org/mirrors/nwjs) [mirrors](https://npmmirror.com/mirrors/nwjs)
14
+ - Integrate [`nwjs-ffmpeg-prebuilt`](https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt)
15
+ - Configure executable fields and icons
16
+
17
+ ## Table of Contents
18
+
10
19
  - [Installation](https://github.com/nwutils/nw-builder#installation)
11
20
  - [Usage](https://github.com/nwutils/nw-builder#usage)
12
21
  - [Limitations](https://github.com/nwutils/nw-builder#limitations)
13
22
  - [API Reference](https://nwutils.io/nw-builder/global#nwbuild)
23
+ - [Migration Guide](https://github.com/nwutils/nw-builder#migration)
14
24
  - [Contributing](https://github.com/nwutils/nw-builder#contributing)
15
25
  - [License](https://github.com/nwutils/nw-builder#license)
16
26
 
@@ -112,30 +122,30 @@ For more options, check out the [API reference](https://nwutils.io/nw-builder/gl
112
122
 
113
123
  - #716 File permissions are incorrectly set for Linux or MacOS apps built on Windows platform.
114
124
 
115
- ## Migration to v4
125
+ ## Migration
126
+
127
+ Migrate from v3 to v4
116
128
 
117
129
  ### Update `nw-builder`
118
130
 
119
131
  With npm:
120
132
 
121
133
  ```shell
122
- npm update nw-builder@^4.0.3
134
+ npm update nw-builder@^4.1.1
123
135
  ```
124
136
 
125
137
  With yarn:
126
138
 
127
139
  ```shell
128
- yarn upgrade nw-builder@^4.0.3
140
+ yarn upgrade nw-builder@^4.1.1
129
141
  ```
130
142
 
131
143
  With pnpm:
132
144
 
133
145
  ```shell
134
- pnpm update nw-builder@^4.0.3
146
+ pnpm update nw-builder@^4.1.1
135
147
  ```
136
148
 
137
- > Note: `nw-builder` has been tested on Node 16 and 18 only.
138
-
139
149
  ### Update options
140
150
 
141
151
  Let's take an example of v3 code and migrate it to v4.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nw-builder",
3
- "version": "4.1.0",
3
+ "version": "4.1.1-beta.1",
4
4
  "description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
5
5
  "keywords": [
6
6
  "NW.js",
@@ -8,7 +8,16 @@
8
8
  "Desktop",
9
9
  "Application"
10
10
  ],
11
- "author": "nw-builder Authors",
11
+ "author": {
12
+ "name": "Steffen Müller",
13
+ "url": "https://www.mllrsohn.com/"
14
+ },
15
+ "contributors": [
16
+ {
17
+ "name": "The nw-builder Authors",
18
+ "url": "https://github.com/nwutil/nw-builder/graphs/contributors"
19
+ }
20
+ ],
12
21
  "license": "MIT",
13
22
  "exports": {
14
23
  "default": "./src/nwbuild.js"
@@ -25,13 +34,13 @@
25
34
  },
26
35
  "scripts": {
27
36
  "fmt": "prettier --write \"./**/*.{css,html,js,json,md,yml}\"",
28
- "lnt": "eslint ./src",
37
+ "lnt": "eslint --fix ./src",
29
38
  "doc": "jsdoc ./src/nwbuild.js -d docs",
30
- "e2e": "node --test e2e/index.js",
39
+ "e2e": "node --test-reporter=spec --test e2e/index.js",
31
40
  "test:unit": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
32
41
  "demo:esm": "cd e2e && node demo.js",
33
42
  "demo:cjs": "cd e2e && node demo.cjs",
34
- "demo:cli": "cd ./test && nwbuild ./nwapp/* --mode=build --version=latest --flavor=normal --platform=linux --arch=x64 --outDir=./build/cli"
43
+ "demo:cli": "cd e2e && nwbuild ./app/* --mode=build --version=0.73.0 --flavor=normal --platform=win --arch=x64 --outDir=./out --cacheDir=./tmp"
35
44
  },
36
45
  "devDependencies": {
37
46
  "eslint": "^8.34.0",
@@ -20,7 +20,7 @@ import { setWinConfig } from "./winCfg.js";
20
20
  * @param {object} app Multi platform configuration options
21
21
  * @return {Promise<undefined>}
22
22
  */
23
- const packager = async (
23
+ export const build = async (
24
24
  files,
25
25
  nwDir,
26
26
  outDir,
@@ -34,8 +34,14 @@ const packager = async (
34
34
  log.debug(`Copy ${nwDir} files to ${outDir} directory`);
35
35
  await cp(nwDir, outDir, { recursive: true });
36
36
 
37
- log.debug(`Copy ${nwDir} files to ${outDir} directory`);
37
+ log.debug(`Copy files in srcDir to ${outDir} directory`);
38
38
  for (let file of files) {
39
+ let filePath = "";
40
+ if (file.split("/").length === 2) {
41
+ filePath = file;
42
+ } else {
43
+ filePath = file.split("/").splice(2).join("/");
44
+ }
39
45
  log.debug(`Copy ${file} file to ${outDir} directory`);
40
46
  await cp(
41
47
  file,
@@ -44,10 +50,8 @@ const packager = async (
44
50
  platform !== "osx"
45
51
  ? "package.nw"
46
52
  : "nwjs.app/Contents/Resources/app.nw",
53
+ filePath,
47
54
  ),
48
- {
49
- recursive: true,
50
- },
51
55
  );
52
56
  }
53
57
 
@@ -72,5 +76,3 @@ const packager = async (
72
76
  await compress(outDir, zip);
73
77
  }
74
78
  };
75
-
76
- export { packager };
@@ -7,9 +7,9 @@ import { log } from "../log.js";
7
7
  * Generates a Desktop Entry file for Linux
8
8
  * https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s06.html
9
9
  *
10
- * @param {object} app Multi platform configuration options
11
- * @param {string} outDir Directory which stores build artifacts
12
- * @return {undefined}
10
+ * @param {object} app Multi platform configuration options
11
+ * @param {string} outDir Directory which stores build artifacts
12
+ * @return {Promise<void>}
13
13
  */
14
14
  export const setLinuxConfig = async (app, outDir) => {
15
15
  if (platform === "win32") {
package/src/bld/winCfg.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { rename } from "node:fs/promises";
2
+ import { resolve } from "node:path";
2
3
 
3
4
  import rcedit from "rcedit";
4
5
 
@@ -37,9 +38,9 @@ const setWinConfig = async (app, outDir) => {
37
38
  });
38
39
 
39
40
  try {
40
- await rename(`${outDir}/nw.exe`, `${outDir}/${app.name}.exe`);
41
-
42
- await rcedit(`${outDir}/${app.name}.exe`, {
41
+ const outDirAppExe = resolve(outDir, `${app.name}.exe`);
42
+ await rename(resolve(outDir, "nw.exe"), outDirAppExe);
43
+ await rcedit(outDirAppExe, {
43
44
  "file-version": app.version,
44
45
  "icon": app.icon,
45
46
  "product-version": app.version,
@@ -47,7 +48,7 @@ const setWinConfig = async (app, outDir) => {
47
48
  });
48
49
  } catch (error) {
49
50
  log.warn(
50
- "Unable to modify EXE. Ensure WINE is installed or build in Windows",
51
+ "Renaming EXE failed or unable to modify EXE. If it's the latter, ensure WINE is installed or build in Windows",
51
52
  );
52
53
  log.error(error);
53
54
  }
@@ -14,12 +14,21 @@ import { log } from "../log.js";
14
14
  */
15
15
  const decompress = async (platform, cacheDir, downloadUrl) => {
16
16
  try {
17
- if (downloadUrl === "https://dl.nwjs.io") {
17
+ if (
18
+ downloadUrl === "https://dl.nwjs.io" ||
19
+ downloadUrl === "https://npm.taobao.org/mirrors/nwjs" ||
20
+ downloadUrl === "https://npmmirror.com/mirrors/nwjs"
21
+ ) {
18
22
  if (platform === "linux") {
19
23
  await Decompress(resolve(cacheDir, "nw.tar.gz"), cacheDir);
20
24
  } else {
21
25
  await Decompress(resolve(cacheDir, "nw.zip"), cacheDir);
22
26
  }
27
+ } else if (
28
+ downloadUrl ===
29
+ "https://github.com/corwin-of-amber/nw.js/releases/download"
30
+ ) {
31
+ await Decompress(resolve(cacheDir, "nw.zip"), cacheDir);
23
32
  } else if (
24
33
  downloadUrl ===
25
34
  "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
@@ -28,13 +28,25 @@ const download = (
28
28
  let url;
29
29
  let out;
30
30
  return new Promise((res, rej) => {
31
- if (downloadUrl === "https://dl.nwjs.io") {
31
+ if (
32
+ downloadUrl === "https://dl.nwjs.io" ||
33
+ downloadUrl === "https://npm.taobao.org/mirrors/nwjs" ||
34
+ downloadUrl === "https://npmmirror.com/mirrors/nwjs"
35
+ ) {
32
36
  url = `${downloadUrl}/v${version}/nwjs${
33
37
  flavor === "sdk" ? "-sdk" : ""
34
38
  }-v${version}-${platform}-${architecture}.${
35
39
  platform === "linux" ? "tar.gz" : "zip"
36
40
  }`;
37
41
  out = resolve(cacheDir, `nw.${platform === "linux" ? "tar.gz" : "zip"}`);
42
+ } else if (
43
+ downloadUrl ===
44
+ "https://github.com/corwin-of-amber/nw.js/releases/download"
45
+ ) {
46
+ url = `${downloadUrl}/nw-v${version}/nwjs-${
47
+ flavor === "sdk" ? "sdk-" : ""
48
+ }v${version}-${platform}-${architecture}.zip`;
49
+ out = resolve(cacheDir, `nw.zip`);
38
50
  } else if (
39
51
  downloadUrl ===
40
52
  "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
@@ -46,9 +58,14 @@ const download = (
46
58
  }
47
59
 
48
60
  https.get(url, (response) => {
61
+ // For GitHub releases, we need to follow the redirect
49
62
  if (
50
63
  downloadUrl ===
51
- "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
64
+ "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download" ||
65
+ downloadUrl ===
66
+ "https://github.com/corwin-of-amber/nw.js/releases/download" ||
67
+ downloadUrl === "https://npm.taobao.org/mirrors/nwjs" ||
68
+ downloadUrl === "https://npmmirror.com/mirrors/nwjs"
52
69
  ) {
53
70
  url = response.headers.location;
54
71
  }
@@ -9,25 +9,37 @@ import { getManifest } from "./getManifest.js";
9
9
  * Get version specific release metadata
10
10
  *
11
11
  * @param {string} version NW version
12
+ * @param {string} platform NW platform
13
+ * @param {string} arch NW architecture
12
14
  * @param {string} cacheDir Directory to store NW binaries
13
15
  * @param {string} manifestUrl Url to manifest
14
16
  * @return {object} Version specific release info
15
17
  */
16
- export const getReleaseInfo = async (version, cacheDir, manifestUrl) => {
18
+ export const getReleaseInfo = async (
19
+ version,
20
+ platform,
21
+ arch,
22
+ cacheDir,
23
+ manifestUrl,
24
+ ) => {
17
25
  let releaseData = undefined;
26
+ let manifestPath = undefined;
27
+ if (platform === "osx" && arch === "arm64") {
28
+ manifestPath = resolve(cacheDir, "manifest.mac.arm.json");
29
+ } else {
30
+ manifestPath = resolve(cacheDir, "manifest.json");
31
+ }
18
32
  try {
19
- await access(resolve(cacheDir, "manifest.json"));
33
+ await access(manifestPath);
20
34
  log.debug(`Manifest file already exists locally under ${cacheDir}`);
21
35
  } catch (e) {
22
36
  log.debug(`Manifest file does not exist locally`);
23
37
  log.debug(`Downloading latest manifest file under ${cacheDir}`);
24
38
  const data = await getManifest(manifestUrl);
25
- await writeFile(resolve(cacheDir, "manifest.json"), data.slice(9));
39
+ await writeFile(manifestPath, data.slice(9));
26
40
  } finally {
27
41
  log.debug("Store manifest metadata in memory");
28
- let manifest = JSON.parse(
29
- await readFile(resolve(cacheDir, "manifest.json")),
30
- );
42
+ let manifest = JSON.parse(await readFile(resolve(manifestPath)));
31
43
  log.debug(`Search for ${version} specific release data`);
32
44
  if (version === "latest" || version === "stable" || version === "lts") {
33
45
  // Remove leading "v" from version string
package/src/nwbuild.js CHANGED
@@ -5,13 +5,14 @@ import { decompress } from "./get/decompress.js";
5
5
  import { download } from "./get/download.js";
6
6
  import { getReleaseInfo } from "./get/getReleaseInfo.js";
7
7
  import { remove } from "./get/remove.js";
8
- import { packager } from "./bld/package.js";
8
+ import { build } from "./bld/build.js";
9
9
  import { develop } from "./run/develop.js";
10
10
  import { isCached } from "./util/cache.js";
11
11
  import { replaceFfmpeg } from "./util/ffmpeg.js";
12
12
  import { getOptions } from "./util/options.js";
13
13
  import { parse } from "./util/parse.js";
14
14
  import { validate } from "./util/validate.js";
15
+ import { xattr } from "./util/xattr.js";
15
16
 
16
17
  import { log } from "./log.js";
17
18
 
@@ -57,21 +58,21 @@ import { log } from "./log.js";
57
58
 
58
59
  /**
59
60
  * @typedef {object} Options
60
- * @property {string} [srcDir="./"] String of space separated glob patterns which correspond to NW app code
61
- * @property {"run" | "build"} [mode="build"] Run or build application
62
- * @property {"latest" | "stable" | string} [version="latest"] NW runtime version
63
- * @property {"normal" | "sdk"} [flavor="normal"] NW runtime build flavor
64
- * @property {"linux" | "osx" | "win"} platform NW supported platforms
65
- * @property {"ia32" | "x64"} arch NW supported architectures
66
- * @property {string} [outDir="./out"] Directory to store build artifacts
67
- * @property {"./cache" | string} [cacheDir="./cache"] Directory to store NW binaries
68
- * @property {"https://dl.nwjs.io"} [downloadUrl="https://dl.nwjs.io"] URI to download NW binaries from
69
- * @property {"https://nwjs.io/versions"} [manifestUrl="https://nwjs.io/versions"] URI to download manifest from
70
- * @property {App} app Multi platform configuration options
71
- * @property {boolean} [cache=true] If true the existing cache is used. Otherwise it removes and redownloads it.
72
- * @property {boolean} [zip=false] If true the outDir directory is zipped
73
- * @property {boolean} [cli=false] If true the CLI is used to glob srcDir and parse other options
74
- * @property {boolean} [ffmpeg=false] If true the chromium ffmpeg is replaced by community version
61
+ * @property {string} [srcDir="./"] String of space separated glob patterns which correspond to NW app code
62
+ * @property {"get" | "run" | "build"} [mode="build"] Run or build application
63
+ * @property {"latest" | "stable" | string} [version="latest"] NW runtime version
64
+ * @property {"normal" | "sdk"} [flavor="normal"] NW runtime build flavor
65
+ * @property {"linux" | "osx" | "win"} platform NW supported platforms
66
+ * @property {"ia32" | "x64" | "arm64"} arch NW supported architectures
67
+ * @property {string} [outDir="./out"] Directory to store build artifacts
68
+ * @property {"./cache" | string} [cacheDir="./cache"] Directory to store NW binaries
69
+ * @property {"https://dl.nwjs.io" | "https://npmmirror.com/mirrors/nwjs" | "https://npm.taobao.org/mirrors/nwjs"} [downloadUrl="https://dl.nwjs.io"] URI to download NW binaries from
70
+ * @property {"https://nwjs.io/versions"} [manifestUrl="https://nwjs.io/versions"] URI to download manifest from
71
+ * @property {App} app Multi platform configuration options
72
+ * @property {boolean} [cache=true] If true the existing cache is used. Otherwise it removes and redownloads it.
73
+ * @property {boolean} [zip=false] If true the outDir directory is zipped
74
+ * @property {boolean} [cli=false] If true the CLI is used to glob srcDir and parse other options
75
+ * @property {boolean} [ffmpeg=false] If true the chromium ffmpeg is replaced by community version
75
76
  */
76
77
 
77
78
  /**
@@ -110,6 +111,8 @@ const nwbuild = async (options) => {
110
111
  // Validate options.version to get the version specific release info
111
112
  releaseInfo = await getReleaseInfo(
112
113
  options.version,
114
+ options.platform,
115
+ options.arch,
113
116
  options.cacheDir,
114
117
  options.manifestUrl,
115
118
  );
@@ -121,7 +124,8 @@ const nwbuild = async (options) => {
121
124
  // Variable to store nwDir file path
122
125
  nwDir = resolve(
123
126
  options.cacheDir,
124
- `nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${options.platform
127
+ `nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${
128
+ options.platform
125
129
  }-${options.arch}`,
126
130
  );
127
131
 
@@ -144,10 +148,14 @@ const nwbuild = async (options) => {
144
148
  );
145
149
  await decompress(options.platform, options.cacheDir, options.downloadUrl);
146
150
  await remove(options.platform, options.cacheDir, options.downloadUrl);
151
+ } else {
152
+ log.debug("Using cached NW.js binaries");
147
153
  }
148
154
 
149
155
  if (options.ffmpeg === true) {
150
- log.warn("Using MP3 and H.264 codecs requires you to pay attention to the patent royalties and the license of the source code. Consult a lawyer if you do not understand the licensing constraints and using patented media formats in your app. See https://chromium.googlesource.com/chromium/third_party/ffmpeg.git/+/master/CREDITS.chromium for more information.");
156
+ log.warn(
157
+ "Using MP3 and H.264 codecs requires you to pay attention to the patent royalties and the license of the source code. Consult a lawyer if you do not understand the licensing constraints and using patented media formats in your app. See https://chromium.googlesource.com/chromium/third_party/ffmpeg.git/+/master/CREDITS.chromium for more information.",
158
+ );
151
159
  if (options.platform === "win") {
152
160
  ffmpegFile = "libffmpeg.dll";
153
161
  } else if (options.platform === "osx") {
@@ -189,11 +197,19 @@ const nwbuild = async (options) => {
189
197
  }
190
198
  }
191
199
 
200
+ await xattr(options.platform, options.arch, nwDir);
201
+
202
+ // Downloading binaries is required for run and build modes
203
+ // If mode is get, exit function since we have gotten the binaries
204
+ if (options.mode === "get") {
205
+ return undefined;
206
+ }
207
+
192
208
  if (options.mode === "run") {
193
209
  await develop(options.srcDir, nwDir, options.platform, options.argv);
194
210
  }
195
211
  if (options.mode === "build") {
196
- await packager(
212
+ await build(
197
213
  files,
198
214
  nwDir,
199
215
  options.outDir,
@@ -21,15 +21,6 @@ const execute = (srcDir, nwPath, argv) => {
21
21
  windowsHide: true,
22
22
  });
23
23
 
24
- nwProcess.on("nw_app_running", () => {
25
- log.debug("Kill NW process after confirming that it runs in CI.");
26
- nwProcess.kill("SIGKILL");
27
- });
28
-
29
- if (process.env.NODE_ENV !== "production") {
30
- nwProcess.emit("nw_app_running");
31
- }
32
-
33
24
  nwProcess.on("close", () => {
34
25
  resolve();
35
26
  });
package/src/util/arch.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Get user's computer architecture
3
3
  *
4
- * @param {string} arch Node's process.arch
5
- * @return {"ia32"| "x64" | "string"} NW.js supported architectures
4
+ * @param {string} arch Node's process.arch
5
+ * @return {"ia32"| "x64" | "arm64" | "string"} NW.js supported architectures
6
6
  */
7
7
  export const getArch = (arch) => {
8
8
  return arch;
package/src/util/cache.js CHANGED
@@ -3,8 +3,8 @@ import { access, constants } from "node:fs/promises";
3
3
  /**
4
4
  * Check if NW binaries are cached
5
5
  *
6
- * @param {string} nwDir Path to cached NW binaries
7
- * @return {boolean} Boolean value to denote if cache exists or not
6
+ * @param {string} nwDir Path to cached NW binaries
7
+ * @return {Promise<boolean>} Boolean value to denote if cache exists or not
8
8
  */
9
9
  export const isCached = async (nwDir) => {
10
10
  let exists = true;
@@ -1,5 +1,5 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { basename, resolve } from "node:path";
2
+ import { basename } from "node:path";
3
3
 
4
4
  import glob from "glob-promise";
5
5
 
@@ -26,10 +26,6 @@ export const getOptions = async (opts) => {
26
26
  files = [...patterns];
27
27
  }
28
28
 
29
- files.forEach((file, index) => {
30
- files[index] = resolve(file);
31
- });
32
-
33
29
  // Try to find the first instance of the package.json
34
30
  for (const file of files) {
35
31
  if (basename(file) === "package.json" && nwPkg === undefined) {
@@ -0,0 +1,17 @@
1
+ {
2
+ "latest": "v0.70.0",
3
+ "stable": "v0.70.0",
4
+ "lts": "v0.70.0",
5
+ "versions": [
6
+ {
7
+ "version": "v0.70.0",
8
+ "date": "2022/11/30",
9
+ "files": ["osx-arm64"],
10
+ "flavors": ["normal", "sdk"],
11
+ "components": {
12
+ "node": "19.0.0",
13
+ "chromium": "107.0.5304.88"
14
+ }
15
+ }
16
+ ]
17
+ }
package/src/util/parse.js CHANGED
@@ -16,17 +16,17 @@ export const parse = async (options, pkg) => {
16
16
  options = { ...pkg.nwbuild };
17
17
  }
18
18
 
19
- options.srcDir = resolve(options.srcDir) ?? resolve("./*");
19
+ options.srcDir = resolve(options.srcDir ?? "./*");
20
20
  options.mode = options.mode ?? "build";
21
21
  options.version = options.version ?? "latest";
22
22
  options.flavor = options.flavor || "normal";
23
23
  options.platform = options.platform ?? getPlatform(platform);
24
24
  options.arch = options.arch ?? getArch(arch);
25
- options.outDir = resolve(options.outDir) ?? resolve("./out");
26
- options.cacheDir = resolve(options.cacheDir) ?? resolve("./cache");
25
+ options.outDir = resolve(options.outDir ?? "./out");
26
+ options.cacheDir = resolve(options.cacheDir ?? "./cache");
27
27
  options.downloadUrl = options.downloadUrl ?? "https://dl.nwjs.io";
28
28
  options.manifestUrl = options.manifestUrl ?? "https://nwjs.io/versions";
29
- options.app = {};
29
+ options.app = options.app ?? {};
30
30
  options.argv = options.argv ?? [];
31
31
  // linux desktop entry file configurations options
32
32
  options.app.name = options.app.name ?? pkg.name;
@@ -1,17 +1,22 @@
1
+ import { version } from "node:process";
1
2
  import { readdir } from "node:fs/promises";
2
3
 
3
4
  /**
4
5
  * Validate options
5
6
  *
6
- * @param {object} options Options
7
- * @param {object} releaseInfo Version specific NW release info
8
- * @return {Promise<undefined>} True if options are valid. False otherwise
7
+ * @param {import("../nwbuild").Options} options Options
8
+ * @param {object} releaseInfo Version specific NW release info
9
+ * @return {Promise<undefined>} True if options are valid. False otherwise
9
10
  */
10
11
  export const validate = async (options, releaseInfo) => {
11
12
  if (options.srcDir === "") {
12
13
  throw new Error("srcDir is empty");
13
14
  }
14
- if (options.mode !== "run" && options.mode !== "build") {
15
+ if (
16
+ options.mode !== "get" &&
17
+ options.mode !== "run" &&
18
+ options.mode !== "build"
19
+ ) {
15
20
  throw new Error("Invalid mode value. Expected run or build.");
16
21
  }
17
22
  if (
@@ -20,11 +25,14 @@ export const validate = async (options, releaseInfo) => {
20
25
  !releaseInfo.files.includes(`${options.platform}-${options.arch}`)
21
26
  ) {
22
27
  throw new Error(
23
- `Platform ${options.platform} and architecture ${options.arch} is not supported. Sorry!`,
28
+ `Platform ${options.platform} and architecture ${options.arch} is not supported by this download server. Sorry!`,
24
29
  );
25
30
  }
26
31
  if (options.outDir) {
27
32
  await readdir(options.outDir);
28
33
  }
34
+ if (releaseInfo.components.node !== version.slice(1)) {
35
+ return new Error(`NW.js ${releaseInfo.version} requires Node.js v${releaseInfo.components.node} but you are using Node.js ${version.slice(1)}.`);
36
+ }
29
37
  return undefined;
30
38
  };
@@ -0,0 +1,30 @@
1
+ import { exec } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+
4
+ import { log } from "../log.js";
5
+
6
+ /**
7
+ * Remove the quarantine attribute from the app bundle
8
+ *
9
+ * @param {string} platform - The platform to build for
10
+ * @param {string} arch - The arch to build for
11
+ * @param {string} nwDir - The path to the nw directory
12
+ * @return {Promise<void>} - A promise that resolves when the attribute is removed
13
+ */
14
+ export const xattr = (platform, arch, nwDir) => {
15
+ return new Promise((res, rej) => {
16
+ if (platform === "osx" && arch === "arm64") {
17
+ let app = resolve(nwDir, "nwjs.app");
18
+ exec(`sudo xattr -d com.apple.quarantine ${app}`, (err, stdout) => {
19
+ log.debug(stdout);
20
+ if (err) {
21
+ rej(err);
22
+ } else {
23
+ res();
24
+ }
25
+ });
26
+ } else {
27
+ res();
28
+ }
29
+ });
30
+ };