nw-builder 4.18.1 → 4.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +20 -64
- package/package.json +15 -34
- package/src/cli.js +6 -3
- package/src/index.d.ts +5 -1
- package/src/index.js +78 -71
- package/src/util.js +42 -19
- package/src/bld/osx.js +0 -225
- package/src/bld.js +0 -389
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -234,7 +234,7 @@ This object defines additional properties used for building for a specific platf
|
|
|
234
234
|
| `productName` | `string` | `name` in NW.js manifest | Name of the product with which the file is distributed. This string is required. |
|
|
235
235
|
| `productVersion` | `string` | Value of `version` in NW.js manifest | Version of the product with which the file is distributed—for example, 3.10 or 5.00.RC2. |
|
|
236
236
|
| `specialBuild` | `string` | `undefined` | 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. |
|
|
237
|
-
| `languageCode` | `number` | `1033` | Language of the file, defined by Microsoft, see
|
|
237
|
+
| `languageCode` | `number` | `1033` | Language of the file, defined by Microsoft, see [MS-OE376](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376)6c085406-a698-4e12-9d4d-c3b0ee3dbc4a |
|
|
238
238
|
|
|
239
239
|
#### Linux-specific options (`LinuxRc`)
|
|
240
240
|
|
|
@@ -265,19 +265,20 @@ This object defines additional properties used for building for a specific platf
|
|
|
265
265
|
|
|
266
266
|
#### MacOS-specific options (`OsxRc`)
|
|
267
267
|
|
|
268
|
-
| Name | Type
|
|
269
|
-
| ------------------------------ |
|
|
270
|
-
| name | `string`
|
|
271
|
-
| icon | `string`
|
|
272
|
-
| LSApplicationCategoryType | `string`
|
|
273
|
-
| CFBundleIdentifier | `string`
|
|
274
|
-
| CFBundleName | `string`
|
|
275
|
-
| CFBundleDisplayName | `string`
|
|
276
|
-
| CFBundleSpokenName | `string`
|
|
277
|
-
| CFBundleVersion | `string`
|
|
278
|
-
| CFBundleShortVersionString | `string`
|
|
279
|
-
| NSHumanReadableCopyright | `string`
|
|
280
|
-
| NSLocalNetworkUsageDescription | `string`
|
|
268
|
+
| Name | Type | Description |
|
|
269
|
+
| ------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
270
|
+
| name | `string` | The name of the application |
|
|
271
|
+
| icon | `string` | The path to the icon file. It should be a .icns file. (**WARNING**: Please define the icon in the NW.js manifest instead) |
|
|
272
|
+
| LSApplicationCategoryType | `string` | The category that best describes your app for the App Store. |
|
|
273
|
+
| CFBundleIdentifier | `string` | A unique identifier for a bundle usually in reverse DNS format. |
|
|
274
|
+
| CFBundleName | `string` | A user-visible short name for the bundle. |
|
|
275
|
+
| CFBundleDisplayName | `string` | The user-visible name for the bundle. |
|
|
276
|
+
| CFBundleSpokenName | `string` | A replacement for the app name in text-to-speech operations. |
|
|
277
|
+
| CFBundleVersion | `string` | The version of the build that identifies an iteration of the bundle. |
|
|
278
|
+
| CFBundleShortVersionString | `string` | The release or version number of the bundle. |
|
|
279
|
+
| NSHumanReadableCopyright | `string` | A human-readable copyright notice for the bundle. |
|
|
280
|
+
| NSLocalNetworkUsageDescription | `string` | A human-readable description of why the application needs access to the local network. |
|
|
281
|
+
| LSFileQuarantineEnabled | `boolean` | A Boolean value indicating whether the files this app creates are quarantined by default. |
|
|
281
282
|
|
|
282
283
|
## Guides
|
|
283
284
|
|
|
@@ -328,55 +329,10 @@ nwbuild({
|
|
|
328
329
|
|
|
329
330
|
### External contributor
|
|
330
331
|
|
|
331
|
-
-
|
|
332
|
-
-
|
|
333
|
-
- Pull requests are squashed and merged onto the `main` branch.
|
|
334
|
-
- PR title is used as commit's first line, PR description is used as commit body.
|
|
335
|
-
- Only commit messages starting with `fix`, `feat` and `chore` are recognised by the Release Please bot.
|
|
336
|
-
- Lint your code before commiting your change.
|
|
337
|
-
- Add tests whenever possible.
|
|
332
|
+
- Use Node.js standard libraries whenever possible.
|
|
333
|
+
- Prefer to use syncronous APIs over modern APIs which have been introduced in later versions.
|
|
338
334
|
|
|
339
|
-
### Maintainer
|
|
335
|
+
### Maintainer
|
|
340
336
|
|
|
341
|
-
-
|
|
342
|
-
-
|
|
343
|
-
- A commit's first line should be formatted as `<type>[optional scope]: <description>`.
|
|
344
|
-
- A commit's body should have a description of changes in bullet points followed by any links it references or issues it fixes or closes.
|
|
345
|
-
- Google's Release Please Action is used to update the changelog, bump the package version and generate GitHub releases.
|
|
346
|
-
- NPM Publish Action publishes to `npm` if there is a version bump.
|
|
347
|
-
- Every time `nw` is upgraded, the `volta` package should also be updated and `nw-builder` should create a minor release (since the underlying Node version is changed).
|
|
348
|
-
|
|
349
|
-
## Roadmap
|
|
350
|
-
|
|
351
|
-
### Bugs
|
|
352
|
-
|
|
353
|
-
- Managed Manifest is broken. If glob is disabled and srcDir has no package.json, build fails.
|
|
354
|
-
- Add back error, info, warn and debug logs
|
|
355
|
-
|
|
356
|
-
### Features
|
|
357
|
-
|
|
358
|
-
- feat(get): support canary releases
|
|
359
|
-
- feat(pkg): add `AppImage` installer
|
|
360
|
-
- feat(pkg): add `NSIS` installer
|
|
361
|
-
- feat(pkg): add `DMG` installer
|
|
362
|
-
- feat(get): add Linux ARM unofficial support
|
|
363
|
-
- feat(bld): add source code protection
|
|
364
|
-
- feat(pkg): add code signing
|
|
365
|
-
|
|
366
|
-
### Chores
|
|
367
|
-
|
|
368
|
-
- chore(docs): don't store JSDoc definitions in `typedef`s - get's hard to understand during development.
|
|
369
|
-
- chore: annotate file paths as `fs.PathLike` instead of `string`.
|
|
370
|
-
- chore(bld): factor out core build step
|
|
371
|
-
- chore(bld): factor out linux config
|
|
372
|
-
- chore(bld): factor out windows config
|
|
373
|
-
- chore(bld): factor out native addon
|
|
374
|
-
- chore(bld): factor out compressing
|
|
375
|
-
- chore(bld): factor out managed manifest
|
|
376
|
-
- chore(bld): move `.desktop` entry file logic to `create-desktop-shortcuts` package
|
|
377
|
-
|
|
378
|
-
## FAQ
|
|
379
|
-
|
|
380
|
-
## License
|
|
381
|
-
|
|
382
|
-
MIT License.
|
|
337
|
+
- npm Trusted Publishing with OIDC is used for releases
|
|
338
|
+
- A package is released when a maintainer creates a release note for a specific version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nw-builder",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.19.1",
|
|
4
4
|
"description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NW.js",
|
|
@@ -42,46 +42,27 @@
|
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"postinstall": "node ./src/postinstall.js",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"demo:bld:
|
|
52
|
-
"demo:
|
|
53
|
-
"demo:
|
|
54
|
-
"demo:exe:
|
|
55
|
-
"demo:
|
|
56
|
-
"demo:exe:win": "./tests/fixtures/out/win/Demo.exe",
|
|
57
|
-
"demo:cli": "nwbuild --mode=build --flavor=sdk --glob=false --cacheDir=./node_modules/nw --logLevel=debug --managedManifest=./tests/fixtures/app/package.json --outDir=./tests/fixtures/out/linux --app.name=Demo --app.icon=./tests/fixtures/app/icon.png ./tests/fixtures/app"
|
|
45
|
+
"lint": "eslint ./src ../../tests/specs/nw-builder",
|
|
46
|
+
"lint:fix": "eslint --fix ./src ../../tests/specs/nw-builder",
|
|
47
|
+
"type": "tsc",
|
|
48
|
+
"test": "node --test \"../../tests/specs/nw-builder/*.test.js\"",
|
|
49
|
+
"demo:bld:linux": "node ../../tests/fixtures/nw-builder/demo.linux.js",
|
|
50
|
+
"demo:bld:osx": "node ../../tests/fixtures/nw-builder/demo.osx.js",
|
|
51
|
+
"demo:bld:win": "node ../../tests/fixtures/nw-builder/demo.win.js",
|
|
52
|
+
"demo:exe:linux": "../../tests/fixtures/nw-builder/out/linux/Demo",
|
|
53
|
+
"demo:exe:osx": "../../tests/fixtures/nw-builder/out/osx/Demo.app/Contents/MacOS/Demo",
|
|
54
|
+
"demo:exe:win": "../../tests/fixtures/nw-builder/out/win/Demo.exe",
|
|
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"
|
|
58
56
|
},
|
|
59
57
|
"devDependencies": {
|
|
60
|
-
"@eslint/js": "^10.0.1",
|
|
61
|
-
"@vitest/coverage-v8": "^4.1.10",
|
|
62
58
|
"base-volta-off-of-nwjs": "^1.0.5",
|
|
63
|
-
"
|
|
64
|
-
"eslint-plugin-jsdoc": "^64.2.0",
|
|
65
|
-
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
66
|
-
"globals": "^17.11.0",
|
|
67
|
-
"nw": "^0.114.1",
|
|
68
|
-
"prettier": "^3.9.6",
|
|
69
|
-
"selenium-webdriver": "^4.47.0",
|
|
70
|
-
"vitest": "^4.0.14"
|
|
59
|
+
"nw": "^0.115.0"
|
|
71
60
|
},
|
|
72
61
|
"dependencies": {
|
|
62
|
+
"@nwutils/builder": "^0.1.0",
|
|
73
63
|
"@nwutils/getter": "^0.2.5",
|
|
74
64
|
"@nwutils/runner": "^0.2.3",
|
|
75
|
-
"archiver": "^8.0.0",
|
|
76
65
|
"commander": "^15.0.0",
|
|
77
|
-
"glob": "^13.0.6"
|
|
78
|
-
"plist": "^5.0.0",
|
|
79
|
-
"resedit": "^3.0.2",
|
|
80
|
-
"semver": "^7.8.5",
|
|
81
|
-
"tar": "^7.5.19"
|
|
82
|
-
},
|
|
83
|
-
"volta": {
|
|
84
|
-
"node": "26.7.0",
|
|
85
|
-
"npm": "11.13.0"
|
|
66
|
+
"glob": "^13.0.6"
|
|
86
67
|
}
|
|
87
68
|
}
|
package/src/cli.js
CHANGED
|
@@ -14,12 +14,14 @@ program
|
|
|
14
14
|
.option(
|
|
15
15
|
"--platform <string>",
|
|
16
16
|
"NW.js supported platform",
|
|
17
|
-
util.PLATFORM_KV[
|
|
17
|
+
util.PLATFORM_KV[
|
|
18
|
+
/** @type {"darwin" | "linux" | "win32"} */ (process.platform)
|
|
19
|
+
],
|
|
18
20
|
)
|
|
19
21
|
.option(
|
|
20
22
|
"--arch <string>",
|
|
21
23
|
"NW.js supported architecture",
|
|
22
|
-
util.ARCH_KV[process.arch],
|
|
24
|
+
util.ARCH_KV[/** @type {"x64" | "ia32" | "arm64"} */ (process.arch)],
|
|
23
25
|
)
|
|
24
26
|
.option(
|
|
25
27
|
"--downloadUrl <string>",
|
|
@@ -36,7 +38,7 @@ program
|
|
|
36
38
|
.option(
|
|
37
39
|
"--app <object>",
|
|
38
40
|
"Platform specific app metadata. Refer to docs for more info",
|
|
39
|
-
{},
|
|
41
|
+
/** @type {any} */ ({}),
|
|
40
42
|
)
|
|
41
43
|
.option("--cache <boolean>", "Enable/disable caching", true)
|
|
42
44
|
.option("--ffmpeg <boolean>", "Enable/disable community ffmpeg", false)
|
|
@@ -51,6 +53,7 @@ program
|
|
|
51
53
|
|
|
52
54
|
// Handle unknown --app.* arguments
|
|
53
55
|
const unknownArgs = program.parse(process.argv).args;
|
|
56
|
+
/** @type {Record<string, string>} */
|
|
54
57
|
const appConfig = {};
|
|
55
58
|
for (const arg of unknownArgs) {
|
|
56
59
|
const match = arg.match(/^--app\.([^.=]+)=(.*)$/);
|
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
|
|
1
3
|
/** NW supported platform */
|
|
2
4
|
export type SupportedPlatform = "linux" | "osx" | "win";
|
|
3
5
|
|
|
@@ -172,6 +174,8 @@ export interface OsxAppOptions {
|
|
|
172
174
|
NSHumanReadableCopyright?: string;
|
|
173
175
|
/** A human-readable description of why the application needs access to the local network. */
|
|
174
176
|
NSLocalNetworkUsageDescription?: string;
|
|
177
|
+
/** A Boolean value indicating whether the files this app creates are quarantined by default. */
|
|
178
|
+
LSFileQuarantineEnabled?: boolean;
|
|
175
179
|
}
|
|
176
180
|
|
|
177
181
|
/**
|
|
@@ -179,6 +183,6 @@ export interface OsxAppOptions {
|
|
|
179
183
|
*/
|
|
180
184
|
declare function nwbuild<P extends SupportedPlatform>(
|
|
181
185
|
options: Options<P>,
|
|
182
|
-
): Promise<
|
|
186
|
+
): Promise<ChildProcess | null | undefined>;
|
|
183
187
|
|
|
184
188
|
export default nwbuild;
|
package/src/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import console from "node:console";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
+
import bld from "@nwutils/builder";
|
|
6
7
|
import get from "@nwutils/getter";
|
|
7
8
|
import run from "@nwutils/runner";
|
|
8
9
|
|
|
9
|
-
import bld from "./bld.js";
|
|
10
10
|
import util from "./util.js";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -14,14 +14,14 @@ import util from "./util.js";
|
|
|
14
14
|
* @property {"get" | "run" | "build"} [mode="build"] Choose between get, run or build mode
|
|
15
15
|
* @property {"latest" | "stable" | string} [version="latest"] Runtime version
|
|
16
16
|
* @property {"normal" | "sdk"} [flavor="normal"] Runtime flavor
|
|
17
|
-
* @property {"linux" | "osx" | "win"} platform
|
|
18
|
-
* @property {"ia32" | "x64" | "arm64"} arch
|
|
17
|
+
* @property {"linux" | "osx" | "win"} [platform] Host platform
|
|
18
|
+
* @property {"ia32" | "x64" | "arm64"} [arch] Host architecture
|
|
19
19
|
* @property {"https://dl.nwjs.io" | string} [downloadUrl="https://dl.nwjs.io"] Download server
|
|
20
20
|
* @property {"https://nwjs.io/versions.json" | string} [manifestUrl="https://nwjs.io/versions.json"] Versions manifest URI, https or file path
|
|
21
21
|
* @property {"./cache" | string} [cacheDir="./cache"] Directory to cache NW binaries
|
|
22
|
-
* @property {
|
|
22
|
+
* @property {string | string[]} [srcDir="./"] File paths to application code
|
|
23
23
|
* @property {"./out" | string} [outDir="./out"] Directory to store build artifacts
|
|
24
|
-
* @property {object} app
|
|
24
|
+
* @property {object} [app] Refer to Linux/Windows Specific Options under Getting Started in the docs
|
|
25
25
|
* @property {boolean} [cache=true] If true the existing cache is used. Otherwise it removes and redownloads it.
|
|
26
26
|
* @property {boolean} [ffmpeg=false] If true the chromium ffmpeg is replaced by community version
|
|
27
27
|
* @property {boolean} [glob=true] If true file globbing is enabled when parsing srcDir.
|
|
@@ -29,8 +29,9 @@ import util from "./util.js";
|
|
|
29
29
|
* @property {boolean} [shaSum = true] If true, shasum is enabled. Otherwise, disabled.
|
|
30
30
|
* @property {boolean | "zip" | "tar" | "tgz"} [zip=false] If true, "zip", "tar" or "tgz" the outDir directory is compressed.
|
|
31
31
|
* @property {boolean | string | object} [managedManifest = false] Managed manifest mode
|
|
32
|
-
* @property {boolean} [
|
|
32
|
+
* @property {boolean} [nativeAddon = false] Get Node native addons
|
|
33
33
|
* @property {boolean} [cli=false] If true the CLI is used to parse options. This option is used internally.
|
|
34
|
+
* @property {string[]} [argv = []] CLI arguments passed to the NW.js process in run mode
|
|
34
35
|
*/
|
|
35
36
|
|
|
36
37
|
/**
|
|
@@ -43,6 +44,7 @@ import util from "./util.js";
|
|
|
43
44
|
async function nwbuild(options) {
|
|
44
45
|
let built;
|
|
45
46
|
let releaseInfo;
|
|
47
|
+
/** @type {{path: string, json: any}} */
|
|
46
48
|
let manifest = {
|
|
47
49
|
path: "",
|
|
48
50
|
json: undefined,
|
|
@@ -55,8 +57,8 @@ async function nwbuild(options) {
|
|
|
55
57
|
|
|
56
58
|
util.log("debug", "info", "Get node manifest...");
|
|
57
59
|
manifest = await util.getNodeManifest({
|
|
58
|
-
srcDir: options.srcDir,
|
|
59
|
-
glob: options.glob,
|
|
60
|
+
srcDir: /** @type {string | string[]} */ (options.srcDir),
|
|
61
|
+
glob: /** @type {boolean} */ (options.glob),
|
|
60
62
|
});
|
|
61
63
|
if (typeof manifest.json?.nwbuild === "object") {
|
|
62
64
|
options = { ...options, ...manifest.json.nwbuild };
|
|
@@ -64,118 +66,123 @@ async function nwbuild(options) {
|
|
|
64
66
|
|
|
65
67
|
util.log(
|
|
66
68
|
"info",
|
|
67
|
-
options.logLevel,
|
|
69
|
+
/** @type {"debug" | "error" | "info" | "warn"} */ (options.logLevel),
|
|
68
70
|
"Parse final options using node manifest",
|
|
69
71
|
);
|
|
70
|
-
|
|
72
|
+
/** @type {Required<Options>} */
|
|
73
|
+
const resolved = await util.parse(options, manifest.json);
|
|
71
74
|
util.log(
|
|
72
75
|
"debug",
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`${manifest.path}\n${manifest.json}\n`,
|
|
76
|
+
resolved.logLevel,
|
|
77
|
+
`Manifest: ${manifest.path}\n${manifest.json}\n`,
|
|
76
78
|
);
|
|
77
79
|
|
|
78
|
-
built = fs.existsSync(
|
|
80
|
+
built = fs.existsSync(resolved.cacheDir);
|
|
79
81
|
if (built === false) {
|
|
80
|
-
await fs.promises.mkdir(
|
|
82
|
+
await fs.promises.mkdir(resolved.cacheDir, { recursive: true });
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
if (
|
|
84
|
-
built = fs.existsSync(
|
|
85
|
+
if (resolved.mode === "build") {
|
|
86
|
+
built = fs.existsSync(resolved.outDir);
|
|
85
87
|
if (built === false) {
|
|
86
|
-
await fs.promises.mkdir(
|
|
88
|
+
await fs.promises.mkdir(resolved.outDir, { recursive: true });
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
/* Validate options.version to get the version specific release info */
|
|
91
|
-
util.log("info",
|
|
93
|
+
util.log("info", resolved.logLevel, "Get version specific release info...");
|
|
92
94
|
releaseInfo = await util.getReleaseInfo(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
resolved.version,
|
|
96
|
+
resolved.platform,
|
|
97
|
+
resolved.arch,
|
|
98
|
+
resolved.cacheDir,
|
|
99
|
+
resolved.manifestUrl,
|
|
98
100
|
);
|
|
99
101
|
util.log(
|
|
100
102
|
"debug",
|
|
101
|
-
|
|
103
|
+
resolved.logLevel,
|
|
102
104
|
`Release info:\n${JSON.stringify(releaseInfo, null, 2)}\n`,
|
|
103
105
|
);
|
|
104
106
|
|
|
105
|
-
util.log("info",
|
|
106
|
-
await util.validate(
|
|
107
|
+
util.log("info", resolved.logLevel, "Validate options.* ...");
|
|
108
|
+
await util.validate(resolved, releaseInfo);
|
|
107
109
|
util.log(
|
|
108
110
|
"debug",
|
|
109
|
-
|
|
110
|
-
`Options:\n${JSON.stringify(
|
|
111
|
+
resolved.logLevel,
|
|
112
|
+
`Options:\n${JSON.stringify(resolved, null, 2)}`,
|
|
111
113
|
);
|
|
112
114
|
|
|
113
115
|
/* Remove leading "v" from version string */
|
|
114
|
-
|
|
116
|
+
resolved.version = releaseInfo.version.slice(1);
|
|
115
117
|
|
|
116
|
-
util.log(
|
|
118
|
+
util.log(
|
|
119
|
+
"info",
|
|
120
|
+
resolved.logLevel,
|
|
121
|
+
"Getting NW.js and related binaries...",
|
|
122
|
+
);
|
|
117
123
|
await get({
|
|
118
|
-
version:
|
|
119
|
-
flavor:
|
|
120
|
-
platform:
|
|
121
|
-
arch:
|
|
122
|
-
downloadUrl:
|
|
123
|
-
manifestUrl:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
version: resolved.version,
|
|
125
|
+
flavor: resolved.flavor,
|
|
126
|
+
platform: resolved.platform,
|
|
127
|
+
arch: resolved.arch,
|
|
128
|
+
downloadUrl: /** @type {"https://dl.nwjs.io"} */ (resolved.downloadUrl),
|
|
129
|
+
manifestUrl: /** @type {"https://nwjs.io/versions.json"} */ (
|
|
130
|
+
resolved.manifestUrl
|
|
131
|
+
),
|
|
132
|
+
cacheDir: resolved.cacheDir,
|
|
133
|
+
cache: resolved.cache,
|
|
134
|
+
ffmpeg: resolved.ffmpeg,
|
|
135
|
+
nativeAddon: resolved.nativeAddon,
|
|
136
|
+
shaSum: resolved.shaSum,
|
|
130
137
|
});
|
|
131
138
|
|
|
132
|
-
if (
|
|
139
|
+
if (resolved.mode === "get") {
|
|
133
140
|
// Do nothing else since we have already downloaded the binaries.
|
|
134
141
|
return undefined;
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
if (
|
|
138
|
-
util.log("info",
|
|
139
|
-
if (
|
|
144
|
+
if (resolved.mode === "run") {
|
|
145
|
+
util.log("info", resolved.logLevel, "Running NW.js in run mode...");
|
|
146
|
+
if (resolved.glob) {
|
|
140
147
|
throw new Error(
|
|
141
148
|
"Glob option is not supported when mode is set to run.",
|
|
142
149
|
);
|
|
143
150
|
}
|
|
144
151
|
const nwProcess = await run({
|
|
145
|
-
version:
|
|
146
|
-
flavor:
|
|
147
|
-
platform:
|
|
148
|
-
arch:
|
|
149
|
-
srcDir:
|
|
150
|
-
cacheDir:
|
|
151
|
-
argv:
|
|
152
|
+
version: resolved.version,
|
|
153
|
+
flavor: resolved.flavor,
|
|
154
|
+
platform: resolved.platform,
|
|
155
|
+
arch: resolved.arch,
|
|
156
|
+
srcDir: /** @type {string} */ (resolved.srcDir),
|
|
157
|
+
cacheDir: resolved.cacheDir,
|
|
158
|
+
argv: resolved.argv,
|
|
152
159
|
});
|
|
153
160
|
return nwProcess;
|
|
154
|
-
} else if (
|
|
161
|
+
} else if (resolved.mode === "build") {
|
|
155
162
|
util.log(
|
|
156
163
|
"info",
|
|
157
|
-
|
|
158
|
-
`Build a NW.js application for ${
|
|
164
|
+
resolved.logLevel,
|
|
165
|
+
`Build a NW.js application for ${resolved.platform} ${resolved.arch}...`,
|
|
159
166
|
);
|
|
160
167
|
await bld({
|
|
161
|
-
version:
|
|
162
|
-
flavor:
|
|
163
|
-
platform:
|
|
164
|
-
arch:
|
|
165
|
-
manifestUrl:
|
|
166
|
-
srcDir:
|
|
167
|
-
cacheDir:
|
|
168
|
-
outDir:
|
|
169
|
-
app:
|
|
170
|
-
glob:
|
|
171
|
-
managedManifest:
|
|
172
|
-
zip:
|
|
168
|
+
version: resolved.version,
|
|
169
|
+
flavor: resolved.flavor,
|
|
170
|
+
platform: resolved.platform,
|
|
171
|
+
arch: resolved.arch,
|
|
172
|
+
manifestUrl: resolved.manifestUrl,
|
|
173
|
+
srcDir: /** @type {string} */ (resolved.srcDir),
|
|
174
|
+
cacheDir: resolved.cacheDir,
|
|
175
|
+
outDir: resolved.outDir,
|
|
176
|
+
app: /** @type {any} */ (resolved.app),
|
|
177
|
+
glob: resolved.glob,
|
|
178
|
+
managedManifest: resolved.managedManifest,
|
|
179
|
+
zip: resolved.zip,
|
|
173
180
|
releaseInfo: releaseInfo,
|
|
174
181
|
});
|
|
175
182
|
util.log(
|
|
176
183
|
"info",
|
|
177
|
-
|
|
178
|
-
`Appliction is available at ${path.resolve(
|
|
184
|
+
resolved.logLevel,
|
|
185
|
+
`Appliction is available at ${path.resolve(resolved.outDir)}`,
|
|
179
186
|
);
|
|
180
187
|
}
|
|
181
188
|
} catch (error) {
|
package/src/util.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as GlobModule from "glob";
|
|
|
10
10
|
/**
|
|
11
11
|
* Get manifest (array of NW release metadata) from URL.
|
|
12
12
|
* @param {string} manifestUrl Versions manifest URI, https or file path
|
|
13
|
-
* @returns {string} - Manifest object
|
|
13
|
+
* @returns {string | Promise<string>} - Manifest object
|
|
14
14
|
*/
|
|
15
15
|
function getManifest(manifestUrl) {
|
|
16
16
|
let chunks = "";
|
|
@@ -49,7 +49,7 @@ function getManifest(manifestUrl) {
|
|
|
49
49
|
* @param {string} arch NW architecture
|
|
50
50
|
* @param {string} cacheDir Directory to store NW binaries
|
|
51
51
|
* @param {string} manifestUrl Versions manifest URI, https or file path
|
|
52
|
-
* @returns {Promise<
|
|
52
|
+
* @returns {Promise<any>} Version specific release info
|
|
53
53
|
*/
|
|
54
54
|
async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
55
55
|
let releaseData = undefined;
|
|
@@ -66,14 +66,17 @@ async function getReleaseInfo(version, platform, arch, cacheDir, manifestUrl) {
|
|
|
66
66
|
await fs.promises.writeFile(manifestPath, data);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
/** @type {any} */
|
|
70
|
+
const manifest = JSON.parse(
|
|
71
|
+
await fs.promises.readFile(manifestPath, "utf8"),
|
|
72
|
+
);
|
|
70
73
|
if (version === "latest" || version === "stable" || version === "lts") {
|
|
71
74
|
// Remove leading "v" from version string
|
|
72
75
|
version = manifest[version].slice(1);
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
releaseData = manifest.versions.find(
|
|
76
|
-
(release) => release.version === `v${version}`,
|
|
79
|
+
(/** @type {any} */ release) => release.version === `v${version}`,
|
|
77
80
|
);
|
|
78
81
|
} catch {
|
|
79
82
|
console.error(
|
|
@@ -108,7 +111,7 @@ const EXE_NAME = {
|
|
|
108
111
|
* @param {object} options - glob file options
|
|
109
112
|
* @param {string | string[]} options.srcDir - app src dir
|
|
110
113
|
* @param {boolean} options.glob - glob flag
|
|
111
|
-
* @returns {Promise<string[]>}
|
|
114
|
+
* @returns {Promise<string[] | string>} - Returns array of file paths, or `srcDir` as-is when `glob` is false
|
|
112
115
|
*/
|
|
113
116
|
async function globFiles({ srcDir, glob }) {
|
|
114
117
|
let files;
|
|
@@ -143,26 +146,31 @@ async function globFiles({ srcDir, glob }) {
|
|
|
143
146
|
* @returns {Promise.<{path: string, json: object}>} - Node manifest
|
|
144
147
|
*/
|
|
145
148
|
async function getNodeManifest({ srcDir, glob }) {
|
|
149
|
+
/** @type {{path: string, json: any}} */
|
|
146
150
|
let manifest = {
|
|
147
151
|
path: "",
|
|
148
152
|
json: undefined,
|
|
149
153
|
};
|
|
150
154
|
let files;
|
|
151
155
|
if (glob === true) {
|
|
152
|
-
files = await globFiles({ srcDir, glob });
|
|
156
|
+
files = /** @type {string[]} */ (await globFiles({ srcDir, glob }));
|
|
153
157
|
for (const file of files) {
|
|
154
158
|
if (
|
|
155
159
|
path.basename(file) === "package.json" &&
|
|
156
160
|
manifest.json === undefined
|
|
157
161
|
) {
|
|
158
162
|
manifest.path = file;
|
|
159
|
-
manifest.json = JSON.parse(await fs.promises.readFile(file));
|
|
163
|
+
manifest.json = JSON.parse(await fs.promises.readFile(file, "utf8"));
|
|
160
164
|
}
|
|
161
165
|
}
|
|
162
166
|
} else {
|
|
163
|
-
|
|
167
|
+
const srcDirPath = /** @type {string} */ (srcDir);
|
|
168
|
+
manifest.path = path.resolve(srcDirPath, "package.json");
|
|
164
169
|
manifest.json = JSON.parse(
|
|
165
|
-
await fs.promises.readFile(
|
|
170
|
+
await fs.promises.readFile(
|
|
171
|
+
path.resolve(srcDirPath, "package.json"),
|
|
172
|
+
"utf8",
|
|
173
|
+
),
|
|
166
174
|
);
|
|
167
175
|
}
|
|
168
176
|
|
|
@@ -191,9 +199,9 @@ function str2Bool(option) {
|
|
|
191
199
|
|
|
192
200
|
/**
|
|
193
201
|
* Parse options.
|
|
194
|
-
* @param {
|
|
195
|
-
* @param {
|
|
196
|
-
* @returns {Promise<
|
|
202
|
+
* @param {any} options Options
|
|
203
|
+
* @param {any} pkg Package.json as JSON
|
|
204
|
+
* @returns {Promise<any>} Options
|
|
197
205
|
*/
|
|
198
206
|
export const parse = async (options, pkg) => {
|
|
199
207
|
options = options ?? {};
|
|
@@ -201,8 +209,12 @@ export const parse = async (options, pkg) => {
|
|
|
201
209
|
|
|
202
210
|
options.version = options.version ?? "latest";
|
|
203
211
|
options.flavor = options.flavor ?? "normal";
|
|
204
|
-
options.platform =
|
|
205
|
-
|
|
212
|
+
options.platform =
|
|
213
|
+
options.platform ??
|
|
214
|
+
PLATFORM_KV[/** @type {"darwin" | "linux" | "win32"} */ (process.platform)];
|
|
215
|
+
options.arch =
|
|
216
|
+
options.arch ??
|
|
217
|
+
ARCH_KV[/** @type {"x64" | "ia32" | "arm64"} */ (process.arch)];
|
|
206
218
|
options.downloadUrl = options.downloadUrl ?? "https://dl.nwjs.io";
|
|
207
219
|
options.manifestUrl = options.manifestUrl ?? "https://nwjs.io/versions.json";
|
|
208
220
|
options.cacheDir = options.cacheDir ?? "./cache";
|
|
@@ -307,6 +319,7 @@ export const parse = async (options, pkg) => {
|
|
|
307
319
|
options.app.NSHumanReadableCopyright ?? undefined;
|
|
308
320
|
options.app.NSLocalNetworkUsageDescription =
|
|
309
321
|
options.app.NSLocalNetworkUsageDescription ?? undefined;
|
|
322
|
+
options.app.LSFileQuarantineEnabled ?? false;
|
|
310
323
|
}
|
|
311
324
|
|
|
312
325
|
return { ...options };
|
|
@@ -314,8 +327,8 @@ export const parse = async (options, pkg) => {
|
|
|
314
327
|
|
|
315
328
|
/**
|
|
316
329
|
* Validate options.
|
|
317
|
-
* @param {
|
|
318
|
-
* @param {
|
|
330
|
+
* @param {any} options Options
|
|
331
|
+
* @param {any} releaseInfo Version specific NW release info
|
|
319
332
|
* @returns {Promise<undefined>} Return undefined if options are valid
|
|
320
333
|
* @throws {Error} Throw error if options are invalid
|
|
321
334
|
*/
|
|
@@ -460,7 +473,8 @@ export const validate = async (options, releaseInfo) => {
|
|
|
460
473
|
}
|
|
461
474
|
|
|
462
475
|
if (
|
|
463
|
-
|
|
476
|
+
typeof options.zip !== "boolean" &&
|
|
477
|
+
options.zip !== "zip" &&
|
|
464
478
|
options.zip !== "tar" &&
|
|
465
479
|
options.zip !== "tgz"
|
|
466
480
|
) {
|
|
@@ -684,6 +698,15 @@ export const validate = async (options, releaseInfo) => {
|
|
|
684
698
|
options.app.NSLocalNetworkUsageDescription,
|
|
685
699
|
);
|
|
686
700
|
}
|
|
701
|
+
if (
|
|
702
|
+
options.app.LSFileQuarantineEnabled &&
|
|
703
|
+
typeof options.app.LSFileQuarantineEnabled !== "boolean"
|
|
704
|
+
) {
|
|
705
|
+
throw new Error(
|
|
706
|
+
"Expected options.app.LSFileQuarantineEnabled to be a boolean. Got " +
|
|
707
|
+
options.app.LSFileQuarantineEnabled,
|
|
708
|
+
);
|
|
709
|
+
}
|
|
687
710
|
} else {
|
|
688
711
|
if (typeof options.app.name !== "string") {
|
|
689
712
|
throw new Error(
|
|
@@ -829,8 +852,8 @@ export const validate = async (options, releaseInfo) => {
|
|
|
829
852
|
* @async
|
|
830
853
|
* @function
|
|
831
854
|
* @param {"chromedriver"} type - NW specific file or directory
|
|
832
|
-
* @param {
|
|
833
|
-
* @returns {string}
|
|
855
|
+
* @param {any} options - nwbuild options
|
|
856
|
+
* @returns {Promise<string>} - Path to chromedriver
|
|
834
857
|
* @throws {Error}
|
|
835
858
|
*/
|
|
836
859
|
async function getPath(type, options) {
|
package/src/bld/osx.js
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import console from "node:console";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import process from "node:process";
|
|
5
|
-
|
|
6
|
-
import { build, parse } from "plist";
|
|
7
|
-
import semver from "semver";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Function to update Helper App Plist Files
|
|
11
|
-
* @param {string} plistPath - Path to Helper App Plist File
|
|
12
|
-
* @param {string} helperName - Helper App Name
|
|
13
|
-
* @param {string} helperId - Helper App ID
|
|
14
|
-
* @param {string} appCFBundleIdentifier - options.app.CFBundleIdentifier
|
|
15
|
-
*/
|
|
16
|
-
async function updateHelperPlist(
|
|
17
|
-
plistPath,
|
|
18
|
-
helperName,
|
|
19
|
-
helperId,
|
|
20
|
-
appCFBundleIdentifier,
|
|
21
|
-
) {
|
|
22
|
-
const plistFullPath = path.resolve(plistPath, "Contents/Info.plist");
|
|
23
|
-
const plistJson = parse(await fs.promises.readFile(plistFullPath, "utf-8"));
|
|
24
|
-
plistJson.CFBundleDisplayName = helperName;
|
|
25
|
-
plistJson.CFBundleName = helperName;
|
|
26
|
-
plistJson.CFBundleExecutable = helperName;
|
|
27
|
-
plistJson.CFBundleIdentifier = `${appCFBundleIdentifier}.${helperId}`;
|
|
28
|
-
plistJson.LSFileQuarantineEnabled = false;
|
|
29
|
-
await fs.promises.writeFile(plistFullPath, build(plistJson));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
* @param {object} options - Options.
|
|
35
|
-
* @param {string} options.version - NW.js version.
|
|
36
|
-
* @param {object} options.app - Application configuration.
|
|
37
|
-
* @param {string} options.outDir - Output directory.
|
|
38
|
-
* @param {string} options.releaseInfo - Release information.
|
|
39
|
-
* @returns {Promise<void>} - Promise.
|
|
40
|
-
*/
|
|
41
|
-
export default async function setOsxConfig({
|
|
42
|
-
version,
|
|
43
|
-
app,
|
|
44
|
-
outDir,
|
|
45
|
-
releaseInfo,
|
|
46
|
-
}) {
|
|
47
|
-
if (process.platform === "win32") {
|
|
48
|
-
console.warn(
|
|
49
|
-
"MacOS apps built on Windows platform do not preserve all file permissions. See https://github.com/nwutils/nw-builder/issues/716",
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
/**
|
|
55
|
-
* @type {string | null}
|
|
56
|
-
*/
|
|
57
|
-
const chromiumVersion = releaseInfo?.components?.chromium;
|
|
58
|
-
if (!chromiumVersion) {
|
|
59
|
-
throw new Error("Chromium version is missing.");
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Path to MacOS application.
|
|
63
|
-
* @type {string}
|
|
64
|
-
*/
|
|
65
|
-
const nwjsApp = path.resolve(outDir, "nwjs.app");
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Path to renamed MacOS application.
|
|
69
|
-
* @type {string}
|
|
70
|
-
*/
|
|
71
|
-
const outApp = path.resolve(outDir, `${app.name}.app`);
|
|
72
|
-
|
|
73
|
-
/* Rename `nwjs.app` to `${app.name}.app` */
|
|
74
|
-
await fs.promises.rename(nwjsApp, outApp);
|
|
75
|
-
|
|
76
|
-
/* Rename `Contents/MacOS/nwjs` to `Contents/MacOS/${app.name}` */
|
|
77
|
-
await fs.promises.rename(
|
|
78
|
-
path.resolve(outApp, "Contents", "MacOS", "nwjs"),
|
|
79
|
-
path.resolve(outApp, "Contents", "MacOS", app.name),
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
/* Rename all Helper apps */
|
|
83
|
-
const helperBaseDir = path.resolve(
|
|
84
|
-
outApp,
|
|
85
|
-
"Contents/Frameworks/nwjs Framework.framework/Versions",
|
|
86
|
-
/* TODO: Version mismatch tracked in https://github.com/nwjs/nw.js/issues/8371 */
|
|
87
|
-
"Current",
|
|
88
|
-
"Helpers",
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const helperApps = [
|
|
92
|
-
{ name: "nwjs Helper (Alerts).app", id: "helper.alert" },
|
|
93
|
-
{ name: "nwjs Helper (GPU).app", id: "helper.gpu" },
|
|
94
|
-
{ name: "nwjs Helper (Renderer).app", id: "helper.renderer" },
|
|
95
|
-
{ name: "nwjs Helper.app", id: "helper" },
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
/* MacOS Plugin Helper is removed in NW.js v0.111.0 (Chromium M148) */
|
|
99
|
-
if (semver.lt(version, "0.111.0")) {
|
|
100
|
-
helperApps.push({
|
|
101
|
-
name: "nwjs Helper (Plugin).app",
|
|
102
|
-
id: "helper.plugin",
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
for (const helperApp of helperApps) {
|
|
107
|
-
const newHelperAppName = helperApp.name.replace(/^nwjs/, app.name);
|
|
108
|
-
const oldPath = path.resolve(helperBaseDir, helperApp.name);
|
|
109
|
-
const newPath = path.resolve(helperBaseDir, newHelperAppName);
|
|
110
|
-
|
|
111
|
-
// Rename Helper base directory
|
|
112
|
-
await fs.promises.rename(oldPath, newPath);
|
|
113
|
-
|
|
114
|
-
// Rename Helper sub-directory
|
|
115
|
-
const helperBaseName = helperApp.name.replace(/.app$/, "");
|
|
116
|
-
const subPathBase = path.resolve(newPath, "Contents/MacOS/");
|
|
117
|
-
const oldSubPath = path.resolve(subPathBase, helperBaseName);
|
|
118
|
-
const newSubPath = path.resolve(
|
|
119
|
-
subPathBase,
|
|
120
|
-
helperBaseName.replace(/^nwjs/, app.name),
|
|
121
|
-
);
|
|
122
|
-
await fs.promises.rename(oldSubPath, newSubPath);
|
|
123
|
-
|
|
124
|
-
// Update Helper Plist file
|
|
125
|
-
await updateHelperPlist(
|
|
126
|
-
newPath,
|
|
127
|
-
newHelperAppName.replace(/.app$/, ""),
|
|
128
|
-
helperApp.id,
|
|
129
|
-
app.CFBundleIdentifier,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/* Replace default icon with user defined icon if specified. */
|
|
134
|
-
if (app.icon !== undefined) {
|
|
135
|
-
await fs.promises.copyFile(
|
|
136
|
-
path.resolve(app.icon),
|
|
137
|
-
path.resolve(outApp, "Contents", "Resources", "app.icns"),
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Path to `nwjs.app/Contents/Info.plist`
|
|
143
|
-
* @type {string}
|
|
144
|
-
*/
|
|
145
|
-
const contentsInfoPlistPath = path.resolve(
|
|
146
|
-
outApp,
|
|
147
|
-
"Contents",
|
|
148
|
-
"Info.plist",
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Path to `nwjs.app/Contents/Resources/en.lproj/InfoPlist.settings`
|
|
153
|
-
* @type {string}
|
|
154
|
-
*/
|
|
155
|
-
const contentsResourcesEnLprojInfoPlistStringsPath = path.resolve(
|
|
156
|
-
outApp,
|
|
157
|
-
"Contents",
|
|
158
|
-
"Resources",
|
|
159
|
-
"en.lproj",
|
|
160
|
-
"InfoPlist.strings",
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* JSON from `nwjs.app/Contents/Info.plist`
|
|
165
|
-
* @type {object}
|
|
166
|
-
*/
|
|
167
|
-
const contentsInfoPlistJson = parse(
|
|
168
|
-
await fs.promises.readFile(contentsInfoPlistPath, "utf-8"),
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
/* Update Plist with user defined values. */
|
|
172
|
-
contentsInfoPlistJson.LSApplicationCategoryType =
|
|
173
|
-
app.LSApplicationCategoryType;
|
|
174
|
-
contentsInfoPlistJson.CFBundleIdentifier = app.CFBundleIdentifier;
|
|
175
|
-
contentsInfoPlistJson.CFBundleName = app.CFBundleName;
|
|
176
|
-
contentsInfoPlistJson.CFBundleDisplayName = app.CFBundleDisplayName;
|
|
177
|
-
contentsInfoPlistJson.CFBundleSpokenName = app.CFBundleSpokenName;
|
|
178
|
-
contentsInfoPlistJson.CFBundleVersion = app.CFBundleVersion;
|
|
179
|
-
contentsInfoPlistJson.CFBundleShortVersionString =
|
|
180
|
-
app.CFBundleShortVersionString;
|
|
181
|
-
contentsInfoPlistJson.CFBundleExecutable = app.name;
|
|
182
|
-
contentsInfoPlistJson.NSLocalNetworkUsageDescription =
|
|
183
|
-
app.NSLocalNetworkUsageDescription;
|
|
184
|
-
/* Workaround for https://github.com/nwjs/nw.js/issues/7646 */
|
|
185
|
-
contentsInfoPlistJson.LSFileQuarantineEnabled = false;
|
|
186
|
-
|
|
187
|
-
/* Remove properties that were not updated by the user. */
|
|
188
|
-
Object.keys(contentsInfoPlistJson).forEach((option) => {
|
|
189
|
-
if (contentsInfoPlistJson[option] === undefined) {
|
|
190
|
-
delete contentsInfoPlistJson[option];
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Data from `nwjs.app/Contents/Resources/en.lproj/InfoPlist.settings`
|
|
196
|
-
* @type {string[]}
|
|
197
|
-
*/
|
|
198
|
-
const contentsResourcesEnLprojInfoPlistStringsArray = (
|
|
199
|
-
await fs.promises.readFile(
|
|
200
|
-
contentsResourcesEnLprojInfoPlistStringsPath,
|
|
201
|
-
"utf-8",
|
|
202
|
-
)
|
|
203
|
-
).split("\n");
|
|
204
|
-
contentsResourcesEnLprojInfoPlistStringsArray.forEach((line, idx, arr) => {
|
|
205
|
-
if (line.includes("NSHumanReadableCopyright")) {
|
|
206
|
-
arr[idx] =
|
|
207
|
-
`NSHumanReadableCopyright = "${app.NSHumanReadableCopyright}";`;
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
/* Write the updated values to their config files. */
|
|
212
|
-
await fs.promises.writeFile(
|
|
213
|
-
contentsInfoPlistPath,
|
|
214
|
-
build(contentsInfoPlistJson),
|
|
215
|
-
);
|
|
216
|
-
await fs.promises.writeFile(
|
|
217
|
-
contentsResourcesEnLprojInfoPlistStringsPath,
|
|
218
|
-
contentsResourcesEnLprojInfoPlistStringsArray
|
|
219
|
-
.toString()
|
|
220
|
-
.replace(/,/g, "\n"),
|
|
221
|
-
);
|
|
222
|
-
} catch (error) {
|
|
223
|
-
console.error(error);
|
|
224
|
-
}
|
|
225
|
-
}
|
package/src/bld.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
import child_process from "node:child_process";
|
|
2
|
-
import console from "node:console";
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import process from "node:process";
|
|
6
|
-
|
|
7
|
-
import { ZipArchive } from "archiver";
|
|
8
|
-
import * as resedit from "resedit";
|
|
9
|
-
// pe-library is a direct dependency of resedit
|
|
10
|
-
import * as peLibrary from "pe-library";
|
|
11
|
-
import * as tar from "tar";
|
|
12
|
-
|
|
13
|
-
import util from "./util.js";
|
|
14
|
-
import setOsxConfig from "./bld/osx.js";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* References:
|
|
18
|
-
* https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
|
|
19
|
-
* @typedef {object} LinuxRc Linux configuration options
|
|
20
|
-
* @property {string} name Name of the application
|
|
21
|
-
* @property {string} genericName Generic name of the application
|
|
22
|
-
* @property {boolean} noDisplay If true the application is not displayed
|
|
23
|
-
* @property {string} comment Tooltip for the entry, for example "View sites on the Internet".
|
|
24
|
-
* @property {string} icon Icon to display in file manager, menus, etc.
|
|
25
|
-
* @property {boolean} hidden TBD
|
|
26
|
-
* @property {string[]} onlyShowIn A list of strings identifying the desktop environments that should (/not) display a given desktop entry
|
|
27
|
-
* @property {string[]} notShowIn A list of strings identifying the desktop environments that should (/not) display a given desktop entry
|
|
28
|
-
* @property {boolean} dBusActivatable A boolean value specifying if D-Bus activation is supported for this application
|
|
29
|
-
* @property {string} tryExec Path to an executable file on disk used to determine if the program is actually installed
|
|
30
|
-
* @property {string} exec Program to execute, possibly with arguments.
|
|
31
|
-
* @property {string} path If entry is of type Application, the working directory to run the program in.
|
|
32
|
-
* @property {boolean} terminal Whether the program runs in a terminal window.
|
|
33
|
-
* @property {string[]} actions Identifiers for application actions.
|
|
34
|
-
* @property {string[]} mimeType The MIME type(s) supported by this application.
|
|
35
|
-
* @property {string[]} categories Categories in which the entry should be shown in a menu
|
|
36
|
-
* @property {string[]} implements A list of interfaces that this application implements.
|
|
37
|
-
* @property {string[]} keywords A list of strings which may be used in addition to other metadata to describe this entry.
|
|
38
|
-
* @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.
|
|
39
|
-
* @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
|
|
40
|
-
* @property {boolean} prefersNonDefaultGPU If true, the application prefers to be run on a more powerful discrete GPU if available.
|
|
41
|
-
* @property {string} singleMainWindow If true, the application has a single main window, and does not support having an additional one opened.
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* References:
|
|
46
|
-
* https://developer.apple.com/documentation/bundleresources/information_property_list
|
|
47
|
-
* @typedef {object} OsxRc OSX resource configuration options
|
|
48
|
-
* @property {string} name The name of the application
|
|
49
|
-
* @property {string} icon The path to the icon file. It should be a .icns file.
|
|
50
|
-
* @property {string} LSApplicationCategoryType The category that best describes your app for the App Store.
|
|
51
|
-
* @property {string} CFBundleIdentifier A unique identifier for a bundle usually in reverse DNS format.
|
|
52
|
-
* @property {string} CFBundleName A user-visible short name for the bundle.
|
|
53
|
-
* @property {string} CFBundleDisplayName The user-visible name for the bundle.
|
|
54
|
-
* @property {string} CFBundleSpokenName A replacement for the app name in text-to-speech operations.
|
|
55
|
-
* @property {string} CFBundleVersion The version of the build that identifies an iteration of the bundle.
|
|
56
|
-
* @property {string} CFBundleShortVersionString The release or version number of the bundle.
|
|
57
|
-
* @property {string} NSHumanReadableCopyright A human-readable copyright notice for the bundle.
|
|
58
|
-
* @property {string} NSLocalNetworkUsageDescription A human-readable description of why the application needs access to the local network.
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* References:
|
|
63
|
-
* https://learn.microsoft.com/en-us/windows/win32/msi/version
|
|
64
|
-
* https://learn.microsoft.com/en-gb/windows/win32/sbscs/application-manifests
|
|
65
|
-
* https://learn.microsoft.com/en-us/visualstudio/deployment/trustinfo-element-clickonce-application?view=vs-2022#requestedexecutionlevel
|
|
66
|
-
* https://learn.microsoft.com/en-gb/windows/win32/menurc/versioninfo-resource
|
|
67
|
-
* @typedef {object} WinRc Windows configuration options. More info
|
|
68
|
-
* @property {string} name The name of the application
|
|
69
|
-
* @property {string} version The version of the application
|
|
70
|
-
* @property {string} comments Additional information that should be displayed for diagnostic purposes.
|
|
71
|
-
* @property {string} company Company that produced the file—for example, Microsoft Corporation or Standard Microsystems Corporation, Inc. This string is required.
|
|
72
|
-
* @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.
|
|
73
|
-
* @property {string} fileVersion Version number of the file. For example, 3.10 or 5.00.RC2. This string is required.
|
|
74
|
-
* @property {string} icon The path to the icon file. It should be a .ico file.
|
|
75
|
-
* @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.
|
|
76
|
-
* @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.
|
|
77
|
-
* @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.
|
|
78
|
-
* @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.
|
|
79
|
-
* @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.
|
|
80
|
-
* @property {string} productName Name of the product with which the file is distributed. This string is required.
|
|
81
|
-
* @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.
|
|
82
|
-
* @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.
|
|
83
|
-
* @property {string} languageCode Language of the file, defined by Microsoft, see: https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @typedef {object} BuildOptions
|
|
88
|
-
* @property {string | "latest" | "stable" | "lts"} [version = "latest"] Runtime version
|
|
89
|
-
* @property {"normal" | "sdk"} [flavor = "normal"] Build flavor
|
|
90
|
-
* @property {"linux" | "osx" | "win"} [platform] Target platform
|
|
91
|
-
* @property {"ia32" | "x64" | "arm64"} [arch] Target arch
|
|
92
|
-
* @property {string} [manifestUrl = "https://nwjs.io/versions.json"] Versions manifest URI, https or file path
|
|
93
|
-
* @property {string} [srcDir = "./src"] Source directory
|
|
94
|
-
* @property {string} [cacheDir = "./cache"] Cache directory
|
|
95
|
-
* @property {string} [outDir = "./out"] Out directory
|
|
96
|
-
* @property {LinuxRc | WinRc | OsxRc} [app] Platform specific rc
|
|
97
|
-
* @property {boolean} [glob = true] File globbing
|
|
98
|
-
* @property {boolean | string | object} [managedManifest = false] Manage manifest
|
|
99
|
-
* @property {false | "zip" | "tar" | "tgz"} [zip = false] Compress built artifacts
|
|
100
|
-
* @property {object} [releaseInfo = {}] Version specific release metadata.
|
|
101
|
-
*/
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Build NW.js application.
|
|
105
|
-
* @async
|
|
106
|
-
* @function
|
|
107
|
-
* @param {BuildOptions} options - Build options
|
|
108
|
-
* @returns {Promise<void>}
|
|
109
|
-
*/
|
|
110
|
-
async function bld({
|
|
111
|
-
version = "latest",
|
|
112
|
-
flavor = "normal",
|
|
113
|
-
platform = util.PLATFORM_KV[process.platform],
|
|
114
|
-
arch = util.ARCH_KV[process.arch],
|
|
115
|
-
srcDir = "./src",
|
|
116
|
-
cacheDir = "./cache",
|
|
117
|
-
outDir = "./out",
|
|
118
|
-
app,
|
|
119
|
-
glob = true,
|
|
120
|
-
managedManifest = false,
|
|
121
|
-
zip = false,
|
|
122
|
-
releaseInfo = {},
|
|
123
|
-
}) {
|
|
124
|
-
const nwDir = path.resolve(
|
|
125
|
-
cacheDir,
|
|
126
|
-
`nwjs${flavor === "sdk" ? "-sdk" : ""}-v${version}-${platform}-${arch}`,
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
await fs.promises.rm(outDir, { force: true, recursive: true });
|
|
130
|
-
await fs.promises.cp(nwDir, outDir, {
|
|
131
|
-
recursive: true,
|
|
132
|
-
verbatimSymlinks: true,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
const files = await util.globFiles({ srcDir, glob });
|
|
136
|
-
|
|
137
|
-
const nwProjectDir = path.resolve(
|
|
138
|
-
outDir,
|
|
139
|
-
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
await fs.promises.mkdir(nwProjectDir, { recursive: true });
|
|
143
|
-
|
|
144
|
-
if (glob) {
|
|
145
|
-
for (let file of files) {
|
|
146
|
-
const stats = await fs.promises.stat(file);
|
|
147
|
-
if (stats.isDirectory()) {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
await fs.promises.cp(file, path.resolve(nwProjectDir, file), {
|
|
151
|
-
recursive: true,
|
|
152
|
-
force: true,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
} else {
|
|
156
|
-
await fs.promises.cp(files, path.resolve(nwProjectDir), {
|
|
157
|
-
recursive: true,
|
|
158
|
-
verbatimSymlinks: true,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const builtManifest = JSON.parse(
|
|
163
|
-
await fs.promises.readFile(
|
|
164
|
-
path.resolve(nwProjectDir, "package.json"),
|
|
165
|
-
"utf8",
|
|
166
|
-
),
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
/* Set `product_string` in manifest for MacOS. This is used in renaming the Helper apps. */
|
|
170
|
-
if (platform === "osx") {
|
|
171
|
-
builtManifest.product_string = app.name;
|
|
172
|
-
await fs.promises.writeFile(
|
|
173
|
-
path.resolve(nwProjectDir, "package.json"),
|
|
174
|
-
JSON.stringify(builtManifest, null, 2),
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
managedManifest === true ||
|
|
180
|
-
typeof managedManifest === "object" ||
|
|
181
|
-
typeof managedManifest === "string"
|
|
182
|
-
) {
|
|
183
|
-
await manageManifest({
|
|
184
|
-
nwPkg: builtManifest,
|
|
185
|
-
managedManifest,
|
|
186
|
-
outDir,
|
|
187
|
-
platform,
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (platform === "linux") {
|
|
192
|
-
await setLinuxConfig({ app, outDir });
|
|
193
|
-
} else if (platform === "win") {
|
|
194
|
-
await setWinConfig({ app, outDir });
|
|
195
|
-
} else if (platform === "osx") {
|
|
196
|
-
await setOsxConfig({ version, app, outDir, releaseInfo });
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (zip !== false) {
|
|
200
|
-
await compress({ zip, outDir });
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const manageManifest = async ({ nwPkg, managedManifest, outDir, platform }) => {
|
|
205
|
-
let manifest = undefined;
|
|
206
|
-
|
|
207
|
-
if (managedManifest === true) {
|
|
208
|
-
manifest = nwPkg;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (typeof managedManifest === "object") {
|
|
212
|
-
manifest = managedManifest;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (typeof managedManifest === "string") {
|
|
216
|
-
manifest = JSON.parse(await fs.promises.readFile(managedManifest));
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (manifest.devDependencies) {
|
|
220
|
-
manifest.devDependencies = undefined;
|
|
221
|
-
}
|
|
222
|
-
manifest.packageManager = manifest.packageManager ?? "npm@*";
|
|
223
|
-
|
|
224
|
-
await fs.promises.writeFile(
|
|
225
|
-
path.resolve(
|
|
226
|
-
outDir,
|
|
227
|
-
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
228
|
-
"package.json",
|
|
229
|
-
),
|
|
230
|
-
JSON.stringify(manifest, null, 2),
|
|
231
|
-
"utf8",
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
const cwd = path.resolve(
|
|
235
|
-
outDir,
|
|
236
|
-
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
if (manifest.packageManager.startsWith("npm")) {
|
|
240
|
-
child_process.execSync("npm install", { cwd });
|
|
241
|
-
} else if (manifest.packageManager.startsWith("yarn")) {
|
|
242
|
-
child_process.execSync("yarn install", { cwd });
|
|
243
|
-
} else if (manifest.packageManager.startsWith("pnpm")) {
|
|
244
|
-
child_process.execSync("pnpm install", { cwd });
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
const setLinuxConfig = async ({ app, outDir }) => {
|
|
249
|
-
if (process.platform === "win32") {
|
|
250
|
-
console.warn(
|
|
251
|
-
"Linux apps built on Windows platform do not preserve all file permissions. See #716",
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
let desktopEntryFile = {
|
|
255
|
-
Type: "Application",
|
|
256
|
-
Version: "1.5",
|
|
257
|
-
Name: app.name,
|
|
258
|
-
GenericName: app.genericName,
|
|
259
|
-
NoDisplay: app.noDisplay,
|
|
260
|
-
Comment: app.comment,
|
|
261
|
-
Icon: app.icon ? path.resolve(outDir, "package.nw", app.icon) : "",
|
|
262
|
-
Hidden: app.hidden,
|
|
263
|
-
OnlyShowIn: app.onlyShowIn,
|
|
264
|
-
NotShowIn: app.notShowIn,
|
|
265
|
-
DBusActivatable: app.dBusActivatable,
|
|
266
|
-
TryExec: app.tryExec,
|
|
267
|
-
Exec: app.exec,
|
|
268
|
-
Path: app.path,
|
|
269
|
-
Terminal: app.terminal,
|
|
270
|
-
Actions: app.actions,
|
|
271
|
-
MimeType: app.mimeType,
|
|
272
|
-
Categories: app.categories,
|
|
273
|
-
Implements: app.implements,
|
|
274
|
-
Keywords: app.keywords,
|
|
275
|
-
StartupNotify: app.startupNotify,
|
|
276
|
-
StartupWMClass: app.startupWMClass,
|
|
277
|
-
PrefersNonDefaultGPU: app.prefersNonDefaultGPU,
|
|
278
|
-
SingleMainWindow: app.singleMainWindow,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
await fs.promises.rename(`${outDir}/nw`, `${outDir}/${app.name}`);
|
|
282
|
-
|
|
283
|
-
let fileContent = "[Desktop Entry]\n";
|
|
284
|
-
Object.keys(desktopEntryFile).forEach((key) => {
|
|
285
|
-
if (desktopEntryFile[key] !== undefined) {
|
|
286
|
-
fileContent += `${key}=${desktopEntryFile[key]}\n`;
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
let filePath = `${outDir}/${app.name}.desktop`;
|
|
290
|
-
await fs.promises.writeFile(filePath, fileContent);
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
const setWinConfig = async ({ app, outDir }) => {
|
|
294
|
-
let versionString = {
|
|
295
|
-
Comments: app.comments,
|
|
296
|
-
CompanyName: app.company,
|
|
297
|
-
FileDescription: app.fileDescription,
|
|
298
|
-
FileVersion: app.fileVersion,
|
|
299
|
-
InternalName: app.internalName,
|
|
300
|
-
LegalCopyright: app.legalCopyright,
|
|
301
|
-
LegalTrademarks: app.legalTrademark,
|
|
302
|
-
OriginalFilename: app.originalFilename,
|
|
303
|
-
PrivateBuild: app.privateBuild,
|
|
304
|
-
ProductName: app.productName,
|
|
305
|
-
ProductVersion: app.productVersion,
|
|
306
|
-
SpecialBuild: app.specialBuild,
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
Object.keys(versionString).forEach((option) => {
|
|
310
|
-
if (versionString[option] === undefined) {
|
|
311
|
-
delete versionString[option];
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
const outDirAppExe = path.resolve(outDir, `${app.name}.exe`);
|
|
316
|
-
await fs.promises.rename(path.resolve(outDir, "nw.exe"), outDirAppExe);
|
|
317
|
-
const exe = peLibrary.NtExecutable.from(
|
|
318
|
-
await fs.promises.readFile(outDirAppExe),
|
|
319
|
-
);
|
|
320
|
-
const res = peLibrary.NtExecutableResource.from(exe);
|
|
321
|
-
// English (United States)
|
|
322
|
-
const EN_US = 1033;
|
|
323
|
-
if (app.icon) {
|
|
324
|
-
const iconBuffer = await fs.promises.readFile(path.resolve(app.icon));
|
|
325
|
-
const iconFile = resedit.Data.IconFile.from(iconBuffer);
|
|
326
|
-
const iconGroupIDs = resedit.Resource.IconGroupEntry.fromEntries(
|
|
327
|
-
res.entries,
|
|
328
|
-
).map((entry) => entry.id);
|
|
329
|
-
resedit.Resource.IconGroupEntry.replaceIconsForResource(
|
|
330
|
-
res.entries,
|
|
331
|
-
/* Should be `IDR_MAINFRAME` */
|
|
332
|
-
iconGroupIDs[0],
|
|
333
|
-
EN_US,
|
|
334
|
-
iconFile.icons.map((i) => i.data),
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
const [vi] = resedit.Resource.VersionInfo.fromEntries(res.entries);
|
|
338
|
-
if (app.languageCode !== EN_US) {
|
|
339
|
-
res.removeResourceEntry(16, 1, EN_US);
|
|
340
|
-
vi.removeAllStringValues({
|
|
341
|
-
lang: EN_US,
|
|
342
|
-
codepage: 1200,
|
|
343
|
-
});
|
|
344
|
-
vi.lang = app.languageCode;
|
|
345
|
-
}
|
|
346
|
-
vi.setFileVersion(app.fileVersion, app.languageCode);
|
|
347
|
-
vi.setProductVersion(app.productVersion, app.languageCode);
|
|
348
|
-
vi.setStringValues(
|
|
349
|
-
{
|
|
350
|
-
lang: app.languageCode,
|
|
351
|
-
codepage: 1200,
|
|
352
|
-
},
|
|
353
|
-
versionString,
|
|
354
|
-
);
|
|
355
|
-
vi.outputToResourceEntries(res.entries);
|
|
356
|
-
res.outputResource(exe);
|
|
357
|
-
const outBuffer = Buffer.from(exe.generate());
|
|
358
|
-
await fs.promises.writeFile(outDirAppExe, outBuffer);
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
const compress = async ({ zip, outDir }) => {
|
|
362
|
-
if (zip === true || zip === "zip") {
|
|
363
|
-
const archive = new ZipArchive();
|
|
364
|
-
const writeStream = fs.createWriteStream(`${outDir}.zip`);
|
|
365
|
-
archive.pipe(writeStream);
|
|
366
|
-
archive.directory(outDir, false);
|
|
367
|
-
await archive.finalize();
|
|
368
|
-
} else if (zip === "tar") {
|
|
369
|
-
await tar.create(
|
|
370
|
-
{
|
|
371
|
-
gzip: false,
|
|
372
|
-
file: `${outDir}.tar`,
|
|
373
|
-
},
|
|
374
|
-
[outDir],
|
|
375
|
-
);
|
|
376
|
-
} else if (zip === "tgz") {
|
|
377
|
-
await tar.create(
|
|
378
|
-
{
|
|
379
|
-
gzip: true,
|
|
380
|
-
file: `${outDir}.tgz`,
|
|
381
|
-
},
|
|
382
|
-
[outDir],
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
await fs.promises.rm(outDir, { recursive: true, force: true });
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
export default bld;
|