nw-builder 4.19.2 → 4.21.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/README.md +94 -23
- package/package.json +16 -8
- package/src/cli.js +24 -7
- package/src/index.d.ts +5 -3
- package/src/index.js +52 -11
- package/src/util.js +177 -18
- package/src/postinstall.js +0 -19
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ See `nw-builder` in action by building the demo application.
|
|
|
98
98
|
|
|
99
99
|
## Concepts
|
|
100
100
|
|
|
101
|
-
`nw-builder` can get, run and
|
|
101
|
+
`nw-builder` can get, run, build and package NW.js applications. We refer to them as get, run, build and package modes.
|
|
102
102
|
|
|
103
103
|
### Get Mode
|
|
104
104
|
|
|
@@ -184,32 +184,103 @@ nwbuild({
|
|
|
184
184
|
});
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
+
### Package Mode
|
|
188
|
+
|
|
189
|
+
Builds the application, then packages the `outDir` produced by the build via
|
|
190
|
+
[`@nwutils/packager`](https://www.npmjs.com/package/@nwutils/packager). `mode: "package"` resolves with the path to the resulting packaged artifact instead of `undefined`.
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const packagePath = await nwbuild({
|
|
194
|
+
mode: "package",
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`format` selects the packager to run and defaults to `"AppImage"` on Linux. Only `"AppImage"` is implemented today - `deb`, `rpm`, `msix`, `nsis` and `dmg` are reserved for later.
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const appImagePath = await nwbuild({
|
|
202
|
+
mode: "package",
|
|
203
|
+
format: "AppImage",
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Signing
|
|
208
|
+
|
|
209
|
+
Set `sign` to embed a GPG signature in the AppImage. It needs `gpg` on the host
|
|
210
|
+
with the secret key imported. `signKey` picks the key, defaulting to `gpg`'s
|
|
211
|
+
default secret key. A passphrase protected key reads its passphrase from the
|
|
212
|
+
`APPIMAGETOOL_SIGN_PASSPHRASE` environment variable.
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
await nwbuild({
|
|
216
|
+
mode: "package",
|
|
217
|
+
sign: true,
|
|
218
|
+
signKey: "ABCDEF1234567890",
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Self updating
|
|
223
|
+
|
|
224
|
+
Set `publish` to where releases are uploaded to make the AppImage self updatable
|
|
225
|
+
with [`@nwutils/updater`](https://www.npmjs.com/package/@nwutils/updater). An
|
|
226
|
+
`app-update.yml` pointing at `publish` is embedded in the AppImage, and a
|
|
227
|
+
`latest-linux.yml` update info file holding the app's `package.json` `version`
|
|
228
|
+
is written next to it. Upload both to every release.
|
|
229
|
+
|
|
230
|
+
Set `updateInformation: true` to also support zsync based updaters such as
|
|
231
|
+
AppImageUpdate - this needs `zsyncmake` on the host, and the `.zsync` file
|
|
232
|
+
written next to the AppImage must be uploaded too.
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"name": "demo",
|
|
237
|
+
"version": "1.2.0",
|
|
238
|
+
"nwbuild": {
|
|
239
|
+
"mode": "package",
|
|
240
|
+
"platform": "linux",
|
|
241
|
+
"app": { "name": "Demo" },
|
|
242
|
+
"publish": { "provider": "github", "owner": "nwutils", "repo": "demo" },
|
|
243
|
+
"updateInformation": true
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
With the CLI, pass `--publish.provider=github --publish.owner=nwutils
|
|
249
|
+
--publish.repo=demo`. See the
|
|
250
|
+
[`@nwutils/packager` docs](https://www.npmjs.com/package/@nwutils/packager) for
|
|
251
|
+
the `generic` provider and more details.
|
|
252
|
+
|
|
187
253
|
## API Reference
|
|
188
254
|
|
|
189
255
|
Options
|
|
190
256
|
|
|
191
|
-
| Name
|
|
192
|
-
|
|
|
193
|
-
| mode
|
|
194
|
-
| version
|
|
195
|
-
| flavor
|
|
196
|
-
| platform
|
|
197
|
-
| arch
|
|
198
|
-
| downloadUrl
|
|
199
|
-
| manifestUrl
|
|
200
|
-
| cacheDir
|
|
201
|
-
| cache
|
|
202
|
-
| ffmpeg
|
|
203
|
-
| logLevel
|
|
204
|
-
| shaSum
|
|
205
|
-
| srcDir
|
|
206
|
-
| argv
|
|
207
|
-
| glob
|
|
208
|
-
| outDir
|
|
209
|
-
| managedManifest
|
|
210
|
-
| nodeAddon
|
|
211
|
-
| zip
|
|
212
|
-
|
|
|
257
|
+
| Name | Type | Default | Description |
|
|
258
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
259
|
+
| mode | `"get" \| "run" \| "build" \| "package"` | `"build"` | Choose between get, run, build or package mode |
|
|
260
|
+
| version | `string \| "latest" \| "stable"` | `"latest"` | Runtime version |
|
|
261
|
+
| flavor | `"normal" \| "sdk"` | `"normal"` | Runtime flavor |
|
|
262
|
+
| platform | `"linux" \| "osx" \| "win"` | | Host platform |
|
|
263
|
+
| arch | `"ia32" \| "x64" \| "arm64"` | | Host architecture |
|
|
264
|
+
| downloadUrl | `"https://dl.nwjs.io" \| "https://npm.taobao.org/mirrors/nwjs" \| https://npmmirror.com/mirrors/nwjs \| "https://github.com/corwin-of-amber/nw.js/releases/"` | `"https://dl.nwjs.io"` | Download server. Supports file systems too (for example `file:///home/localghost/nwjs_mirror`) |
|
|
265
|
+
| manifestUrl | `"https://nwjs.io/versions.json" \| "https://raw.githubusercontent.com/nwutils/nw-builder/main/src/util/osx.arm.versions.json"` | `"https://nwjs.io/versions.json"` | Versions manifest URI, gotten via https or local file |
|
|
266
|
+
| cacheDir | `string` | `"./cache"` | Directory to cache NW binaries |
|
|
267
|
+
| cache | `boolean` | `true` | If true the existing cache is used. Otherwise it removes and redownloads it. |
|
|
268
|
+
| ffmpeg | `boolean` | `false` | If true the chromium ffmpeg is replaced by community version with proprietary codecs. |
|
|
269
|
+
| logLevel | `"error" \| "warn" \| "info" \| "debug"` | `"info"` | Specify level of logging. |
|
|
270
|
+
| shaSum | `boolean` | `true` | Flag to enable/disable shasum checks. |
|
|
271
|
+
| srcDir | `string` | `"./"` | File paths to application code |
|
|
272
|
+
| argv | `string[]` | `[]` | Command line arguments to pass to NW executable in run mode. You can also define these in `chromium-args` in NW.js manifest. |
|
|
273
|
+
| glob | `boolean` | `true` | If true file globbing is enabled when parsing `srcDir`. |
|
|
274
|
+
| outDir | `string` | `"./out"` | Directory to store build artifacts |
|
|
275
|
+
| managedManifest | `boolean \| string \| object` | `false` | Managed manifest |
|
|
276
|
+
| nodeAddon | `boolean` | `false` | Rebuild Node native addons |
|
|
277
|
+
| zip | `boolean \| "zip" \| "tar" \| "tgz"` | `false` | If true, "zip", "tar" or "tgz" the `outDir` directory is compressed. |
|
|
278
|
+
| format | `"AppImage" \| "deb" \| "rpm" \| "msix" \| "nsis" \| "dmg"` | `"AppImage"` on Linux | Packaged output format, used in package mode. Only `"AppImage"` is implemented today. |
|
|
279
|
+
| sign | `boolean` | `false` | If true, embed a GPG signature in the AppImage. Used in package mode. |
|
|
280
|
+
| signKey | `string` | | ID of the GPG key to sign with. Requires `sign`. Used in package mode. |
|
|
281
|
+
| publish | `{provider: "github", owner, repo} \| {provider: "generic", url}` | | Where releases are published. Makes the AppImage self updatable with `@nwutils/updater`. Used in package mode. |
|
|
282
|
+
| updateInformation | `boolean \| string` | | AppImage zsync update information. `true` derives it from `publish`. Used in package mode. |
|
|
283
|
+
| app | `LinuxRc \| WinRc \| OsxRc` | Additional options for each platform. (See below.) |
|
|
213
284
|
|
|
214
285
|
### `app` configuration object
|
|
215
286
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nw-builder",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.4",
|
|
4
4
|
"description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NW.js",
|
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
"directory": "./packages/nw-builder"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
|
-
"postinstall": "node ./src/postinstall.js",
|
|
46
45
|
"lint": "eslint ./src ../../tests/specs/nw-builder",
|
|
47
46
|
"lint:fix": "eslint --fix ./src ../../tests/specs/nw-builder",
|
|
48
47
|
"type": "tsc",
|
|
@@ -55,15 +54,24 @@
|
|
|
55
54
|
"demo:exe:win": "../../tests/fixtures/nw-builder/out/win/Demo.exe",
|
|
56
55
|
"demo:cli": "nwbuild --mode=build --flavor=sdk --glob=false --cacheDir=./node_modules/nw --logLevel=debug --managedManifest=../../tests/fixtures/nw-builder/app/package.json --outDir=../../tests/fixtures/nw-builder/out/linux --app.name=Demo --app.icon=../../tests/fixtures/nw-builder/app/icon.png ../../tests/fixtures/nw-builder/app"
|
|
57
56
|
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"base-volta-off-of-nwjs": "^1.0.5",
|
|
60
|
-
"nw": "^0.115.0"
|
|
61
|
-
},
|
|
62
57
|
"dependencies": {
|
|
63
|
-
"@nwutils/builder": "^0.1.
|
|
58
|
+
"@nwutils/builder": "^0.1.2",
|
|
64
59
|
"@nwutils/getter": "^0.2.5",
|
|
65
|
-
"@nwutils/
|
|
60
|
+
"@nwutils/packager": "^0.5.0",
|
|
61
|
+
"@nwutils/runner": "^0.2.6",
|
|
66
62
|
"commander": "^15.0.0",
|
|
67
63
|
"glob": "^13.0.6"
|
|
64
|
+
},
|
|
65
|
+
"devEngines": {
|
|
66
|
+
"runtime": {
|
|
67
|
+
"name": "node",
|
|
68
|
+
"version": "26.7.0",
|
|
69
|
+
"onFail": "warn"
|
|
70
|
+
},
|
|
71
|
+
"packageManager": {
|
|
72
|
+
"name": "npm",
|
|
73
|
+
"version": "12.0.2",
|
|
74
|
+
"onFail": "warn"
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
77
|
}
|
package/src/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import util from "./util.js";
|
|
|
8
8
|
|
|
9
9
|
program
|
|
10
10
|
.argument("<string>", "File path(s) to project")
|
|
11
|
-
.option("--mode <string>", "get, run or
|
|
11
|
+
.option("--mode <string>", "get, run, build or package mode", "build")
|
|
12
12
|
.option("--version <string>", "NW.js version", "latest")
|
|
13
13
|
.option("--flavor <string>", "NW.js build flavor", "normal")
|
|
14
14
|
.option(
|
|
@@ -38,7 +38,6 @@ program
|
|
|
38
38
|
.option(
|
|
39
39
|
"--app <object>",
|
|
40
40
|
"Platform specific app metadata. Refer to docs for more info",
|
|
41
|
-
/** @type {any} */ ({}),
|
|
42
41
|
)
|
|
43
42
|
.option("--cache <boolean>", "Enable/disable caching", true)
|
|
44
43
|
.option("--ffmpeg <boolean>", "Enable/disable community ffmpeg", false)
|
|
@@ -48,18 +47,33 @@ program
|
|
|
48
47
|
.option("--zip <string>", "Enable/disable compression", false)
|
|
49
48
|
.option("--managedManifest <string>", "Managed manifest mode", false)
|
|
50
49
|
.option("--nodeAddon <boolean>", "Download NW.js Node headers", false)
|
|
50
|
+
.option("--format <string>", "Packaged output format, used in package mode")
|
|
51
|
+
.option(
|
|
52
|
+
"--sign <boolean>",
|
|
53
|
+
"Sign the AppImage with GPG, used in package mode",
|
|
54
|
+
)
|
|
55
|
+
.option(
|
|
56
|
+
"--signKey <string>",
|
|
57
|
+
"GPG key to sign the AppImage with, used in package mode",
|
|
58
|
+
)
|
|
59
|
+
.option(
|
|
60
|
+
"--updateInformation <string>",
|
|
61
|
+
"AppImage zsync update information, or true to derive it from --publish.*",
|
|
62
|
+
)
|
|
51
63
|
.allowUnknownOption(true)
|
|
52
64
|
.allowExcessArguments(true);
|
|
53
65
|
|
|
54
|
-
// Handle unknown --app.* arguments
|
|
66
|
+
// Handle unknown --app.* and --publish.* arguments
|
|
55
67
|
const unknownArgs = program.parse(process.argv).args;
|
|
56
68
|
/** @type {Record<string, string>} */
|
|
57
69
|
const appConfig = {};
|
|
70
|
+
/** @type {Record<string, string>} */
|
|
71
|
+
const publishConfig = {};
|
|
58
72
|
for (const arg of unknownArgs) {
|
|
59
|
-
const match = arg.match(/^--app\.([^.=]+)=(.*)$/);
|
|
73
|
+
const match = arg.match(/^--(app|publish)\.([^.=]+)=(.*)$/);
|
|
60
74
|
if (match) {
|
|
61
|
-
const [, key, value] = match;
|
|
62
|
-
appConfig[key] = value;
|
|
75
|
+
const [, group, key, value] = match;
|
|
76
|
+
(group === "app" ? appConfig : publishConfig)[key] = value;
|
|
63
77
|
}
|
|
64
78
|
}
|
|
65
79
|
|
|
@@ -67,7 +81,10 @@ for (const arg of unknownArgs) {
|
|
|
67
81
|
const opts = {
|
|
68
82
|
...program.opts(),
|
|
69
83
|
app: appConfig,
|
|
70
|
-
|
|
84
|
+
publish: Object.keys(publishConfig).length > 0 ? publishConfig : undefined,
|
|
85
|
+
srcDir: program.args.find(
|
|
86
|
+
(arg) => !arg.startsWith("--app") && !arg.startsWith("--publish"),
|
|
87
|
+
),
|
|
71
88
|
cli: true,
|
|
72
89
|
};
|
|
73
90
|
|
package/src/index.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export type SupportedPlatform = "linux" | "osx" | "win";
|
|
|
8
8
|
export interface Options<P extends SupportedPlatform = SupportedPlatform> {
|
|
9
9
|
/** String of space separated glob patterns which correspond to NW app code */
|
|
10
10
|
srcDir?: "./" | string;
|
|
11
|
-
/** Run or
|
|
12
|
-
mode?: "build" | "get" | "run";
|
|
11
|
+
/** Run, build or package application */
|
|
12
|
+
mode?: "build" | "get" | "run" | "package";
|
|
13
13
|
/** NW runtime version */
|
|
14
14
|
version?: "latest" | "stable" | string;
|
|
15
15
|
/** NW runtime flavor */
|
|
@@ -42,6 +42,8 @@ export interface Options<P extends SupportedPlatform = SupportedPlatform> {
|
|
|
42
42
|
logLevel?: "error" | "warn" | "info" | "debug";
|
|
43
43
|
/** Managed manifest */
|
|
44
44
|
managedManifest?: boolean | string | object;
|
|
45
|
+
/** Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux. Only `"AppImage"` is implemented today - the others are reserved. */
|
|
46
|
+
format?: "AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg";
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/** Platform-specific application options */
|
|
@@ -183,6 +185,6 @@ export interface OsxAppOptions {
|
|
|
183
185
|
*/
|
|
184
186
|
declare function nwbuild<P extends SupportedPlatform>(
|
|
185
187
|
options: Options<P>,
|
|
186
|
-
): Promise<ChildProcess | null | undefined>;
|
|
188
|
+
): Promise<ChildProcess | string | null | undefined>;
|
|
187
189
|
|
|
188
190
|
export default nwbuild;
|
package/src/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import path from "node:path";
|
|
|
5
5
|
|
|
6
6
|
import bld from "@nwutils/builder";
|
|
7
7
|
import get from "@nwutils/getter";
|
|
8
|
+
import pkg from "@nwutils/packager";
|
|
8
9
|
import run from "@nwutils/runner";
|
|
9
10
|
|
|
10
11
|
import util from "./util.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @typedef {object} Options Configuration options
|
|
14
|
-
* @property {"get" | "run" | "build"}
|
|
15
|
+
* @property {"get" | "run" | "build" | "package"} [mode="build"] Choose between get, run, build or package mode
|
|
15
16
|
* @property {"latest" | "stable" | string} [version="latest"] Runtime version
|
|
16
17
|
* @property {"normal" | "sdk"} [flavor="normal"] Runtime flavor
|
|
17
18
|
* @property {"linux" | "osx" | "win"} [platform] Host platform
|
|
@@ -21,17 +22,22 @@ import util from "./util.js";
|
|
|
21
22
|
* @property {"./cache" | string} [cacheDir="./cache"] Directory to cache NW binaries
|
|
22
23
|
* @property {string | string[]} [srcDir="./"] File paths to application code
|
|
23
24
|
* @property {"./out" | string} [outDir="./out"] Directory to store build artifacts
|
|
24
|
-
* @property {
|
|
25
|
+
* @property {import("./util.js").AppOptions} [app] Refer to Linux/Windows Specific Options under Getting Started in the docs
|
|
25
26
|
* @property {boolean} [cache=true] If true the existing cache is used. Otherwise it removes and redownloads it.
|
|
26
27
|
* @property {boolean} [ffmpeg=false] If true the chromium ffmpeg is replaced by community version
|
|
27
28
|
* @property {boolean} [glob=true] If true file globbing is enabled when parsing srcDir.
|
|
28
29
|
* @property {"error" | "warn" | "info" | "debug"} [logLevel="info"] Specify level of logging.
|
|
29
30
|
* @property {boolean} [shaSum = true] If true, shasum is enabled. Otherwise, disabled.
|
|
30
31
|
* @property {boolean | "zip" | "tar" | "tgz"} [zip=false] If true, "zip", "tar" or "tgz" the outDir directory is compressed.
|
|
31
|
-
* @property {boolean | string |
|
|
32
|
+
* @property {boolean | string | Record<string, unknown>} [managedManifest = false] Managed manifest mode
|
|
32
33
|
* @property {boolean} [nativeAddon = false] Get Node native addons
|
|
33
34
|
* @property {boolean} [cli=false] If true the CLI is used to parse options. This option is used internally.
|
|
34
35
|
* @property {string[]} [argv = []] CLI arguments passed to the NW.js process in run mode
|
|
36
|
+
* @property {"AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg"} [format] Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux. Only `"AppImage"` is implemented today - the others are reserved.
|
|
37
|
+
* @property {boolean} [sign=false] If true, embed a GPG signature in the AppImage, used in package mode.
|
|
38
|
+
* @property {string} [signKey] ID of the GPG key to sign the AppImage with, used in package mode. Requires `sign`.
|
|
39
|
+
* @property {import("@nwutils/packager").PublishOptions} [publish] Where releases are published, used in package mode. Makes the AppImage self updatable with `@nwutils/updater`.
|
|
40
|
+
* @property {boolean | string} [updateInformation] AppImage zsync update information, used in package mode. `true` derives it from `publish`.
|
|
35
41
|
*/
|
|
36
42
|
|
|
37
43
|
/**
|
|
@@ -39,12 +45,12 @@ import util from "./util.js";
|
|
|
39
45
|
* @async
|
|
40
46
|
* @function
|
|
41
47
|
* @param {Options} options Options
|
|
42
|
-
* @returns {Promise<child_process.ChildProcess | null | undefined>} - Returns NW.js process
|
|
48
|
+
* @returns {Promise<child_process.ChildProcess | string | null | undefined>} - Returns the NW.js process in run mode, the path to the packaged artifact in package mode, otherwise returns `undefined`.
|
|
43
49
|
*/
|
|
44
50
|
async function nwbuild(options) {
|
|
45
51
|
let built;
|
|
46
52
|
let releaseInfo;
|
|
47
|
-
/** @type {{path: string, json:
|
|
53
|
+
/** @type {{path: string, json: import("./util.js").PackageManifest | undefined}} */
|
|
48
54
|
let manifest = {
|
|
49
55
|
path: "",
|
|
50
56
|
json: undefined,
|
|
@@ -52,7 +58,9 @@ async function nwbuild(options) {
|
|
|
52
58
|
|
|
53
59
|
try {
|
|
54
60
|
/* Parse options */
|
|
55
|
-
options =
|
|
61
|
+
options = /** @type {Options} */ (
|
|
62
|
+
await util.parse(options, manifest.json ?? {})
|
|
63
|
+
);
|
|
56
64
|
util.log("debug", "info", "Parse initial options");
|
|
57
65
|
|
|
58
66
|
util.log("debug", "info", "Get node manifest...");
|
|
@@ -69,8 +77,9 @@ async function nwbuild(options) {
|
|
|
69
77
|
/** @type {"debug" | "error" | "info" | "warn"} */ (options.logLevel),
|
|
70
78
|
"Parse final options using node manifest",
|
|
71
79
|
);
|
|
72
|
-
/** @type {Required<Options>} */
|
|
73
|
-
|
|
80
|
+
const resolved = /** @type {Required<Options>} */ (
|
|
81
|
+
await util.parse(options, manifest.json ?? {})
|
|
82
|
+
);
|
|
74
83
|
util.log(
|
|
75
84
|
"debug",
|
|
76
85
|
resolved.logLevel,
|
|
@@ -113,7 +122,9 @@ async function nwbuild(options) {
|
|
|
113
122
|
);
|
|
114
123
|
|
|
115
124
|
/* Remove leading "v" from version string */
|
|
116
|
-
resolved.version =
|
|
125
|
+
resolved.version = /** @type {import("./util.js").ReleaseInfo} */ (
|
|
126
|
+
releaseInfo
|
|
127
|
+
).version.slice(1);
|
|
117
128
|
|
|
118
129
|
util.log(
|
|
119
130
|
"info",
|
|
@@ -158,7 +169,7 @@ async function nwbuild(options) {
|
|
|
158
169
|
argv: resolved.argv,
|
|
159
170
|
});
|
|
160
171
|
return nwProcess;
|
|
161
|
-
} else if (resolved.mode === "build") {
|
|
172
|
+
} else if (resolved.mode === "build" || resolved.mode === "package") {
|
|
162
173
|
util.log(
|
|
163
174
|
"info",
|
|
164
175
|
resolved.logLevel,
|
|
@@ -173,7 +184,9 @@ async function nwbuild(options) {
|
|
|
173
184
|
srcDir: /** @type {string} */ (resolved.srcDir),
|
|
174
185
|
cacheDir: resolved.cacheDir,
|
|
175
186
|
outDir: resolved.outDir,
|
|
176
|
-
app: /** @type {
|
|
187
|
+
app: /** @type {import("@nwutils/builder").LinuxRc | import("@nwutils/builder").WinRc | import("@nwutils/builder").OsxRc} */ (
|
|
188
|
+
resolved.app
|
|
189
|
+
),
|
|
177
190
|
glob: resolved.glob,
|
|
178
191
|
managedManifest: resolved.managedManifest,
|
|
179
192
|
zip: resolved.zip,
|
|
@@ -184,6 +197,34 @@ async function nwbuild(options) {
|
|
|
184
197
|
resolved.logLevel,
|
|
185
198
|
`Appliction is available at ${path.resolve(resolved.outDir)}`,
|
|
186
199
|
);
|
|
200
|
+
|
|
201
|
+
if (resolved.mode === "package") {
|
|
202
|
+
util.log(
|
|
203
|
+
"info",
|
|
204
|
+
resolved.logLevel,
|
|
205
|
+
`Packaging NW.js application as ${resolved.format}...`,
|
|
206
|
+
);
|
|
207
|
+
const packagePath = await pkg({
|
|
208
|
+
format: resolved.format,
|
|
209
|
+
appDir: resolved.outDir,
|
|
210
|
+
appName: resolved.app.name,
|
|
211
|
+
icon: resolved.app.icon,
|
|
212
|
+
arch: resolved.arch,
|
|
213
|
+
cacheDir: resolved.cacheDir,
|
|
214
|
+
cache: resolved.cache,
|
|
215
|
+
sign: resolved.sign,
|
|
216
|
+
signKey: resolved.signKey,
|
|
217
|
+
version: manifest.json?.version,
|
|
218
|
+
publish: resolved.publish,
|
|
219
|
+
updateInformation: resolved.updateInformation,
|
|
220
|
+
});
|
|
221
|
+
util.log(
|
|
222
|
+
"info",
|
|
223
|
+
resolved.logLevel,
|
|
224
|
+
`Package is available at ${packagePath}`,
|
|
225
|
+
);
|
|
226
|
+
return packagePath;
|
|
227
|
+
}
|
|
187
228
|
}
|
|
188
229
|
} catch (error) {
|
|
189
230
|
console.error(error);
|
package/src/util.js
CHANGED
|
@@ -7,6 +7,122 @@ import url from "node:url";
|
|
|
7
7
|
|
|
8
8
|
import * as GlobModule from "glob";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Linux/Windows/OSX specific application configuration. Every property maps
|
|
12
|
+
* to a `LinuxRc`/`WinRc`/`OsxRc` field from `@nwutils/builder`, kept optional
|
|
13
|
+
* here since which ones are required depends on `options.platform` - that is
|
|
14
|
+
* checked at runtime by `validate()`.
|
|
15
|
+
* @typedef {object} AppOptions
|
|
16
|
+
* @property {string} [name] Name of the application
|
|
17
|
+
* @property {string} [icon] Path to icon file
|
|
18
|
+
* @property {string} [genericName] Generic name of the application
|
|
19
|
+
* @property {boolean} [noDisplay] If true the application is not displayed
|
|
20
|
+
* @property {string} [comment] Tooltip for the entry
|
|
21
|
+
* @property {string | boolean} [hidden] Whether the entry is hidden
|
|
22
|
+
* @property {string[]} [onlyShowIn] Desktop environments that should display this entry
|
|
23
|
+
* @property {string[]} [notShowIn] Desktop environments that should not display this entry
|
|
24
|
+
* @property {boolean} [dBusActivatable] If true D-Bus activation is supported
|
|
25
|
+
* @property {string} [tryExec] Executable used to determine if the program is installed
|
|
26
|
+
* @property {string} [exec] Program to execute, possibly with arguments
|
|
27
|
+
* @property {string} [path] Working directory to run the program in
|
|
28
|
+
* @property {boolean} [terminal] Whether the program runs in a terminal window
|
|
29
|
+
* @property {string[]} [actions] Identifiers for application actions
|
|
30
|
+
* @property {string[]} [mimeType] MIME type(s) supported by this application
|
|
31
|
+
* @property {string[]} [categories] Menu categories the entry should be shown in
|
|
32
|
+
* @property {string[]} [implements] Interfaces this application implements
|
|
33
|
+
* @property {string[]} [keywords] Additional strings used to describe this entry
|
|
34
|
+
* @property {boolean} [startupNotify] Whether the application supports startup notification
|
|
35
|
+
* @property {string} [startupWMClass] WM class or WM name hint the application maps
|
|
36
|
+
* @property {boolean} [prefersNonDefaultGPU] If true prefers running on a discrete GPU
|
|
37
|
+
* @property {string} [singleMainWindow] If true the application has a single main window
|
|
38
|
+
* @property {string} [version] Version of the application
|
|
39
|
+
* @property {string} [comments] Additional diagnostic information
|
|
40
|
+
* @property {string} [company] Company that produced the file
|
|
41
|
+
* @property {string} [fileDescription] File description presented to users
|
|
42
|
+
* @property {string} [fileVersion] Version number of the file
|
|
43
|
+
* @property {string} [internalName] Internal name of the file
|
|
44
|
+
* @property {string} [legalCopyright] Copyright notices that apply to the file
|
|
45
|
+
* @property {string} [legalTrademark] Trademarks that apply to the file
|
|
46
|
+
* @property {string} [originalFilename] Original name of the file
|
|
47
|
+
* @property {string} [privateBuild] Information about a private build
|
|
48
|
+
* @property {string} [productName] Name of the product the file is distributed with
|
|
49
|
+
* @property {string} [productVersion] Version of the product the file is distributed with
|
|
50
|
+
* @property {string} [specialBuild] How this build differs from the standard version
|
|
51
|
+
* @property {number} [languageCode] Language identifier (LCID) of the file
|
|
52
|
+
* @property {string} [LSApplicationCategoryType] App Store category
|
|
53
|
+
* @property {string} [CFBundleIdentifier] Unique bundle identifier, usually reverse DNS
|
|
54
|
+
* @property {string} [CFBundleName] User-visible short name for the bundle
|
|
55
|
+
* @property {string} [CFBundleDisplayName] User-visible name for the bundle
|
|
56
|
+
* @property {string} [CFBundleSpokenName] Replacement app name for text-to-speech
|
|
57
|
+
* @property {string} [CFBundleShortVersionString] Release or version number of the bundle
|
|
58
|
+
* @property {string} [CFBundleVersion] Build version that identifies a bundle iteration
|
|
59
|
+
* @property {string} [NSHumanReadableCopyright] Human-readable copyright notice
|
|
60
|
+
* @property {string} [NSLocalNetworkUsageDescription] Why the app needs local network access
|
|
61
|
+
* @property {boolean} [LSFileQuarantineEnabled] Whether files this app creates are quarantined
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Minimal shape of the `package.json` fields read while resolving options.
|
|
66
|
+
* @typedef {object} PackageManifest
|
|
67
|
+
* @property {string} [name] Package name
|
|
68
|
+
* @property {string} [version] Package version
|
|
69
|
+
* @property {string} [author] Package author
|
|
70
|
+
* @property {string} [description] Package description
|
|
71
|
+
* @property {{icon?: string}} [window] NW.js manifest `window` configuration
|
|
72
|
+
* @property {object} [nwbuild] `nwbuild` options embedded in the manifest
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Version specific NW.js release metadata, as found in the `versions` array
|
|
77
|
+
* of the manifest at `manifestUrl`.
|
|
78
|
+
* @typedef {object} ReleaseInfo
|
|
79
|
+
* @property {string} version NW.js version, eg. `"v0.115.0"`
|
|
80
|
+
* @property {string[]} flavors Flavors this release is published for
|
|
81
|
+
* @property {string[]} files Supported `<platform>-<arch>` combinations
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The versions manifest NW.js releases are published to.
|
|
86
|
+
* @typedef {object} VersionsManifest
|
|
87
|
+
* @property {string} latest Latest published version
|
|
88
|
+
* @property {string} stable Latest stable version
|
|
89
|
+
* @property {string} lts Latest LTS version
|
|
90
|
+
* @property {ReleaseInfo[]} versions Every published release
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* `nwbuild` options, partially or fully resolved. Every field is optional
|
|
95
|
+
* and loosely typed as supplied by the caller or CLI (eg. `cache` may arrive
|
|
96
|
+
* as the string `"true"`) - `parse()` normalizes them in place.
|
|
97
|
+
* @typedef {object} Options
|
|
98
|
+
* @property {"get" | "run" | "build" | "package"} [mode] Choose between get, run, build or package mode
|
|
99
|
+
* @property {string} [version] Runtime version
|
|
100
|
+
* @property {"normal" | "sdk"} [flavor] Runtime flavor
|
|
101
|
+
* @property {"linux" | "osx" | "win"} [platform] Host platform
|
|
102
|
+
* @property {"ia32" | "x64" | "arm64"} [arch] Host architecture
|
|
103
|
+
* @property {string} [downloadUrl] Download server
|
|
104
|
+
* @property {string} [manifestUrl] Versions manifest URI
|
|
105
|
+
* @property {string} [cacheDir] Directory to cache NW binaries
|
|
106
|
+
* @property {boolean | string} [cache] If true the existing cache is used
|
|
107
|
+
* @property {boolean | string} [ffmpeg] If true the community ffmpeg is used
|
|
108
|
+
* @property {"error" | "warn" | "info" | "debug"} [logLevel] Specify level of logging
|
|
109
|
+
* @property {boolean | string} [shaSum] If true, shasum is enabled
|
|
110
|
+
* @property {boolean | string} [nativeAddon] Get Node native addons
|
|
111
|
+
* @property {"AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg"} [format] Packaged output format, used in package mode
|
|
112
|
+
* @property {boolean | string} [sign] If true, sign the AppImage, used in package mode
|
|
113
|
+
* @property {string} [signKey] GPG key to sign the AppImage with, used in package mode
|
|
114
|
+
* @property {import("@nwutils/packager").PublishOptions} [publish] Where releases are published, used in package mode
|
|
115
|
+
* @property {boolean | string} [updateInformation] AppImage zsync update information, used in package mode
|
|
116
|
+
* @property {string[]} [argv] CLI arguments passed to the NW.js process in run mode
|
|
117
|
+
* @property {boolean | string} [glob] If true file globbing is enabled when parsing srcDir
|
|
118
|
+
* @property {string | string[]} [srcDir] File paths to application code
|
|
119
|
+
* @property {string} [outDir] Directory to store build artifacts
|
|
120
|
+
* @property {boolean | string} [zip] If truthy, the outDir directory is compressed
|
|
121
|
+
* @property {boolean | string | Record<string, unknown>} [managedManifest] Managed manifest mode
|
|
122
|
+
* @property {AppOptions} [app] Platform specific app metadata
|
|
123
|
+
* @property {boolean} [cli] If true the CLI is used to parse options
|
|
124
|
+
*/
|
|
125
|
+
|
|
10
126
|
/**
|
|
11
127
|
* Get manifest (array of NW release metadata) from URL.
|
|
12
128
|
* @param {string} manifestUrl Versions manifest URI, https or file path
|
|
@@ -49,7 +165,7 @@ function getManifest(manifestUrl) {
|
|
|
49
165
|
* @param {string} arch NW architecture
|
|
50
166
|
* @param {string} cacheDir Directory to store NW binaries
|
|
51
167
|
* @param {string} manifestUrl Versions manifest URI, https or file path
|
|
52
|
-
* @returns {Promise<
|
|
168
|
+
* @returns {Promise<ReleaseInfo | undefined>} Version specific release info
|
|
53
169
|
*/
|
|
54
170
|
async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
55
171
|
let releaseData = undefined;
|
|
@@ -66,7 +182,7 @@ async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
|
66
182
|
await fs.promises.writeFile(manifestPath, data);
|
|
67
183
|
}
|
|
68
184
|
|
|
69
|
-
/** @type {
|
|
185
|
+
/** @type {VersionsManifest} */
|
|
70
186
|
const manifest = JSON.parse(
|
|
71
187
|
await fs.promises.readFile(manifestPath, "utf8"),
|
|
72
188
|
);
|
|
@@ -76,7 +192,7 @@ async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
|
76
192
|
}
|
|
77
193
|
|
|
78
194
|
releaseData = manifest.versions.find(
|
|
79
|
-
(
|
|
195
|
+
(release) => release.version === `v${version}`,
|
|
80
196
|
);
|
|
81
197
|
} catch {
|
|
82
198
|
console.error(
|
|
@@ -86,12 +202,14 @@ async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
|
86
202
|
return releaseData;
|
|
87
203
|
}
|
|
88
204
|
|
|
205
|
+
/** @type {Record<"darwin" | "linux" | "win32", "linux" | "osx" | "win">} */
|
|
89
206
|
const PLATFORM_KV = {
|
|
90
207
|
darwin: "osx",
|
|
91
208
|
linux: "linux",
|
|
92
209
|
win32: "win",
|
|
93
210
|
};
|
|
94
211
|
|
|
212
|
+
/** @type {Record<"x64" | "ia32" | "arm64", "x64" | "ia32" | "arm64">} */
|
|
95
213
|
const ARCH_KV = {
|
|
96
214
|
x64: "x64",
|
|
97
215
|
ia32: "ia32",
|
|
@@ -143,10 +261,10 @@ async function globFiles({ srcDir, glob }) {
|
|
|
143
261
|
* @param {object} options - node manifest options
|
|
144
262
|
* @param {string | string []} options.srcDir - src dir
|
|
145
263
|
* @param {boolean} options.glob - glob flag
|
|
146
|
-
* @returns {Promise
|
|
264
|
+
* @returns {Promise<{path: string, json: PackageManifest | undefined}>} - Node manifest
|
|
147
265
|
*/
|
|
148
266
|
async function getNodeManifest({ srcDir, glob }) {
|
|
149
|
-
/** @type {{path: string, json:
|
|
267
|
+
/** @type {{path: string, json: PackageManifest | undefined}} */
|
|
150
268
|
let manifest = {
|
|
151
269
|
path: "",
|
|
152
270
|
json: undefined,
|
|
@@ -184,24 +302,31 @@ async function getNodeManifest({ srcDir, glob }) {
|
|
|
184
302
|
/**
|
|
185
303
|
* Function to convert `'true'` and `'false'` into `true` and `false`.
|
|
186
304
|
* `commander` does not do the conversion automatically.
|
|
187
|
-
* @
|
|
188
|
-
* @
|
|
305
|
+
* @template {string | boolean | Record<string, unknown> | undefined} T
|
|
306
|
+
* @param {T} option - a boolean type option
|
|
307
|
+
* @returns {T extends "true" ? true : T extends "false" ? false : T} `true`, `false` or file path
|
|
189
308
|
*/
|
|
190
309
|
function str2Bool(option) {
|
|
191
310
|
if (option === "true") {
|
|
192
|
-
return true
|
|
311
|
+
return /** @type {T extends "true" ? true : T extends "false" ? false : T} */ (
|
|
312
|
+
true
|
|
313
|
+
);
|
|
193
314
|
} else if (option === "false") {
|
|
194
|
-
return false
|
|
315
|
+
return /** @type {T extends "true" ? true : T extends "false" ? false : T} */ (
|
|
316
|
+
false
|
|
317
|
+
);
|
|
195
318
|
} else {
|
|
196
|
-
return
|
|
319
|
+
return /** @type {T extends "true" ? true : T extends "false" ? false : T} */ (
|
|
320
|
+
option
|
|
321
|
+
);
|
|
197
322
|
}
|
|
198
323
|
}
|
|
199
324
|
|
|
200
325
|
/**
|
|
201
326
|
* Parse options.
|
|
202
|
-
* @param {
|
|
203
|
-
* @param {
|
|
204
|
-
* @returns {Promise<
|
|
327
|
+
* @param {Options | undefined} options Options
|
|
328
|
+
* @param {PackageManifest} pkg Package.json as JSON
|
|
329
|
+
* @returns {Promise<Options>} Options
|
|
205
330
|
*/
|
|
206
331
|
export const parse = async (options, pkg) => {
|
|
207
332
|
options = options ?? {};
|
|
@@ -228,6 +353,13 @@ export const parse = async (options, pkg) => {
|
|
|
228
353
|
return { ...options };
|
|
229
354
|
}
|
|
230
355
|
|
|
356
|
+
if (options.mode === "package") {
|
|
357
|
+
options.format =
|
|
358
|
+
options.format ?? (options.platform === "linux" ? "AppImage" : undefined);
|
|
359
|
+
options.sign = str2Bool(options.sign ?? false);
|
|
360
|
+
options.updateInformation = str2Bool(options.updateInformation);
|
|
361
|
+
}
|
|
362
|
+
|
|
231
363
|
options.argv = options.argv ?? [];
|
|
232
364
|
options.glob = str2Bool(options.glob) ?? true;
|
|
233
365
|
options.srcDir = options.srcDir ?? (options.glob ? "./*" : ".");
|
|
@@ -327,8 +459,8 @@ export const parse = async (options, pkg) => {
|
|
|
327
459
|
|
|
328
460
|
/**
|
|
329
461
|
* Validate options.
|
|
330
|
-
* @param {
|
|
331
|
-
* @param {
|
|
462
|
+
* @param {Options} options Options
|
|
463
|
+
* @param {ReleaseInfo | undefined} releaseInfo Version specific NW release info
|
|
332
464
|
* @returns {Promise<undefined>} Return undefined if options are valid
|
|
333
465
|
* @throws {Error} Throw error if options are invalid
|
|
334
466
|
*/
|
|
@@ -336,10 +468,11 @@ export const validate = async (options, releaseInfo) => {
|
|
|
336
468
|
if (
|
|
337
469
|
options.mode !== "get" &&
|
|
338
470
|
options.mode !== "run" &&
|
|
339
|
-
options.mode !== "build"
|
|
471
|
+
options.mode !== "build" &&
|
|
472
|
+
options.mode !== "package"
|
|
340
473
|
) {
|
|
341
474
|
throw new Error(
|
|
342
|
-
`Unknown mode ${options.mode}. Expected "get", "run" or "
|
|
475
|
+
`Unknown mode ${options.mode}. Expected "get", "run", "build" or "package".`,
|
|
343
476
|
);
|
|
344
477
|
}
|
|
345
478
|
if (typeof releaseInfo === "undefined") {
|
|
@@ -347,6 +480,8 @@ export const validate = async (options, releaseInfo) => {
|
|
|
347
480
|
"Either the specific version info does not exist or the version manifest itself does not exist. In case of the latter, please check your internet connection and try again later.",
|
|
348
481
|
);
|
|
349
482
|
}
|
|
483
|
+
/* By the time validate() runs, parse() has already defaulted options.flavor. */
|
|
484
|
+
options.flavor = options.flavor ?? "normal";
|
|
350
485
|
if (!releaseInfo.flavors.includes(options.flavor)) {
|
|
351
486
|
throw new Error(
|
|
352
487
|
`${options.flavor} flavor is not supported by this download server.`,
|
|
@@ -484,6 +619,30 @@ export const validate = async (options, releaseInfo) => {
|
|
|
484
619
|
);
|
|
485
620
|
}
|
|
486
621
|
|
|
622
|
+
if (options.mode === "package") {
|
|
623
|
+
if (
|
|
624
|
+
options.format !== "AppImage" &&
|
|
625
|
+
options.format !== "deb" &&
|
|
626
|
+
options.format !== "rpm" &&
|
|
627
|
+
options.format !== "msix" &&
|
|
628
|
+
options.format !== "nsis" &&
|
|
629
|
+
options.format !== "dmg"
|
|
630
|
+
) {
|
|
631
|
+
throw new Error(
|
|
632
|
+
'Expected options.format to be one of "AppImage", "deb", "rpm", "msix", "nsis" or "dmg". Got ' +
|
|
633
|
+
JSON.stringify(options.format),
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
if (options.format === "AppImage" && options.platform !== "linux") {
|
|
637
|
+
throw new Error(
|
|
638
|
+
`options.format "AppImage" requires options.platform to be "linux". Got ${JSON.stringify(options.platform)}.`,
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/* By the time validate() runs, parse() has already defaulted options.app to {}. */
|
|
644
|
+
options.app = options.app ?? {};
|
|
645
|
+
|
|
487
646
|
if (options.platform === "linux") {
|
|
488
647
|
if (options.app.name && typeof options.app.name !== "string") {
|
|
489
648
|
throw new Error(
|
|
@@ -852,7 +1011,7 @@ export const validate = async (options, releaseInfo) => {
|
|
|
852
1011
|
* @async
|
|
853
1012
|
* @function
|
|
854
1013
|
* @param {"chromedriver"} type - NW specific file or directory
|
|
855
|
-
* @param {
|
|
1014
|
+
* @param {{cacheDir: string, flavor: string, version: string, platform: string, arch: string}} options - nwbuild options
|
|
856
1015
|
* @returns {Promise<string>} - Path to chromedriver
|
|
857
1016
|
* @throws {Error}
|
|
858
1017
|
*/
|
package/src/postinstall.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import url from "node:url";
|
|
3
|
-
|
|
4
|
-
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
5
|
-
|
|
6
|
-
const baseVoltaPath = path.resolve(
|
|
7
|
-
path.join(
|
|
8
|
-
__dirname,
|
|
9
|
-
"..",
|
|
10
|
-
"node_modules",
|
|
11
|
-
"base-volta-off-of-nwjs",
|
|
12
|
-
"index.js",
|
|
13
|
-
),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
/* Execute the script in development mode only since it is used during testing */
|
|
17
|
-
import(baseVoltaPath)
|
|
18
|
-
.then(() => console.log("Node version is updated"))
|
|
19
|
-
.catch((error) => console.log(error));
|