nw-builder 4.0.2 → 4.0.4
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/.github/dependabot.yml +2 -4
- package/.github/workflows/cd.yml +1 -0
- package/.github/workflows/ci.yml +3 -4
- package/README.md +324 -0
- package/package.json +16 -9
- package/src/bld/linuxCfg.js +34 -16
- package/src/bld/osxCfg.js +40 -44
- package/src/bld/package.js +29 -25
- package/src/bld/winCfg.js +42 -14
- package/src/cli.js +9 -6
- package/src/get/download.js +5 -7
- package/src/get/getReleaseInfo.js +4 -0
- package/src/nwbuild.js +172 -71
- package/src/run/develop.js +23 -7
- package/src/run/execute.js +22 -6
- package/src/util/arch.js +9 -0
- package/src/util/arch.test.js +9 -0
- package/src/util/cache.js +17 -0
- package/src/util/cache.test.js +9 -0
- package/src/util/parse.js +70 -0
- package/src/util/parse.test.js +5 -0
- package/src/util/platform.js +18 -0
- package/src/util/platform.test.js +13 -0
- package/src/util/validate.js +30 -0
- package/test/{demo/bld.cjs → e2e/bld.js} +13 -5
- package/test/e2e/nix.js +11 -0
- package/test/{demo → e2e}/nwapp/index.html +0 -0
- package/test/e2e/nwapp/package.json +6 -0
- package/test/e2e/osx.js +11 -0
- package/test/e2e/win.js +11 -0
- package/test/fixture/cacheDir/nw +0 -0
- package/docs/index.md +0 -112
- package/nwbuild.cjs +0 -113
- package/test/demo/nwapp/package.json +0 -4
package/src/bld/winCfg.js
CHANGED
|
@@ -2,27 +2,55 @@ import { rename } from "node:fs/promises";
|
|
|
2
2
|
|
|
3
3
|
import rcedit from "rcedit";
|
|
4
4
|
|
|
5
|
+
import { log } from "../log.js";
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Windows specific configuration steps
|
|
9
|
+
* https://learn.microsoft.com/en-us/windows/win32/msi/version
|
|
10
|
+
* https://learn.microsoft.com/en-gb/windows/win32/sbscs/application-manifests
|
|
11
|
+
* https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2015/deployment/trustinfo-element-clickonce-application?view=vs-2015#requestedexecutionlevel
|
|
12
|
+
* https://learn.microsoft.com/en-gb/windows/win32/menurc/versioninfo-resource
|
|
7
13
|
*
|
|
8
|
-
* @param {object}
|
|
14
|
+
* @param {object} app Multi platform configuration options
|
|
9
15
|
* @param {string} outDir The directory to hold build artifacts
|
|
10
16
|
*/
|
|
11
|
-
const setWinConfig = async (
|
|
12
|
-
|
|
17
|
+
const setWinConfig = async (app, outDir) => {
|
|
18
|
+
let versionString = {
|
|
19
|
+
Comments: app.comments,
|
|
20
|
+
CompanyName: app.author,
|
|
21
|
+
FileDescription: app.fileDescription,
|
|
22
|
+
FileVersion: app.fileVersion,
|
|
23
|
+
InternalName: app.name,
|
|
24
|
+
LegalCopyright: app.legalCopyright,
|
|
25
|
+
LegalTrademarks: app.legalTrademark,
|
|
26
|
+
OriginalFilename: app.name,
|
|
27
|
+
PrivateBuild: app.name,
|
|
28
|
+
ProductName: app.name,
|
|
29
|
+
ProductVersion: app.version,
|
|
30
|
+
SpecialBuild: app.name,
|
|
31
|
+
};
|
|
13
32
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"icon": pkg.icon,
|
|
19
|
-
"version-string": {
|
|
20
|
-
FileDescription: pkg.description,
|
|
21
|
-
LegalCopyright: pkg.copyright,
|
|
22
|
-
ProductName: pkg.name,
|
|
23
|
-
OriginalFilename: pkg.name,
|
|
24
|
-
},
|
|
33
|
+
Object.keys(versionString).forEach((option) => {
|
|
34
|
+
if (versionString[option] === undefined) {
|
|
35
|
+
delete versionString[option];
|
|
36
|
+
}
|
|
25
37
|
});
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await rename(`${outDir}/nw.exe`, `${outDir}/${app.name}.exe`);
|
|
41
|
+
|
|
42
|
+
await rcedit(`${outDir}/${app.name}.exe`, {
|
|
43
|
+
"file-version": app.version,
|
|
44
|
+
"icon": app.icon,
|
|
45
|
+
"product-version": app.version,
|
|
46
|
+
"version-string": versionString,
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
log.warn(
|
|
50
|
+
"Unable to modify EXE. Ensure WINE is installed or build in Windows",
|
|
51
|
+
);
|
|
52
|
+
log.error(error);
|
|
53
|
+
}
|
|
26
54
|
};
|
|
27
55
|
|
|
28
56
|
export { setWinConfig };
|
package/src/cli.js
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
import yargs from "yargs/yargs";
|
|
4
4
|
import { hideBin } from "yargs/helpers";
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import nwbuild from "./nwbuild.js";
|
|
7
7
|
|
|
8
8
|
const cli = yargs(hideBin(process.argv))
|
|
9
9
|
.version(false)
|
|
10
10
|
.command("[srcDir] [options]")
|
|
11
|
+
.option("mode", {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "`run` or `build` application",
|
|
14
|
+
})
|
|
11
15
|
.option("version", {
|
|
12
16
|
type: "string",
|
|
13
17
|
description: "NW.js version",
|
|
14
18
|
})
|
|
15
|
-
.option("
|
|
19
|
+
.option("flavor", {
|
|
16
20
|
type: "string",
|
|
17
|
-
description: "NW.js build
|
|
21
|
+
description: "NW.js build flavor",
|
|
18
22
|
})
|
|
19
23
|
.option("platform", {
|
|
20
24
|
type: "string",
|
|
@@ -28,10 +32,9 @@ const cli = yargs(hideBin(process.argv))
|
|
|
28
32
|
type: "string",
|
|
29
33
|
description: "NW.js build artifacts",
|
|
30
34
|
})
|
|
31
|
-
.demandOption(["version", "flavour", "platform", "arch", "outDir"])
|
|
32
35
|
.parse();
|
|
33
36
|
|
|
34
37
|
nwbuild({
|
|
35
38
|
...cli,
|
|
36
|
-
srcDir: cli._
|
|
37
|
-
});
|
|
39
|
+
srcDir: cli._.join(" "),
|
|
40
|
+
});
|
package/src/get/download.js
CHANGED
|
@@ -7,7 +7,7 @@ const bar = new progress.SingleBar({}, progress.Presets.rect);
|
|
|
7
7
|
|
|
8
8
|
const download = (
|
|
9
9
|
version,
|
|
10
|
-
|
|
10
|
+
flavor,
|
|
11
11
|
platform,
|
|
12
12
|
architecture,
|
|
13
13
|
downloadUrl,
|
|
@@ -15,12 +15,11 @@ const download = (
|
|
|
15
15
|
) => {
|
|
16
16
|
return new Promise((resolve, reject) => {
|
|
17
17
|
if (downloadUrl !== "https://dl.nwjs.io") {
|
|
18
|
-
|
|
19
|
-
reject(1);
|
|
18
|
+
reject(new Error("Invalid download url. Please try again."));
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
let url = `${downloadUrl}/v${version}/nwjs${
|
|
23
|
-
|
|
22
|
+
flavor === "sdk" ? "-sdk" : ""
|
|
24
23
|
}-v${version}-${platform}-${architecture}.${
|
|
25
24
|
platform === "linux" ? "tar.gz" : "zip"
|
|
26
25
|
}`;
|
|
@@ -36,13 +35,12 @@ const download = (
|
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
res.on("error", (error) => {
|
|
39
|
-
|
|
40
|
-
reject(1);
|
|
38
|
+
reject(error);
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
res.on("end", () => {
|
|
44
42
|
bar.stop();
|
|
45
|
-
resolve(
|
|
43
|
+
resolve();
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
fs.mkdirSync(outDir, { recursive: true });
|
|
@@ -28,6 +28,10 @@ export const getReleaseInfo = async (version, cacheDir, manifestUrl) => {
|
|
|
28
28
|
log.debug("Convert manifest data into JSON");
|
|
29
29
|
let manifestJson = JSON.parse(manifestData);
|
|
30
30
|
log.debug(`Search for ${version} specific release data`);
|
|
31
|
+
if (version === "latest" || version === "stable" || version === "lts") {
|
|
32
|
+
version = manifestData[version].slice(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
releaseData = manifestJson.versions.find(
|
|
32
36
|
(release) => release.version === `v${version}`,
|
|
33
37
|
);
|
package/src/nwbuild.js
CHANGED
|
@@ -1,96 +1,197 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { mkdir, readFile, rm } from "node:fs/promises";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
|
|
4
|
+
import glob from "glob-promise";
|
|
3
5
|
|
|
4
6
|
import { decompress } from "./get/decompress.js";
|
|
5
|
-
import { develop } from "./run/develop.js";
|
|
6
7
|
import { download } from "./get/download.js";
|
|
7
8
|
import { getReleaseInfo } from "./get/getReleaseInfo.js";
|
|
8
9
|
import { remove } from "./get/remove.js";
|
|
9
10
|
import { packager } from "./bld/package.js";
|
|
11
|
+
import { develop } from "./run/develop.js";
|
|
12
|
+
import { isCached } from "./util/cache.js";
|
|
13
|
+
import { parse } from "./util/parse.js";
|
|
14
|
+
import { validate } from "./util/validate.js";
|
|
15
|
+
|
|
16
|
+
import { log } from "./log.js";
|
|
10
17
|
|
|
11
18
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* @property {string}
|
|
16
|
-
* @property {
|
|
17
|
-
* @property {string}
|
|
18
|
-
* @property {
|
|
19
|
-
* @property {
|
|
20
|
-
* @property {
|
|
21
|
-
* @property {string}
|
|
19
|
+
* @typedef {object} App
|
|
20
|
+
* @property {string} name Name of the application
|
|
21
|
+
* Linux configuration options
|
|
22
|
+
* @property {string} genericName Generic name of the application
|
|
23
|
+
* @property {boolean} noDisplay If true the application is not displayed
|
|
24
|
+
* @property {string} comment Tooltip for the entry, for example "View sites on the Internet".
|
|
25
|
+
* @property {string} icon Icon to display in file manager, menus, etc.
|
|
26
|
+
* @property {boolean} hidden TBD
|
|
27
|
+
* @property {string[]} onlyShowIn A list of strings identifying the desktop environments that should (/not) display a given desktop entry
|
|
28
|
+
* @property {string[]} notShowIn A list of strings identifying the desktop environments that should (/not) display a given desktop entry
|
|
29
|
+
* @property {boolean} dBusActivatable A boolean value specifying if D-Bus activation is supported for this application
|
|
30
|
+
* @property {string} tryExec Path to an executable file on disk used to determine if the program is actually installed
|
|
31
|
+
* @property {string} exec Program to execute, possibly with arguments.
|
|
32
|
+
* @property {string} path If entry is of type Application, the working directory to run the program in.
|
|
33
|
+
* @property {boolean} terminal Whether the program runs in a terminal window.
|
|
34
|
+
* @property {string[]} actions Identifiers for application actions.
|
|
35
|
+
* @property {string[]} mimeType The MIME type(s) supported by this application.
|
|
36
|
+
* @property {string[]} categories Categories in which the entry should be shown in a menu
|
|
37
|
+
* @property {string[]} implements A list of interfaces that this application implements.
|
|
38
|
+
* @property {string[]} keywords A list of strings which may be used in addition to other metadata to describe this entry.
|
|
39
|
+
* @property {boolean} startupNotify If true, it is KNOWN that the application will send a "remove" message when started with the DESKTOP_STARTUP_ID environment variable set. If false, it is KNOWN that the application does not work with startup notification at all.
|
|
40
|
+
* @property {string} startupWMClass If specified, it is known that the application will map at least one window with the given string as its WM class or WM name hin
|
|
41
|
+
* @property {boolean} prefersNonDefaultGPU If true, the application prefers to be run on a more powerful discrete GPU if available.
|
|
42
|
+
* @property {string} singleMainWindow If true, the application has a single main window, and does not support having an additional one opened.
|
|
43
|
+
* Windows configuration options
|
|
44
|
+
* @property {string} comments Additional information that should be displayed for diagnostic purposes.
|
|
45
|
+
* @property {string} company Company that produced the file—for example, Microsoft Corporation or Standard Microsystems Corporation, Inc. This string is required.
|
|
46
|
+
* @property {string} fileDescription File description to be presented to users. This string may be displayed in a list box when the user is choosing files to install. For example, Keyboard Driver for AT-Style Keyboards. This string is required.
|
|
47
|
+
* @property {string} fileVersion Version number of the file. For example, 3.10 or 5.00.RC2. This string is required.
|
|
48
|
+
* @property {string} internalName Internal name of the file, if one exists—for example, a module name if the file is a dynamic-link library. If the file has no internal name, this string should be the original filename, without extension. This string is required.
|
|
49
|
+
* @property {string} legalCopyright Copyright notices that apply to the file. This should include the full text of all notices, legal symbols, copyright dates, and so on. This string is optional.
|
|
50
|
+
* @property {string} legalTrademark Trademarks and registered trademarks that apply to the file. This should include the full text of all notices, legal symbols, trademark numbers, and so on. This string is optional.
|
|
51
|
+
* @property {string} originalFilename Original name of the file, not including a path. This information enables an application to determine whether a file has been renamed by a user. The format of the name depends on the file system for which the file was created. This string is required.
|
|
52
|
+
* @property {string} privateBuild Information about a private version of the file—for example, Built by TESTER1 on \\TESTBED. This string should be present only if VS_FF_PRIVATEBUILD is specified in the fileflags parameter of the root block.
|
|
53
|
+
* @property {string} productName Name of the product with which the file is distributed. This string is required.
|
|
54
|
+
* @property {string} productVersion Version of the product with which the file is distributed—for example, 3.10 or 5.00.RC2. This string is required.
|
|
55
|
+
* @property {string} specialBuild Text that specifies how this version of the file differs from the standard version—for example, Private build for TESTER1 solving mouse problems on M250 and M250E computers. This string should be present only if VS_FF_SPECIALBUILD is specified in the fileflags parameter of the root block.
|
|
22
56
|
*/
|
|
23
57
|
|
|
24
58
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @
|
|
27
|
-
* @
|
|
59
|
+
* @typedef {object} Options
|
|
60
|
+
* @property {string} srcDir Directory to hold NW app files unless or array of file glob patterns
|
|
61
|
+
* @property {"run" | "build"} mode Run or build application
|
|
62
|
+
* @property {"latest" | "stable" | string} version NW runtime version
|
|
63
|
+
* @property {"normal" | "sdk"} flavor 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 Directory to store build artifacts
|
|
67
|
+
* @property {"./cache" | string} cacheDir Directory to store NW binaries
|
|
68
|
+
* @property {"https://dl.nwjs.io"} downloadUrl URI to download NW binaries from
|
|
69
|
+
* @property {"https://nwjs.io/versions"} manifestUrl URI to download manifest from
|
|
70
|
+
* @property {App} app Multi platform configuration options
|
|
71
|
+
* @property {boolean} cache If true the existing cache is used. Otherwise it removes and redownloads it.
|
|
72
|
+
* @property {boolean} zip If true the outDir directory is zipped
|
|
28
73
|
*/
|
|
29
|
-
const nwbuild = async ({
|
|
30
|
-
srcDir,
|
|
31
|
-
cacheDir = `${cwd()}/cache`,
|
|
32
|
-
version,
|
|
33
|
-
flavour,
|
|
34
|
-
platform,
|
|
35
|
-
arch,
|
|
36
|
-
outDir,
|
|
37
|
-
// flags
|
|
38
|
-
downloadUrl = "https://dl.nwjs.io",
|
|
39
|
-
manifestUrl = "https://nwjs.io/versions",
|
|
40
|
-
noCache = false,
|
|
41
|
-
zip = false,
|
|
42
|
-
run = false,
|
|
43
|
-
}) => {
|
|
44
|
-
let pkgPath = `${srcDir}/package.json`;
|
|
45
|
-
let pkgExist = true;
|
|
46
|
-
let pkgData = null;
|
|
47
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Entry point for nw-builder application
|
|
77
|
+
*
|
|
78
|
+
* @param {...Options} options Options
|
|
79
|
+
* @return {Promise<undefined>}
|
|
80
|
+
*/
|
|
81
|
+
const nwbuild = async (options) => {
|
|
82
|
+
let nwDir = "";
|
|
83
|
+
let nwPkg = undefined;
|
|
84
|
+
let cached;
|
|
85
|
+
let built;
|
|
86
|
+
let releaseInfo = {};
|
|
48
87
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
pkgExist = false;
|
|
52
|
-
}
|
|
88
|
+
let files = [];
|
|
89
|
+
let patterns = options.srcDir.split(" ");
|
|
53
90
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
platform = pkgData.nwbuild.platform ?? platform;
|
|
63
|
-
arch = pkgData.nwbuild.arch ?? arch;
|
|
64
|
-
outDir = pkgData.nwbuild.outDir ?? outDir;
|
|
91
|
+
for (const pattern of patterns) {
|
|
92
|
+
let contents = await glob(pattern);
|
|
93
|
+
for (const content of contents) {
|
|
94
|
+
if (basename(content) === "package.json" && nwPkg === undefined) {
|
|
95
|
+
nwPkg = JSON.parse(await readFile(content));
|
|
96
|
+
}
|
|
97
|
+
files.push(...contents);
|
|
98
|
+
}
|
|
65
99
|
}
|
|
66
|
-
}
|
|
67
100
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
101
|
+
if (files.length === 0) {
|
|
102
|
+
throw new Error(`The globbing pattern ${options.srcDir} is invalid.`);
|
|
103
|
+
}
|
|
71
104
|
|
|
72
|
-
|
|
105
|
+
// The name property is required for NW.js applications
|
|
106
|
+
if (nwPkg.name === undefined) {
|
|
107
|
+
throw new Error(`name property is missing from package.json`);
|
|
108
|
+
}
|
|
73
109
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
110
|
+
// The main property is required for NW.js applications
|
|
111
|
+
if (nwPkg.main === undefined) {
|
|
112
|
+
throw new Error(`main property is missing from package.json`);
|
|
113
|
+
}
|
|
79
114
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
115
|
+
// If the nwbuild property exists in srcDir/package.json, then they take precedence
|
|
116
|
+
if (typeof nwPkg.nwbuild === "object") {
|
|
117
|
+
options = { ...nwPkg.nwbuild };
|
|
118
|
+
}
|
|
119
|
+
if (typeof nwPkg.nwbuild === "undefined") {
|
|
120
|
+
log.debug(`nwbuild property is not defined in package.json`);
|
|
121
|
+
} else {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`nwbuild property in the package.json is of type ${typeof nwPkg.nwbuild}. Expected type object.`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Parse options, set required values to undefined and flags with default values unless specified by user
|
|
128
|
+
options = await parse(options, nwPkg);
|
|
86
129
|
|
|
87
|
-
|
|
130
|
+
// Variable to store nwDir file path
|
|
131
|
+
nwDir = `${options.cacheDir}/nwjs${
|
|
132
|
+
options.flavor === "sdk" ? "-sdk" : ""
|
|
133
|
+
}-v${options.version}-${options.platform}-${options.arch}`;
|
|
134
|
+
|
|
135
|
+
// Create cacheDir if it does not exist
|
|
136
|
+
cached = await isCached(nwDir);
|
|
137
|
+
if (cached === false) {
|
|
138
|
+
await mkdir(nwDir, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Create outDir if it does not exist
|
|
142
|
+
built = await isCached(options.outDir);
|
|
143
|
+
if (built === false) {
|
|
144
|
+
await mkdir(options.outDir, { recursive: true });
|
|
145
|
+
}
|
|
88
146
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
147
|
+
// Validate options.version here
|
|
148
|
+
// We need to do this to get the version specific release info
|
|
149
|
+
releaseInfo = await getReleaseInfo(
|
|
150
|
+
options.version,
|
|
151
|
+
options.cacheDir,
|
|
152
|
+
options.manifestUrl,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
validate(options, releaseInfo);
|
|
156
|
+
|
|
157
|
+
// Remove cached NW binary
|
|
158
|
+
if (options.cache === false && cached === true) {
|
|
159
|
+
log.debug("Remove cached NW binary");
|
|
160
|
+
await rm(nwDir, { force: true, recursive: true });
|
|
161
|
+
}
|
|
162
|
+
// Download relevant NW.js binaries
|
|
163
|
+
if (cached === false) {
|
|
164
|
+
log.debug("Download relevant NW.js binaries");
|
|
165
|
+
await download(
|
|
166
|
+
options.version,
|
|
167
|
+
options.flavor,
|
|
168
|
+
options.platform,
|
|
169
|
+
options.arch,
|
|
170
|
+
options.downloadUrl,
|
|
171
|
+
options.cacheDir,
|
|
172
|
+
);
|
|
173
|
+
await decompress(options.platform, options.cacheDir);
|
|
174
|
+
await remove(options.platform, options.cacheDir);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (options.mode === "run") {
|
|
178
|
+
await develop(options.srcDir, nwDir, options.platform, options.argv);
|
|
179
|
+
}
|
|
180
|
+
if (options.mode === "build") {
|
|
181
|
+
await packager(
|
|
182
|
+
files,
|
|
183
|
+
nwDir,
|
|
184
|
+
options.outDir,
|
|
185
|
+
options.platform,
|
|
186
|
+
options.zip,
|
|
187
|
+
releaseInfo,
|
|
188
|
+
options.app,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
log.error(error);
|
|
193
|
+
return error;
|
|
93
194
|
}
|
|
94
195
|
};
|
|
95
196
|
|
|
96
|
-
export
|
|
197
|
+
export default nwbuild;
|
package/src/run/develop.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { execute } from "./execute.js";
|
|
2
2
|
import { getPlatformSpecificName } from "./getPlatformSpecificName.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
if (getPlatformSpecificName(platform) === null) {
|
|
6
|
-
console.log("Unsupported platform.");
|
|
7
|
-
return 1;
|
|
8
|
-
}
|
|
4
|
+
import { log } from "../log.js";
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Runs the NW app by spawning a child process
|
|
8
|
+
*
|
|
9
|
+
* @param {string} srcDir The directory to run from
|
|
10
|
+
* @param {string} nwDir The directory to run nw.js from
|
|
11
|
+
* @param {"win" | "osx" | "linux"} platform The platform to run for
|
|
12
|
+
* @param {string[]} argv The arguments to pass to the nw.js development server
|
|
13
|
+
* @return {Promise<undefined>}
|
|
14
|
+
*/
|
|
15
|
+
const develop = async (srcDir, nwDir, platform, argv) => {
|
|
16
|
+
try {
|
|
17
|
+
if (getPlatformSpecificName(platform) === null) {
|
|
18
|
+
throw new Error("Unsupported platform.");
|
|
19
|
+
}
|
|
20
|
+
await execute(
|
|
21
|
+
srcDir,
|
|
22
|
+
`${nwDir}/${getPlatformSpecificName(platform)}`,
|
|
23
|
+
argv,
|
|
24
|
+
);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
log.error(error);
|
|
27
|
+
}
|
|
12
28
|
};
|
|
13
29
|
|
|
14
30
|
export { develop };
|
package/src/run/execute.js
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { log } from "../log.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Executes the NW.js process
|
|
7
|
+
* @param {string} srcDir The source directory
|
|
8
|
+
* @param {string} nwPath The path to the NW.js executable
|
|
9
|
+
* @param {string} argv The arguments to pass to the NW.js process
|
|
10
|
+
* @return {Promise<undefined>} The exit code of the NW.js process
|
|
11
|
+
* @throws {Error} - If the NW.js process fails to start
|
|
12
|
+
*/
|
|
13
|
+
const execute = (srcDir, nwPath, argv) => {
|
|
4
14
|
return new Promise((resolve, reject) => {
|
|
5
|
-
|
|
15
|
+
// It is assumed that the first glob pattern p contains the package.json at p/package.json
|
|
16
|
+
srcDir = srcDir.split(" ")[0];
|
|
17
|
+
srcDir = srcDir.replace(/\*[/*]*/, "");
|
|
18
|
+
const nwProcess = spawn(nwPath, [srcDir.concat(argv)], {
|
|
19
|
+
detached: true,
|
|
20
|
+
windowsHide: true,
|
|
21
|
+
});
|
|
6
22
|
|
|
7
23
|
nwProcess.on("close", () => {
|
|
8
|
-
resolve(
|
|
24
|
+
resolve();
|
|
9
25
|
});
|
|
10
26
|
|
|
11
27
|
nwProcess.on("error", (error) => {
|
|
12
|
-
|
|
13
|
-
reject(
|
|
28
|
+
log.error(error);
|
|
29
|
+
reject(error);
|
|
14
30
|
});
|
|
15
31
|
});
|
|
16
32
|
};
|
package/src/util/arch.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { access, constants } from "node:fs/promises";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if NW binaries are cached
|
|
5
|
+
*
|
|
6
|
+
* @param {string} nwDir Path to cached NW binaries
|
|
7
|
+
* @return {Promise<boolean>} Boolean value to denote if cache exists or not
|
|
8
|
+
*/
|
|
9
|
+
export const isCached = async (nwDir) => {
|
|
10
|
+
let exists = true;
|
|
11
|
+
try {
|
|
12
|
+
await access(nwDir, constants.F_OK);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
exists = false;
|
|
15
|
+
}
|
|
16
|
+
return exists;
|
|
17
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { arch, cwd, platform } from "node:process";
|
|
2
|
+
|
|
3
|
+
import { getArch } from "./arch.js";
|
|
4
|
+
import { getPlatform } from "./platform.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parse options
|
|
8
|
+
*
|
|
9
|
+
* @param {import("../nwbuild").Options} options Options
|
|
10
|
+
* @param {object} pkg Package.json as JSON
|
|
11
|
+
* @return {Promise<object>} Options
|
|
12
|
+
*/
|
|
13
|
+
export const parse = async (options, pkg) => {
|
|
14
|
+
if (typeof pkg?.nwbuild === "object") {
|
|
15
|
+
options = { ...pkg.nwbuild };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
options.srcDir = options.srcDir ?? "./";
|
|
19
|
+
options.mode = options.mode ?? "build";
|
|
20
|
+
options.version = options.version ?? "latest";
|
|
21
|
+
options.flavor = options.flavor || "normal";
|
|
22
|
+
options.platform = options.platform ?? getPlatform(platform);
|
|
23
|
+
options.arch = options.arch ?? getArch(arch);
|
|
24
|
+
options.outDir = options.outDir ?? "./out";
|
|
25
|
+
options.cacheDir = options.cacheDir ?? `${cwd()}/cache`;
|
|
26
|
+
options.downloadUrl = options.downloadUrl ?? "https://dl.nwjs.io";
|
|
27
|
+
options.manifestUrl = options.manifestUrl ?? "https://nwjs.io/versions";
|
|
28
|
+
options.app = {};
|
|
29
|
+
options.argv = options.argv ?? [];
|
|
30
|
+
// linux desktop entry file configurations options
|
|
31
|
+
options.app.name = options.app.name ?? pkg.name;
|
|
32
|
+
options.app.genericName = options.app.genericName ?? undefined;
|
|
33
|
+
options.app.noDisplay = options.app.noDisplay ?? undefined;
|
|
34
|
+
options.app.comment = options.app.comment ?? undefined;
|
|
35
|
+
options.app.icon = options.app.icon ?? undefined;
|
|
36
|
+
options.app.hidden = options.app.hidden ?? undefined;
|
|
37
|
+
options.app.onlyShowIn = options.app.onlyShowIn ?? undefined;
|
|
38
|
+
options.app.notShowIn = options.app.notShowIn ?? undefined;
|
|
39
|
+
options.app.dBusActivatable = options.app.dBusActivatable ?? undefined;
|
|
40
|
+
options.app.tryExec = options.app.tryExec ?? undefined;
|
|
41
|
+
options.app.exec = options.app.name ?? undefined;
|
|
42
|
+
options.app.path = options.app.path ?? undefined;
|
|
43
|
+
options.app.terminal = options.app.terminal ?? undefined;
|
|
44
|
+
options.app.actions = options.app.actions ?? undefined;
|
|
45
|
+
options.app.mimeType = options.app.mimeType ?? undefined;
|
|
46
|
+
options.app.categories = options.app.categories ?? undefined;
|
|
47
|
+
options.app.implements = options.app.implements ?? undefined;
|
|
48
|
+
options.app.keywords = options.app.keywords ?? undefined;
|
|
49
|
+
options.app.startupNotify = options.app.startupNotify ?? undefined;
|
|
50
|
+
options.app.startupWMClass = options.app.startupWMClass ?? undefined;
|
|
51
|
+
options.app.prefersNonDefaultGPU =
|
|
52
|
+
options.app.prefersNonDefaultGPU ?? undefined;
|
|
53
|
+
options.app.singleMainWindow = options.app.singleMainWindow ?? undefined;
|
|
54
|
+
// windows configuration options
|
|
55
|
+
options.app.comments = options.app.comments ?? undefined;
|
|
56
|
+
options.app.company = options.app.company ?? pkg.author;
|
|
57
|
+
options.app.fileDescription = options.app.fileDescription ?? pkg.description;
|
|
58
|
+
options.app.fileVersion = options.app.fileVersion ?? pkg.version;
|
|
59
|
+
options.app.internalName = options.app.internalName ?? pkg.name;
|
|
60
|
+
options.app.legalCopyright = options.app.legalCopyright ?? undefined;
|
|
61
|
+
options.app.legalTrademark = options.app.legalTrademark ?? undefined;
|
|
62
|
+
options.app.originalFilename = options.app.originalFilename ?? pkg.name;
|
|
63
|
+
options.app.privateBuild = options.app.privateBuild ?? undefined;
|
|
64
|
+
options.app.productName = options.app.productName ?? pkg.name;
|
|
65
|
+
options.app.productVersion = options.app.productVersion ?? pkg.version;
|
|
66
|
+
options.app.specialBuild = options.app.specialBuild ?? undefined;
|
|
67
|
+
options.cache = options.cache ?? true;
|
|
68
|
+
options.zip = options.zip ?? false;
|
|
69
|
+
return options;
|
|
70
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get user's computer platform
|
|
3
|
+
*
|
|
4
|
+
* @param {string} platform Node's process.platform
|
|
5
|
+
* @return {"osx"| "win" | "linux" | "string"} Platform types
|
|
6
|
+
*/
|
|
7
|
+
export const getPlatform = (platform) => {
|
|
8
|
+
switch (platform) {
|
|
9
|
+
case "darwin":
|
|
10
|
+
return "osx";
|
|
11
|
+
case "win32":
|
|
12
|
+
return "win";
|
|
13
|
+
case "linux":
|
|
14
|
+
return "linux";
|
|
15
|
+
default:
|
|
16
|
+
return platform;
|
|
17
|
+
}
|
|
18
|
+
};
|