nw-builder 4.0.11 → 4.1.0-beta.0
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 +10 -7
- package/package.json +24 -29
- package/src/bld/compress.js +8 -1
- package/src/bld/linuxCfg.js +3 -3
- package/src/bld/package.js +11 -7
- package/src/get/decompress.js +34 -28
- package/src/get/download.js +71 -29
- package/src/get/getReleaseInfo.js +19 -4
- package/src/get/remove.js +30 -13
- package/src/nwbuild.js +63 -9
- package/src/run/execute.js +1 -0
- package/src/run/getPlatformSpecificName.js +6 -0
- package/src/util/arch.js +2 -2
- package/src/util/ffmpeg.js +30 -0
- package/src/util/options.js +5 -1
- package/src/util/osx.arm.versions.json +17 -0
- package/src/util/parse.js +6 -4
- package/src/util/xattr.js +30 -0
- package/src/util/notify.js +0 -14
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Build [NW.js](https://github.com/nwjs/nw.js) applications for Mac, Windows and L
|
|
|
11
11
|
- [Usage](https://github.com/nwutils/nw-builder#usage)
|
|
12
12
|
- [Limitations](https://github.com/nwutils/nw-builder#limitations)
|
|
13
13
|
- [API Reference](https://nwutils.io/nw-builder/global#nwbuild)
|
|
14
|
+
- [Migration Guide](https://github.com/nwutils/nw-builder#migration)
|
|
14
15
|
- [Contributing](https://github.com/nwutils/nw-builder#contributing)
|
|
15
16
|
- [License](https://github.com/nwutils/nw-builder#license)
|
|
16
17
|
|
|
@@ -32,7 +33,7 @@ Module usage
|
|
|
32
33
|
import nwbuild from "nw-builder";
|
|
33
34
|
|
|
34
35
|
nwbuild({
|
|
35
|
-
srcDir: "./nwapp
|
|
36
|
+
srcDir: "./nwapp/*",
|
|
36
37
|
mode: "run",
|
|
37
38
|
version: "latest",
|
|
38
39
|
flavor: "sdk",
|
|
@@ -42,7 +43,7 @@ nwbuild({
|
|
|
42
43
|
CLI usage
|
|
43
44
|
|
|
44
45
|
```shell
|
|
45
|
-
nwbuild ./nwapp
|
|
46
|
+
nwbuild ./nwapp/* --mode=run --version=latest --flavor=sdk
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
package.json usage
|
|
@@ -54,7 +55,7 @@ package.json usage
|
|
|
54
55
|
"name": "nwdemo",
|
|
55
56
|
"main": "./index.html",
|
|
56
57
|
"nwbuild": {
|
|
57
|
-
"srcDir": "./nwapp
|
|
58
|
+
"srcDir": "./nwapp/*",
|
|
58
59
|
"mode": "run",
|
|
59
60
|
"version": "latest",
|
|
60
61
|
"flavor": "sdk"
|
|
@@ -70,7 +71,7 @@ Module usage
|
|
|
70
71
|
import nwbuild from "nw-builder";
|
|
71
72
|
|
|
72
73
|
nwbuild({
|
|
73
|
-
srcDir: "./nwapp
|
|
74
|
+
srcDir: "./nwapp/*",
|
|
74
75
|
mode: "build",
|
|
75
76
|
version: "latest",
|
|
76
77
|
flavor: "normal",
|
|
@@ -83,7 +84,7 @@ nwbuild({
|
|
|
83
84
|
CLI usage
|
|
84
85
|
|
|
85
86
|
```shell
|
|
86
|
-
nwbuild ./nwapp
|
|
87
|
+
nwbuild ./nwapp/* --mode=build --version=latest --flavor=normal --platform=linux --arch=x64 --outDir=./out
|
|
87
88
|
```
|
|
88
89
|
|
|
89
90
|
package.json usage
|
|
@@ -95,7 +96,7 @@ package.json usage
|
|
|
95
96
|
"name": "nwdemo",
|
|
96
97
|
"main": "./index.html",
|
|
97
98
|
"nwbuild": {
|
|
98
|
-
"srcDir": "./nwapp
|
|
99
|
+
"srcDir": "./nwapp/*",
|
|
99
100
|
"mode": "build",
|
|
100
101
|
"version": "latest",
|
|
101
102
|
"flavor": "normal",
|
|
@@ -112,7 +113,9 @@ For more options, check out the [API reference](https://nwutils.io/nw-builder/gl
|
|
|
112
113
|
|
|
113
114
|
- #716 File permissions are incorrectly set for Linux or MacOS apps built on Windows platform.
|
|
114
115
|
|
|
115
|
-
## Migration
|
|
116
|
+
## Migration
|
|
117
|
+
|
|
118
|
+
Migrate from v3 to v4
|
|
116
119
|
|
|
117
120
|
### Update `nw-builder`
|
|
118
121
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nw-builder",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.1.0-beta.0",
|
|
4
4
|
"description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NW.js",
|
|
@@ -8,11 +8,7 @@
|
|
|
8
8
|
"Desktop",
|
|
9
9
|
"Application"
|
|
10
10
|
],
|
|
11
|
-
"author":
|
|
12
|
-
"name": "Steffen Müller",
|
|
13
|
-
"email": "steffen@mllrsohn.com",
|
|
14
|
-
"url": "https://github.com/steffenmllr"
|
|
15
|
-
},
|
|
11
|
+
"author": "nw-builder Authors",
|
|
16
12
|
"license": "MIT",
|
|
17
13
|
"exports": {
|
|
18
14
|
"default": "./src/nwbuild.js"
|
|
@@ -28,37 +24,34 @@
|
|
|
28
24
|
"url": "https://github.com/nwutils/nw-builder.git"
|
|
29
25
|
},
|
|
30
26
|
"scripts": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
27
|
+
"fmt": "prettier --write \"./**/*.{css,html,js,json,md,yml}\"",
|
|
28
|
+
"lnt": "eslint ./src",
|
|
29
|
+
"doc": "jsdoc ./src/nwbuild.js -d docs",
|
|
30
|
+
"e2e": "node --test e2e/index.js",
|
|
34
31
|
"test:unit": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
35
|
-
"
|
|
36
|
-
"demo:
|
|
37
|
-
"demo:
|
|
38
|
-
"demo:osx": "cd ./test/e2e && node osx.js",
|
|
39
|
-
"demo:win": "cd ./test/e2e && node win.js"
|
|
32
|
+
"demo:esm": "cd e2e && node demo.js",
|
|
33
|
+
"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"
|
|
40
35
|
},
|
|
41
36
|
"devDependencies": {
|
|
42
|
-
"eslint": "^8.
|
|
37
|
+
"eslint": "^8.34.0",
|
|
43
38
|
"eslint-config-tjw-jsdoc": "^1.0.3",
|
|
44
|
-
"jest": "^29.
|
|
45
|
-
"jest-environment-jsdom": "^29.
|
|
46
|
-
"jsdoc": "^4.0.
|
|
47
|
-
"jsdom": "^21.
|
|
48
|
-
"prettier": "^2.
|
|
39
|
+
"jest": "^29.4.3",
|
|
40
|
+
"jest-environment-jsdom": "^29.4.3",
|
|
41
|
+
"jsdoc": "^4.0.2",
|
|
42
|
+
"jsdom": "^21.1.0",
|
|
43
|
+
"prettier": "^2.8.4",
|
|
44
|
+
"selenium-webdriver": "^4.8.0"
|
|
49
45
|
},
|
|
50
46
|
"dependencies": {
|
|
51
47
|
"archiver": "^5.3.1",
|
|
52
|
-
"cli-progress": "^3.
|
|
53
|
-
"
|
|
54
|
-
"glob-promise": "^6.0.
|
|
48
|
+
"cli-progress": "^3.12.0",
|
|
49
|
+
"decompress": "^4.2.1",
|
|
50
|
+
"glob-promise": "^6.0.2",
|
|
55
51
|
"plist": "^3.0.6",
|
|
56
|
-
"progress": "^2.0.3",
|
|
57
52
|
"rcedit": "^3.0.1",
|
|
58
|
-
"tar": "^6.1.11",
|
|
59
|
-
"update-notifier": "^6.0.2",
|
|
60
53
|
"winston": "^3.8.2",
|
|
61
|
-
"yargs": "^17.
|
|
54
|
+
"yargs": "^17.7.1"
|
|
62
55
|
},
|
|
63
56
|
"bin": {
|
|
64
57
|
"nwbuild": "./src/cli.js"
|
|
@@ -81,7 +74,7 @@
|
|
|
81
74
|
},
|
|
82
75
|
"eslintConfig": {
|
|
83
76
|
"parserOptions": {
|
|
84
|
-
"ecmaVersion":
|
|
77
|
+
"ecmaVersion": 2023,
|
|
85
78
|
"sourceType": "module"
|
|
86
79
|
},
|
|
87
80
|
"env": {
|
|
@@ -95,7 +88,9 @@
|
|
|
95
88
|
],
|
|
96
89
|
"rules": {
|
|
97
90
|
"jsdoc/require-file-overview": "off",
|
|
98
|
-
"jsdoc/
|
|
91
|
+
"jsdoc/require-returns-description": "off",
|
|
92
|
+
"jsdoc/match-description": "off",
|
|
93
|
+
"jsdoc/valid-types": "off"
|
|
99
94
|
}
|
|
100
95
|
},
|
|
101
96
|
"jest": {
|
package/src/bld/compress.js
CHANGED
|
@@ -3,13 +3,20 @@ import archiver from "archiver";
|
|
|
3
3
|
|
|
4
4
|
import { log } from "../log.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Compress a out directory
|
|
8
|
+
*
|
|
9
|
+
* @param {string} outDir - Output directory
|
|
10
|
+
* @param {string} type - Compression type
|
|
11
|
+
* @return {Promise<undefined>}
|
|
12
|
+
*/
|
|
6
13
|
const compress = (outDir, type = "zip") => {
|
|
7
14
|
const output = fs.createWriteStream(`${outDir}.${type}`);
|
|
8
15
|
const archive = archiver("zip");
|
|
9
16
|
|
|
10
17
|
return new Promise((res, rej) => {
|
|
11
18
|
output.on("close", () => {
|
|
12
|
-
res(
|
|
19
|
+
res();
|
|
13
20
|
});
|
|
14
21
|
|
|
15
22
|
archive.on("warning", (err) => {
|
package/src/bld/linuxCfg.js
CHANGED
|
@@ -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}
|
|
11
|
-
* @param {string}
|
|
12
|
-
* @return {
|
|
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/package.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
2
|
import { cp, rm } from "node:fs/promises";
|
|
3
3
|
|
|
4
4
|
import { log } from "../log.js";
|
|
@@ -34,13 +34,17 @@ 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
38
|
for (let file of files) {
|
|
38
39
|
log.debug(`Copy ${file} file to ${outDir} directory`);
|
|
39
40
|
await cp(
|
|
40
41
|
file,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
resolve(
|
|
43
|
+
outDir,
|
|
44
|
+
platform !== "osx"
|
|
45
|
+
? "package.nw"
|
|
46
|
+
: "nwjs.app/Contents/Resources/app.nw",
|
|
47
|
+
),
|
|
44
48
|
{
|
|
45
49
|
recursive: true,
|
|
46
50
|
},
|
|
@@ -50,13 +54,13 @@ const packager = async (
|
|
|
50
54
|
log.debug(`Starting platform specific config steps for ${platform}`);
|
|
51
55
|
switch (platform) {
|
|
52
56
|
case "linux":
|
|
53
|
-
setLinuxConfig(app, outDir);
|
|
57
|
+
await setLinuxConfig(app, outDir);
|
|
54
58
|
break;
|
|
55
59
|
case "win":
|
|
56
|
-
setWinConfig(app, outDir);
|
|
60
|
+
await setWinConfig(app, outDir);
|
|
57
61
|
break;
|
|
58
62
|
case "osx":
|
|
59
|
-
setOsxConfig(app, outDir, releaseInfo);
|
|
63
|
+
await setOsxConfig(app, outDir, releaseInfo);
|
|
60
64
|
break;
|
|
61
65
|
default:
|
|
62
66
|
break;
|
package/src/get/decompress.js
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import tar from "tar";
|
|
3
|
+
import Decompress from "decompress";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
5
|
+
import { log } from "../log.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Decompress NW.js binary
|
|
9
|
+
*
|
|
10
|
+
* @param {string} platform Platform
|
|
11
|
+
* @param {string} cacheDir Output directory
|
|
12
|
+
* @param {string} downloadUrl Download url
|
|
13
|
+
* @return {Promise<void>}
|
|
14
|
+
*/
|
|
15
|
+
const decompress = async (platform, cacheDir, downloadUrl) => {
|
|
16
|
+
try {
|
|
17
|
+
if (downloadUrl === "https://dl.nwjs.io") {
|
|
18
|
+
if (platform === "linux") {
|
|
19
|
+
await Decompress(resolve(cacheDir, "nw.tar.gz"), cacheDir);
|
|
20
|
+
} else {
|
|
21
|
+
await Decompress(resolve(cacheDir, "nw.zip"), cacheDir);
|
|
22
|
+
}
|
|
23
|
+
} else if (
|
|
24
|
+
downloadUrl ===
|
|
25
|
+
"https://github.com/corwin-of-amber/nw.js/releases/download"
|
|
26
|
+
) {
|
|
27
|
+
await Decompress(resolve(cacheDir, "nw.zip"), cacheDir);
|
|
28
|
+
} else if (
|
|
29
|
+
downloadUrl ===
|
|
30
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
|
|
31
|
+
) {
|
|
32
|
+
await Decompress(resolve(cacheDir, "ffmpeg.zip"), cacheDir);
|
|
30
33
|
}
|
|
31
|
-
})
|
|
34
|
+
} catch (error) {
|
|
35
|
+
log.error(error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
32
38
|
};
|
|
33
39
|
|
|
34
40
|
export { decompress };
|
package/src/get/download.js
CHANGED
|
@@ -1,53 +1,95 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import https from "https";
|
|
3
4
|
|
|
4
5
|
import progress from "cli-progress";
|
|
5
6
|
|
|
6
7
|
const bar = new progress.SingleBar({}, progress.Presets.rect);
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Download NW.js binary
|
|
11
|
+
*
|
|
12
|
+
* @param {string} version Version
|
|
13
|
+
* @param {string} flavor Flavor
|
|
14
|
+
* @param {string} platform Platform
|
|
15
|
+
* @param {string} architecture Architecture
|
|
16
|
+
* @param {string} downloadUrl Download url
|
|
17
|
+
* @param {string} cacheDir Output directory
|
|
18
|
+
* @return {Promise<void>}
|
|
19
|
+
*/
|
|
8
20
|
const download = (
|
|
9
21
|
version,
|
|
10
22
|
flavor,
|
|
11
23
|
platform,
|
|
12
24
|
architecture,
|
|
13
25
|
downloadUrl,
|
|
14
|
-
|
|
26
|
+
cacheDir,
|
|
15
27
|
) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
let url;
|
|
29
|
+
let out;
|
|
30
|
+
return new Promise((res, rej) => {
|
|
31
|
+
if (downloadUrl === "https://dl.nwjs.io") {
|
|
32
|
+
url = `${downloadUrl}/v${version}/nwjs${
|
|
33
|
+
flavor === "sdk" ? "-sdk" : ""
|
|
34
|
+
}-v${version}-${platform}-${architecture}.${
|
|
35
|
+
platform === "linux" ? "tar.gz" : "zip"
|
|
36
|
+
}`;
|
|
37
|
+
out = resolve(cacheDir, `nw.${platform === "linux" ? "tar.gz" : "zip"}`);
|
|
38
|
+
} else if (
|
|
39
|
+
downloadUrl ===
|
|
40
|
+
"https://github.com/corwin-of-amber/nw.js/releases/download"
|
|
41
|
+
) {
|
|
42
|
+
url = `${downloadUrl}/nw-v${version}/nwjs-${
|
|
43
|
+
flavor === "sdk" ? "sdk-" : ""
|
|
44
|
+
}v${version}-${platform}-${architecture}.zip`;
|
|
45
|
+
out = resolve(cacheDir, `nw.zip`);
|
|
46
|
+
} else if (
|
|
47
|
+
downloadUrl ===
|
|
48
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
|
|
49
|
+
) {
|
|
50
|
+
url = `${downloadUrl}/${version}/${version}-${platform}-${architecture}.zip`;
|
|
51
|
+
out = resolve(cacheDir, `ffmpeg.zip`);
|
|
52
|
+
} else {
|
|
53
|
+
rej(new Error("Invalid download url. Please try again."));
|
|
19
54
|
}
|
|
20
55
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
https.get(url, (response) => {
|
|
57
|
+
// For GitHub releases, we need to follow the redirect
|
|
58
|
+
if (
|
|
59
|
+
downloadUrl ===
|
|
60
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download" ||
|
|
61
|
+
downloadUrl ===
|
|
62
|
+
"https://github.com/corwin-of-amber/nw.js/releases/download"
|
|
63
|
+
) {
|
|
64
|
+
url = response.headers.location;
|
|
65
|
+
}
|
|
26
66
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
67
|
+
https.get(url, (response) => {
|
|
68
|
+
let chunks = 0;
|
|
69
|
+
bar.start(Number(response.headers["content-length"]), 0);
|
|
70
|
+
response.on("data", (chunk) => {
|
|
71
|
+
chunks += chunk.length;
|
|
72
|
+
bar.increment();
|
|
73
|
+
bar.update(chunks);
|
|
74
|
+
});
|
|
30
75
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
bar.update(chunks);
|
|
35
|
-
});
|
|
76
|
+
response.on("error", (error) => {
|
|
77
|
+
rej(error);
|
|
78
|
+
});
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
80
|
+
response.on("end", () => {
|
|
81
|
+
bar.stop();
|
|
82
|
+
res();
|
|
83
|
+
});
|
|
40
84
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
85
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
86
|
+
const stream = fs.createWriteStream(out);
|
|
87
|
+
response.pipe(stream);
|
|
44
88
|
});
|
|
45
89
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
res.pipe(stream);
|
|
90
|
+
response.on("error", (error) => {
|
|
91
|
+
rej(error);
|
|
92
|
+
});
|
|
51
93
|
});
|
|
52
94
|
});
|
|
53
95
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { access, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
2
3
|
|
|
3
4
|
import { log } from "../log.js";
|
|
4
5
|
|
|
@@ -8,23 +9,37 @@ import { getManifest } from "./getManifest.js";
|
|
|
8
9
|
* Get version specific release metadata
|
|
9
10
|
*
|
|
10
11
|
* @param {string} version NW version
|
|
12
|
+
* @param {string} platform NW platform
|
|
13
|
+
* @param {string} arch NW architecture
|
|
11
14
|
* @param {string} cacheDir Directory to store NW binaries
|
|
12
15
|
* @param {string} manifestUrl Url to manifest
|
|
13
16
|
* @return {object} Version specific release info
|
|
14
17
|
*/
|
|
15
|
-
export const getReleaseInfo = async (
|
|
18
|
+
export const getReleaseInfo = async (
|
|
19
|
+
version,
|
|
20
|
+
platform,
|
|
21
|
+
arch,
|
|
22
|
+
cacheDir,
|
|
23
|
+
manifestUrl,
|
|
24
|
+
) => {
|
|
16
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
|
+
}
|
|
17
32
|
try {
|
|
18
|
-
await access(
|
|
33
|
+
await access(manifestPath);
|
|
19
34
|
log.debug(`Manifest file already exists locally under ${cacheDir}`);
|
|
20
35
|
} catch (e) {
|
|
21
36
|
log.debug(`Manifest file does not exist locally`);
|
|
22
37
|
log.debug(`Downloading latest manifest file under ${cacheDir}`);
|
|
23
38
|
const data = await getManifest(manifestUrl);
|
|
24
|
-
await writeFile(
|
|
39
|
+
await writeFile(manifestPath, data.slice(9));
|
|
25
40
|
} finally {
|
|
26
41
|
log.debug("Store manifest metadata in memory");
|
|
27
|
-
let manifest = JSON.parse(await readFile(
|
|
42
|
+
let manifest = JSON.parse(await readFile(resolve(manifestPath)));
|
|
28
43
|
log.debug(`Search for ${version} specific release data`);
|
|
29
44
|
if (version === "latest" || version === "stable" || version === "lts") {
|
|
30
45
|
// Remove leading "v" from version string
|
package/src/get/remove.js
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
import { log } from "../log.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Remove NW.js binary
|
|
8
|
+
*
|
|
9
|
+
* @param {string} platform - linux, macos, win32
|
|
10
|
+
* @param {string} cacheDir - Output directory
|
|
11
|
+
* @param {string} downloadUrl - Download URL
|
|
12
|
+
* @return {Promise<void>} - Promise
|
|
13
|
+
*/
|
|
14
|
+
const remove = async (platform, cacheDir, downloadUrl) => {
|
|
15
|
+
try {
|
|
16
|
+
if (downloadUrl === "https://dl.nwjs.io/") {
|
|
17
|
+
if (platform === "linux") {
|
|
18
|
+
await rm(resolve(cacheDir, "nw.tar.gz"));
|
|
19
|
+
} else {
|
|
20
|
+
await rm(resolve(cacheDir, "nw.zip"));
|
|
21
|
+
}
|
|
22
|
+
} else if (
|
|
23
|
+
downloadUrl ===
|
|
24
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download"
|
|
25
|
+
) {
|
|
26
|
+
await rm(resolve(cacheDir, "ffmpeg.zip"));
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
log.error(error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
15
32
|
};
|
|
16
33
|
|
|
17
34
|
export { remove };
|
package/src/nwbuild.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
2
3
|
|
|
3
4
|
import { decompress } from "./get/decompress.js";
|
|
4
5
|
import { download } from "./get/download.js";
|
|
@@ -7,10 +8,11 @@ import { remove } from "./get/remove.js";
|
|
|
7
8
|
import { packager } from "./bld/package.js";
|
|
8
9
|
import { develop } from "./run/develop.js";
|
|
9
10
|
import { isCached } from "./util/cache.js";
|
|
10
|
-
import {
|
|
11
|
+
import { replaceFfmpeg } from "./util/ffmpeg.js";
|
|
11
12
|
import { getOptions } from "./util/options.js";
|
|
12
13
|
import { parse } from "./util/parse.js";
|
|
13
14
|
import { validate } from "./util/validate.js";
|
|
15
|
+
import { xattr } from "./util/xattr.js";
|
|
14
16
|
|
|
15
17
|
import { log } from "./log.js";
|
|
16
18
|
|
|
@@ -61,7 +63,7 @@ import { log } from "./log.js";
|
|
|
61
63
|
* @property {"latest" | "stable" | string} [version="latest"] NW runtime version
|
|
62
64
|
* @property {"normal" | "sdk"} [flavor="normal"] NW runtime build flavor
|
|
63
65
|
* @property {"linux" | "osx" | "win"} platform NW supported platforms
|
|
64
|
-
* @property {"ia32" | "x64"}
|
|
66
|
+
* @property {"ia32" | "x64" | "arm64"} arch NW supported architectures
|
|
65
67
|
* @property {string} [outDir="./out"] Directory to store build artifacts
|
|
66
68
|
* @property {"./cache" | string} [cacheDir="./cache"] Directory to store NW binaries
|
|
67
69
|
* @property {"https://dl.nwjs.io"} [downloadUrl="https://dl.nwjs.io"] URI to download NW binaries from
|
|
@@ -70,6 +72,7 @@ import { log } from "./log.js";
|
|
|
70
72
|
* @property {boolean} [cache=true] If true the existing cache is used. Otherwise it removes and redownloads it.
|
|
71
73
|
* @property {boolean} [zip=false] If true the outDir directory is zipped
|
|
72
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
|
|
73
76
|
*/
|
|
74
77
|
|
|
75
78
|
/**
|
|
@@ -80,13 +83,12 @@ import { log } from "./log.js";
|
|
|
80
83
|
*/
|
|
81
84
|
const nwbuild = async (options) => {
|
|
82
85
|
let nwDir = "";
|
|
86
|
+
let ffmpegFile = "";
|
|
83
87
|
let cached;
|
|
84
88
|
let nwCached;
|
|
85
89
|
let built;
|
|
86
90
|
let releaseInfo = {};
|
|
87
91
|
|
|
88
|
-
notify();
|
|
89
|
-
|
|
90
92
|
try {
|
|
91
93
|
const { opts, files, nwPkg } = await getOptions(options);
|
|
92
94
|
options = opts;
|
|
@@ -109,6 +111,8 @@ const nwbuild = async (options) => {
|
|
|
109
111
|
// Validate options.version to get the version specific release info
|
|
110
112
|
releaseInfo = await getReleaseInfo(
|
|
111
113
|
options.version,
|
|
114
|
+
options.platform,
|
|
115
|
+
options.arch,
|
|
112
116
|
options.cacheDir,
|
|
113
117
|
options.manifestUrl,
|
|
114
118
|
);
|
|
@@ -118,9 +122,12 @@ const nwbuild = async (options) => {
|
|
|
118
122
|
await validate(options, releaseInfo);
|
|
119
123
|
|
|
120
124
|
// Variable to store nwDir file path
|
|
121
|
-
nwDir =
|
|
122
|
-
options.
|
|
123
|
-
|
|
125
|
+
nwDir = resolve(
|
|
126
|
+
options.cacheDir,
|
|
127
|
+
`nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${
|
|
128
|
+
options.platform
|
|
129
|
+
}-${options.arch}`,
|
|
130
|
+
);
|
|
124
131
|
|
|
125
132
|
nwCached = await isCached(nwDir);
|
|
126
133
|
// Remove cached NW binary
|
|
@@ -139,10 +146,57 @@ const nwbuild = async (options) => {
|
|
|
139
146
|
options.downloadUrl,
|
|
140
147
|
options.cacheDir,
|
|
141
148
|
);
|
|
142
|
-
await decompress(options.platform, options.cacheDir);
|
|
143
|
-
await remove(options.platform, options.cacheDir);
|
|
149
|
+
await decompress(options.platform, options.cacheDir, options.downloadUrl);
|
|
150
|
+
await remove(options.platform, options.cacheDir, options.downloadUrl);
|
|
144
151
|
}
|
|
145
152
|
|
|
153
|
+
if (options.ffmpeg === true) {
|
|
154
|
+
log.warn(
|
|
155
|
+
"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
|
+
);
|
|
157
|
+
if (options.platform === "win") {
|
|
158
|
+
ffmpegFile = "libffmpeg.dll";
|
|
159
|
+
} else if (options.platform === "osx") {
|
|
160
|
+
ffmpegFile = "libffmpeg.dylib";
|
|
161
|
+
} else if (options.platform === "linux") {
|
|
162
|
+
ffmpegFile = "libffmpeg.so";
|
|
163
|
+
}
|
|
164
|
+
ffmpegFile = resolve(options.cacheDir, ffmpegFile);
|
|
165
|
+
const ffmpegCached = await isCached(ffmpegFile);
|
|
166
|
+
// Remove cached ffmpeg binary
|
|
167
|
+
if (options.cache === false && ffmpegCached === true) {
|
|
168
|
+
log.debug("Remove cached ffmpeg binary");
|
|
169
|
+
await rm(ffmpegFile, { force: true, recursive: true });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Download relevant ffmpeg binaries
|
|
173
|
+
if (ffmpegCached === false) {
|
|
174
|
+
log.debug("Download relevant ffmpeg binaries");
|
|
175
|
+
await download(
|
|
176
|
+
options.version,
|
|
177
|
+
options.flavor,
|
|
178
|
+
options.platform,
|
|
179
|
+
options.arch,
|
|
180
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download",
|
|
181
|
+
options.cacheDir,
|
|
182
|
+
);
|
|
183
|
+
await decompress(
|
|
184
|
+
options.platform,
|
|
185
|
+
options.cacheDir,
|
|
186
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download",
|
|
187
|
+
);
|
|
188
|
+
await remove(
|
|
189
|
+
options.platform,
|
|
190
|
+
options.cacheDir,
|
|
191
|
+
"https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download",
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
await replaceFfmpeg(options.platform, nwDir, ffmpegFile);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
await xattr(options.platform, options.arch, nwDir);
|
|
199
|
+
|
|
146
200
|
if (options.mode === "run") {
|
|
147
201
|
await develop(options.srcDir, nwDir, options.platform, options.argv);
|
|
148
202
|
}
|
package/src/run/execute.js
CHANGED
package/src/util/arch.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Get user's computer architecture
|
|
3
3
|
*
|
|
4
|
-
* @param {string}
|
|
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;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { copyFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Replaces the ffmpeg file in the nwjs directory with the one provided
|
|
6
|
+
*
|
|
7
|
+
* @param {string} platform The platform to replace the ffmpeg file for
|
|
8
|
+
* @param {string} nwDir The directory of the nwjs installation
|
|
9
|
+
* @param {string} ffmpegFile The path to the ffmpeg file to replace with
|
|
10
|
+
*/
|
|
11
|
+
export const replaceFfmpeg = async (platform, nwDir, ffmpegFile) => {
|
|
12
|
+
if (platform === "linux") {
|
|
13
|
+
await copyFile(ffmpegFile, resolve(nwDir, "lib", ffmpegFile));
|
|
14
|
+
} else if (platform === "win") {
|
|
15
|
+
await copyFile(ffmpegFile, resolve(nwDir, ffmpegFile));
|
|
16
|
+
} else if (platform === "osx") {
|
|
17
|
+
await copyFile(
|
|
18
|
+
ffmpegFile,
|
|
19
|
+
resolve(
|
|
20
|
+
nwDir,
|
|
21
|
+
"Contents",
|
|
22
|
+
"Frameworks",
|
|
23
|
+
"nwjs Framework.framework",
|
|
24
|
+
"Versions",
|
|
25
|
+
"Current",
|
|
26
|
+
ffmpegFile,
|
|
27
|
+
),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
};
|
package/src/util/options.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { basename } from "node:path";
|
|
2
|
+
import { basename, resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
import glob from "glob-promise";
|
|
5
5
|
|
|
@@ -26,6 +26,10 @@ 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
|
+
|
|
29
33
|
// Try to find the first instance of the package.json
|
|
30
34
|
for (const file of files) {
|
|
31
35
|
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
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { arch, platform } from "node:process";
|
|
2
3
|
|
|
3
4
|
import { getArch } from "./arch.js";
|
|
4
5
|
import { getPlatform } from "./platform.js";
|
|
@@ -15,14 +16,14 @@ export const parse = async (options, pkg) => {
|
|
|
15
16
|
options = { ...pkg.nwbuild };
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
options.srcDir =
|
|
19
|
+
options.srcDir = resolve(options.srcDir) ?? resolve("./*");
|
|
19
20
|
options.mode = options.mode ?? "build";
|
|
20
21
|
options.version = options.version ?? "latest";
|
|
21
22
|
options.flavor = options.flavor || "normal";
|
|
22
23
|
options.platform = options.platform ?? getPlatform(platform);
|
|
23
24
|
options.arch = options.arch ?? getArch(arch);
|
|
24
|
-
options.outDir = options.outDir ?? "./out";
|
|
25
|
-
options.cacheDir = options.cacheDir ??
|
|
25
|
+
options.outDir = resolve(options.outDir) ?? resolve("./out");
|
|
26
|
+
options.cacheDir = resolve(options.cacheDir) ?? resolve("./cache");
|
|
26
27
|
options.downloadUrl = options.downloadUrl ?? "https://dl.nwjs.io";
|
|
27
28
|
options.manifestUrl = options.manifestUrl ?? "https://nwjs.io/versions";
|
|
28
29
|
options.app = {};
|
|
@@ -66,5 +67,6 @@ export const parse = async (options, pkg) => {
|
|
|
66
67
|
options.app.specialBuild = options.app.specialBuild ?? undefined;
|
|
67
68
|
options.cache = options.cache ?? true;
|
|
68
69
|
options.zip = options.zip ?? false;
|
|
70
|
+
options.ffmpeg = options.ffmpeg ?? false;
|
|
69
71
|
return options;
|
|
70
72
|
};
|
|
@@ -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
|
+
};
|
package/src/util/notify.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
const require = createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
import updateNotifier from "update-notifier";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Notify the user if there is a new version of the package available.
|
|
8
|
-
*
|
|
9
|
-
* @return {Promise<void>}
|
|
10
|
-
*/
|
|
11
|
-
export const notify = async () => {
|
|
12
|
-
const packageJson = require("../../package.json");
|
|
13
|
-
updateNotifier({ pkg: packageJson }).notify();
|
|
14
|
-
};
|