nw-builder 4.17.13 → 4.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -89
- package/package.json +13 -9
- package/src/bld/osx.js +81 -52
- package/src/bld.js +105 -93
- package/src/cli.js +44 -24
- package/src/index.d.ts +142 -139
- package/src/index.js +58 -28
- package/src/postinstall.js +12 -4
- package/src/util.js +516 -271
package/src/bld.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import child_process from
|
|
2
|
-
import console from
|
|
3
|
-
import fs from
|
|
4
|
-
import path from
|
|
5
|
-
import process from
|
|
6
|
-
|
|
7
|
-
import { ZipArchive } from
|
|
8
|
-
import * as resedit from
|
|
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
9
|
// pe-library is a direct dependency of resedit
|
|
10
|
-
import * as peLibrary from
|
|
11
|
-
import * as tar from
|
|
10
|
+
import * as peLibrary from "pe-library";
|
|
11
|
+
import * as tar from "tar";
|
|
12
12
|
|
|
13
|
-
import util from
|
|
14
|
-
import setOsxConfig from
|
|
13
|
+
import util from "./util.js";
|
|
14
|
+
import setOsxConfig from "./bld/osx.js";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* References:
|
|
@@ -108,13 +108,13 @@ import setOsxConfig from './bld/osx.js';
|
|
|
108
108
|
* @returns {Promise<void>}
|
|
109
109
|
*/
|
|
110
110
|
async function bld({
|
|
111
|
-
version =
|
|
112
|
-
flavor =
|
|
111
|
+
version = "latest",
|
|
112
|
+
flavor = "normal",
|
|
113
113
|
platform = util.PLATFORM_KV[process.platform],
|
|
114
114
|
arch = util.ARCH_KV[process.arch],
|
|
115
|
-
srcDir =
|
|
116
|
-
cacheDir =
|
|
117
|
-
outDir =
|
|
115
|
+
srcDir = "./src",
|
|
116
|
+
cacheDir = "./cache",
|
|
117
|
+
outDir = "./out",
|
|
118
118
|
app,
|
|
119
119
|
glob = true,
|
|
120
120
|
managedManifest = false,
|
|
@@ -123,20 +123,20 @@ async function bld({
|
|
|
123
123
|
}) {
|
|
124
124
|
const nwDir = path.resolve(
|
|
125
125
|
cacheDir,
|
|
126
|
-
`nwjs${flavor ===
|
|
127
|
-
}-${arch}`,
|
|
126
|
+
`nwjs${flavor === "sdk" ? "-sdk" : ""}-v${version}-${platform}-${arch}`,
|
|
128
127
|
);
|
|
129
128
|
|
|
130
129
|
await fs.promises.rm(outDir, { force: true, recursive: true });
|
|
131
|
-
await fs.promises.cp(nwDir, outDir, {
|
|
130
|
+
await fs.promises.cp(nwDir, outDir, {
|
|
131
|
+
recursive: true,
|
|
132
|
+
verbatimSymlinks: true,
|
|
133
|
+
});
|
|
132
134
|
|
|
133
135
|
const files = await util.globFiles({ srcDir, glob });
|
|
134
136
|
|
|
135
137
|
const nwProjectDir = path.resolve(
|
|
136
138
|
outDir,
|
|
137
|
-
platform !==
|
|
138
|
-
? 'package.nw'
|
|
139
|
-
: 'nwjs.app/Contents/Resources/app.nw',
|
|
139
|
+
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
140
140
|
);
|
|
141
141
|
|
|
142
142
|
await fs.promises.mkdir(nwProjectDir, { recursive: true });
|
|
@@ -147,46 +147,52 @@ async function bld({
|
|
|
147
147
|
if (stats.isDirectory()) {
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
150
|
-
await fs.promises.cp(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
file,
|
|
155
|
-
),
|
|
156
|
-
{ recursive: true, force: true },
|
|
157
|
-
);
|
|
150
|
+
await fs.promises.cp(file, path.resolve(nwProjectDir, file), {
|
|
151
|
+
recursive: true,
|
|
152
|
+
force: true,
|
|
153
|
+
});
|
|
158
154
|
}
|
|
159
155
|
} else {
|
|
160
|
-
await fs.promises.cp(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
),
|
|
165
|
-
{ recursive: true, verbatimSymlinks: true },
|
|
166
|
-
);
|
|
156
|
+
await fs.promises.cp(files, path.resolve(nwProjectDir), {
|
|
157
|
+
recursive: true,
|
|
158
|
+
verbatimSymlinks: true,
|
|
159
|
+
});
|
|
167
160
|
}
|
|
168
161
|
|
|
169
|
-
const builtManifest = JSON.parse(
|
|
162
|
+
const builtManifest = JSON.parse(
|
|
163
|
+
await fs.promises.readFile(
|
|
164
|
+
path.resolve(nwProjectDir, "package.json"),
|
|
165
|
+
"utf8",
|
|
166
|
+
),
|
|
167
|
+
);
|
|
170
168
|
|
|
171
169
|
/* Set `product_string` in manifest for MacOS. This is used in renaming the Helper apps. */
|
|
172
|
-
if (platform ===
|
|
170
|
+
if (platform === "osx") {
|
|
173
171
|
builtManifest.product_string = app.name;
|
|
174
|
-
await fs.promises.writeFile(
|
|
172
|
+
await fs.promises.writeFile(
|
|
173
|
+
path.resolve(nwProjectDir, "package.json"),
|
|
174
|
+
JSON.stringify(builtManifest, null, 2),
|
|
175
|
+
);
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
if (
|
|
178
179
|
managedManifest === true ||
|
|
179
|
-
typeof managedManifest ===
|
|
180
|
-
typeof managedManifest ===
|
|
180
|
+
typeof managedManifest === "object" ||
|
|
181
|
+
typeof managedManifest === "string"
|
|
181
182
|
) {
|
|
182
|
-
await manageManifest({
|
|
183
|
+
await manageManifest({
|
|
184
|
+
nwPkg: builtManifest,
|
|
185
|
+
managedManifest,
|
|
186
|
+
outDir,
|
|
187
|
+
platform,
|
|
188
|
+
});
|
|
183
189
|
}
|
|
184
190
|
|
|
185
|
-
if (platform ===
|
|
191
|
+
if (platform === "linux") {
|
|
186
192
|
await setLinuxConfig({ app, outDir });
|
|
187
|
-
} else if (platform ===
|
|
193
|
+
} else if (platform === "win") {
|
|
188
194
|
await setWinConfig({ app, outDir });
|
|
189
|
-
} else if (platform ===
|
|
195
|
+
} else if (platform === "osx") {
|
|
190
196
|
await setOsxConfig({ version, app, outDir, releaseInfo });
|
|
191
197
|
}
|
|
192
198
|
|
|
@@ -202,61 +208,57 @@ const manageManifest = async ({ nwPkg, managedManifest, outDir, platform }) => {
|
|
|
202
208
|
manifest = nwPkg;
|
|
203
209
|
}
|
|
204
210
|
|
|
205
|
-
if (typeof managedManifest ===
|
|
211
|
+
if (typeof managedManifest === "object") {
|
|
206
212
|
manifest = managedManifest;
|
|
207
213
|
}
|
|
208
214
|
|
|
209
|
-
if (typeof managedManifest ===
|
|
215
|
+
if (typeof managedManifest === "string") {
|
|
210
216
|
manifest = JSON.parse(await fs.promises.readFile(managedManifest));
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
if (manifest.devDependencies) {
|
|
214
220
|
manifest.devDependencies = undefined;
|
|
215
221
|
}
|
|
216
|
-
manifest.packageManager = manifest.packageManager ??
|
|
222
|
+
manifest.packageManager = manifest.packageManager ?? "npm@*";
|
|
217
223
|
|
|
218
224
|
await fs.promises.writeFile(
|
|
219
225
|
path.resolve(
|
|
220
226
|
outDir,
|
|
221
|
-
platform !==
|
|
222
|
-
|
|
223
|
-
: 'nwjs.app/Contents/Resources/app.nw',
|
|
224
|
-
'package.json',
|
|
227
|
+
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
228
|
+
"package.json",
|
|
225
229
|
),
|
|
226
230
|
JSON.stringify(manifest, null, 2),
|
|
227
|
-
|
|
231
|
+
"utf8",
|
|
228
232
|
);
|
|
229
233
|
|
|
230
234
|
const cwd = path.resolve(
|
|
231
235
|
outDir,
|
|
232
|
-
platform !==
|
|
233
|
-
? 'package.nw'
|
|
234
|
-
: 'nwjs.app/Contents/Resources/app.nw',
|
|
236
|
+
platform !== "osx" ? "package.nw" : "nwjs.app/Contents/Resources/app.nw",
|
|
235
237
|
);
|
|
236
238
|
|
|
237
|
-
if (manifest.packageManager.startsWith(
|
|
238
|
-
child_process.execSync(
|
|
239
|
-
} else if (manifest.packageManager.startsWith(
|
|
240
|
-
child_process.execSync(
|
|
241
|
-
} else if (manifest.packageManager.startsWith(
|
|
242
|
-
child_process.execSync(
|
|
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 });
|
|
243
245
|
}
|
|
244
246
|
};
|
|
245
247
|
|
|
246
248
|
const setLinuxConfig = async ({ app, outDir }) => {
|
|
247
|
-
if (process.platform ===
|
|
249
|
+
if (process.platform === "win32") {
|
|
248
250
|
console.warn(
|
|
249
|
-
|
|
251
|
+
"Linux apps built on Windows platform do not preserve all file permissions. See #716",
|
|
250
252
|
);
|
|
251
253
|
}
|
|
252
254
|
let desktopEntryFile = {
|
|
253
|
-
Type:
|
|
254
|
-
Version:
|
|
255
|
+
Type: "Application",
|
|
256
|
+
Version: "1.5",
|
|
255
257
|
Name: app.name,
|
|
256
258
|
GenericName: app.genericName,
|
|
257
259
|
NoDisplay: app.noDisplay,
|
|
258
260
|
Comment: app.comment,
|
|
259
|
-
Icon: app.icon ? path.resolve(outDir,
|
|
261
|
+
Icon: app.icon ? path.resolve(outDir, "package.nw", app.icon) : "",
|
|
260
262
|
Hidden: app.hidden,
|
|
261
263
|
OnlyShowIn: app.onlyShowIn,
|
|
262
264
|
NotShowIn: app.notShowIn,
|
|
@@ -278,7 +280,7 @@ const setLinuxConfig = async ({ app, outDir }) => {
|
|
|
278
280
|
|
|
279
281
|
await fs.promises.rename(`${outDir}/nw`, `${outDir}/${app.name}`);
|
|
280
282
|
|
|
281
|
-
let fileContent =
|
|
283
|
+
let fileContent = "[Desktop Entry]\n";
|
|
282
284
|
Object.keys(desktopEntryFile).forEach((key) => {
|
|
283
285
|
if (desktopEntryFile[key] !== undefined) {
|
|
284
286
|
fileContent += `${key}=${desktopEntryFile[key]}\n`;
|
|
@@ -311,21 +313,25 @@ const setWinConfig = async ({ app, outDir }) => {
|
|
|
311
313
|
});
|
|
312
314
|
|
|
313
315
|
const outDirAppExe = path.resolve(outDir, `${app.name}.exe`);
|
|
314
|
-
await fs.promises.rename(path.resolve(outDir,
|
|
315
|
-
const exe = peLibrary.NtExecutable.from(
|
|
316
|
+
await fs.promises.rename(path.resolve(outDir, "nw.exe"), outDirAppExe);
|
|
317
|
+
const exe = peLibrary.NtExecutable.from(
|
|
318
|
+
await fs.promises.readFile(outDirAppExe),
|
|
319
|
+
);
|
|
316
320
|
const res = peLibrary.NtExecutableResource.from(exe);
|
|
317
321
|
// English (United States)
|
|
318
322
|
const EN_US = 1033;
|
|
319
323
|
if (app.icon) {
|
|
320
324
|
const iconBuffer = await fs.promises.readFile(path.resolve(app.icon));
|
|
321
325
|
const iconFile = resedit.Data.IconFile.from(iconBuffer);
|
|
322
|
-
const iconGroupIDs = resedit.Resource.IconGroupEntry.fromEntries(
|
|
326
|
+
const iconGroupIDs = resedit.Resource.IconGroupEntry.fromEntries(
|
|
327
|
+
res.entries,
|
|
328
|
+
).map((entry) => entry.id);
|
|
323
329
|
resedit.Resource.IconGroupEntry.replaceIconsForResource(
|
|
324
330
|
res.entries,
|
|
325
331
|
/* Should be `IDR_MAINFRAME` */
|
|
326
332
|
iconGroupIDs[0],
|
|
327
333
|
EN_US,
|
|
328
|
-
iconFile.icons.map(i => i.data)
|
|
334
|
+
iconFile.icons.map((i) => i.data),
|
|
329
335
|
);
|
|
330
336
|
}
|
|
331
337
|
const [vi] = resedit.Resource.VersionInfo.fromEntries(res.entries);
|
|
@@ -339,36 +345,42 @@ const setWinConfig = async ({ app, outDir }) => {
|
|
|
339
345
|
}
|
|
340
346
|
vi.setFileVersion(app.fileVersion, app.languageCode);
|
|
341
347
|
vi.setProductVersion(app.productVersion, app.languageCode);
|
|
342
|
-
vi.setStringValues(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
348
|
+
vi.setStringValues(
|
|
349
|
+
{
|
|
350
|
+
lang: app.languageCode,
|
|
351
|
+
codepage: 1200,
|
|
352
|
+
},
|
|
353
|
+
versionString,
|
|
354
|
+
);
|
|
346
355
|
vi.outputToResourceEntries(res.entries);
|
|
347
356
|
res.outputResource(exe);
|
|
348
357
|
const outBuffer = Buffer.from(exe.generate());
|
|
349
358
|
await fs.promises.writeFile(outDirAppExe, outBuffer);
|
|
350
359
|
};
|
|
351
360
|
|
|
352
|
-
const compress = async ({
|
|
353
|
-
zip
|
|
354
|
-
outDir,
|
|
355
|
-
}) => {
|
|
356
|
-
if (zip === true || zip === 'zip') {
|
|
361
|
+
const compress = async ({ zip, outDir }) => {
|
|
362
|
+
if (zip === true || zip === "zip") {
|
|
357
363
|
const archive = new ZipArchive();
|
|
358
364
|
const writeStream = fs.createWriteStream(`${outDir}.zip`);
|
|
359
365
|
archive.pipe(writeStream);
|
|
360
366
|
archive.directory(outDir, false);
|
|
361
367
|
await archive.finalize();
|
|
362
|
-
} else if (zip ===
|
|
363
|
-
await tar.create(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
+
);
|
|
372
384
|
}
|
|
373
385
|
|
|
374
386
|
await fs.promises.rm(outDir, { recursive: true, force: true });
|
package/src/cli.js
CHANGED
|
@@ -1,31 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import process from
|
|
4
|
-
import { program } from
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { program } from "commander";
|
|
5
5
|
|
|
6
|
-
import nwbuild from
|
|
7
|
-
import util from
|
|
6
|
+
import nwbuild from "./index.js";
|
|
7
|
+
import util from "./util.js";
|
|
8
8
|
|
|
9
9
|
program
|
|
10
|
-
.argument(
|
|
11
|
-
.option(
|
|
12
|
-
.option(
|
|
13
|
-
.option(
|
|
14
|
-
.option(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.option(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.option(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
.argument("<string>", "File path(s) to project")
|
|
11
|
+
.option("--mode <string>", "get, run or build mode", "build")
|
|
12
|
+
.option("--version <string>", "NW.js version", "latest")
|
|
13
|
+
.option("--flavor <string>", "NW.js build flavor", "normal")
|
|
14
|
+
.option(
|
|
15
|
+
"--platform <string>",
|
|
16
|
+
"NW.js supported platform",
|
|
17
|
+
util.PLATFORM_KV[process.platform],
|
|
18
|
+
)
|
|
19
|
+
.option(
|
|
20
|
+
"--arch <string>",
|
|
21
|
+
"NW.js supported architecture",
|
|
22
|
+
util.ARCH_KV[process.arch],
|
|
23
|
+
)
|
|
24
|
+
.option(
|
|
25
|
+
"--downloadUrl <string>",
|
|
26
|
+
"NW.js download server",
|
|
27
|
+
"https://dl.nwjs.io",
|
|
28
|
+
)
|
|
29
|
+
.option(
|
|
30
|
+
"--manifestUrl <string>",
|
|
31
|
+
"NW.js versions manifest URI",
|
|
32
|
+
"https://nwjs.io/versions.json",
|
|
33
|
+
)
|
|
34
|
+
.option("--cacheDir <string>", "Cache NW.js binaries", "./cache")
|
|
35
|
+
.option("--outDir <string>", "NW.js build artifacts", "./out")
|
|
36
|
+
.option(
|
|
37
|
+
"--app <object>",
|
|
38
|
+
"Platform specific app metadata. Refer to docs for more info",
|
|
39
|
+
{},
|
|
40
|
+
)
|
|
41
|
+
.option("--cache <boolean>", "Enable/disable caching", true)
|
|
42
|
+
.option("--ffmpeg <boolean>", "Enable/disable community ffmpeg", false)
|
|
43
|
+
.option("--glob <boolean>", "Enable/disable globbing", true)
|
|
44
|
+
.option("--logLevel <string>", "Specify log level", "info")
|
|
45
|
+
.option("--shaSum <boolean>", "Enable/disable shasum", true)
|
|
46
|
+
.option("--zip <string>", "Enable/disable compression", false)
|
|
47
|
+
.option("--managedManifest <string>", "Managed manifest mode", false)
|
|
48
|
+
.option("--nodeAddon <boolean>", "Download NW.js Node headers", false)
|
|
29
49
|
.allowUnknownOption(true)
|
|
30
50
|
.allowExcessArguments(true);
|
|
31
51
|
|
|
@@ -44,7 +64,7 @@ for (const arg of unknownArgs) {
|
|
|
44
64
|
const opts = {
|
|
45
65
|
...program.opts(),
|
|
46
66
|
app: appConfig,
|
|
47
|
-
srcDir: program.args.find((arg) => !arg.startsWith(
|
|
67
|
+
srcDir: program.args.find((arg) => !arg.startsWith("--app")),
|
|
48
68
|
cli: true,
|
|
49
69
|
};
|
|
50
70
|
|