nw-builder 3.5.6 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.github/CHANGELOG.md +128 -0
  2. package/.github/CODE_OF_CONDUCT.md +55 -0
  3. package/.github/ISSUE_TEMPLATE.md +17 -0
  4. package/{LICENSE → .github/LICENSE} +0 -0
  5. package/.github/PULL_REQUEST_TEMPLATE.md +5 -0
  6. package/.github/workflows/cd.yml +24 -0
  7. package/.github/workflows/ci.yml +30 -0
  8. package/README.md +169 -113
  9. package/bin/nwbuild.cjs +97 -0
  10. package/dist/index.cjs +1 -0
  11. package/lib/Version.cjs +81 -0
  12. package/lib/downloader.cjs +177 -0
  13. package/lib/index.cjs +1078 -0
  14. package/lib/platformOverrides.cjs +147 -0
  15. package/lib/platforms.cjs +141 -0
  16. package/lib/utils.cjs +293 -0
  17. package/lib/versions.cjs +206 -0
  18. package/package.json +94 -62
  19. package/src/index.js +2 -0
  20. package/src/schema/Platform.js +16 -0
  21. package/src/schema/index.js +3 -0
  22. package/src/utilities/checkCache.js +30 -0
  23. package/src/utilities/detectCurrentPlatform.js +24 -0
  24. package/src/utilities/index.js +4 -0
  25. package/test/demo/icon.icns +0 -0
  26. package/test/demo/icon.ico +0 -0
  27. package/test/demo/index.cjs +14 -0
  28. package/test/demo/index.html +10 -0
  29. package/test/demo/package.json +24 -0
  30. package/test/downloader.cjs +131 -0
  31. package/test/expected/README.md +7 -0
  32. package/test/expected/merged +1 -0
  33. package/test/expected/oneOveriddenRestNot/README.md +7 -0
  34. package/test/expected/oneOveriddenRestNot/osx32.json +9 -0
  35. package/test/expected/oneOveriddenRestNot/osx64.json +9 -0
  36. package/test/expected/osx-plist/1.plist +47 -0
  37. package/test/expected/osx-plist/2.plist +40 -0
  38. package/test/expected/osx-plist/README.md +7 -0
  39. package/test/expected/platformOverrides/README.md +7 -0
  40. package/test/expected/platformOverrides/linux32.json +13 -0
  41. package/test/expected/platformOverrides/linux64.json +9 -0
  42. package/test/expected/platformOverrides/osx32.json +12 -0
  43. package/test/expected/platformOverrides/osx64.json +12 -0
  44. package/test/expected/platformOverrides/win32.json +12 -0
  45. package/test/expected/platformOverrides/win64.json +12 -0
  46. package/test/fixtures/README.md +7 -0
  47. package/test/fixtures/invalid.json +3 -0
  48. package/test/fixtures/manifest/README.md +7 -0
  49. package/test/fixtures/manifest/versions.json +29 -0
  50. package/test/fixtures/nwapp/README.md +7 -0
  51. package/test/fixtures/nwapp/images/imagefile.img +1 -0
  52. package/test/fixtures/nwapp/index.html +13 -0
  53. package/test/fixtures/nwapp/javascript/bower_packages/simple/package.json +1 -0
  54. package/test/fixtures/nwapp/javascript/jsfile.js +1 -0
  55. package/test/fixtures/nwapp/package.json +5 -0
  56. package/test/fixtures/oneOveriddenRestNot/README.md +7 -0
  57. package/test/fixtures/oneOveriddenRestNot/package.json +16 -0
  58. package/test/fixtures/osx-plist/Info.plist +93 -0
  59. package/test/fixtures/osx-plist/README.md +7 -0
  60. package/test/fixtures/platformOverrides/README.md +7 -0
  61. package/test/fixtures/platformOverrides/package.json +72 -0
  62. package/test/fixtures/test-strip.zip +0 -0
  63. package/test/fixtures/test.tar.gz +0 -0
  64. package/test/fixtures/test.zip +0 -0
  65. package/test/fixtures/testVersions.html +74 -0
  66. package/test/nwBuilder.cjs +339 -0
  67. package/test/unit/checkCache.test.js +19 -0
  68. package/test/unit/checkCacheDir/v0.64.1/linux64/nw1.app +0 -0
  69. package/test/unit/checkCacheDir/v0.64.1/linux64/nw2.app +0 -0
  70. package/test/unit/detectCurrentPlatform.test.js +58 -0
  71. package/test/utils.cjs +310 -0
  72. package/test/versions.cjs +486 -0
  73. package/CHANGELOG.md +0 -83
  74. package/bin/README.md +0 -7
  75. package/bin/nwbuild +0 -101
  76. package/index.js +0 -1
  77. package/lib/README.md +0 -7
  78. package/lib/Version.js +0 -60
  79. package/lib/detectCurrentPlatform.js +0 -17
  80. package/lib/downloader.js +0 -192
  81. package/lib/index.js +0 -863
  82. package/lib/platforms.js +0 -76
  83. package/lib/utils.js +0 -249
  84. package/lib/versions.js +0 -198
package/lib/index.cjs ADDED
@@ -0,0 +1,1078 @@
1
+ var _ = require("lodash");
2
+ var inherits = require("inherits");
3
+ var EventEmitter = require("events").EventEmitter;
4
+ var fs = require("graceful-fs-extra");
5
+ var recursiveReaddirSync = require("recursive-readdir-sync");
6
+ var path = require("path");
7
+ var thenify = require("thenify");
8
+ var rcedit = thenify(require("rcedit"));
9
+ var winresourcer = thenify(require("winresourcer"));
10
+ var spawn = require("child_process").spawn;
11
+ var semver = require("semver");
12
+ var platformOverrides = require("./platformOverrides.cjs");
13
+ var deprecate = require("deprecate");
14
+ var updateNotifier = require("update-notifier");
15
+ const { checkCache, detectCurrentPlatform } = require("../dist/index.cjs");
16
+
17
+ var NwVersions = require("./versions.cjs");
18
+ var Version = require("./Version.cjs");
19
+ var Utils = require("./utils.cjs");
20
+ var Downloader = require("./downloader.cjs");
21
+ var platforms = require("./platforms.cjs");
22
+
23
+ var pkg = require("../package.json");
24
+
25
+ updateNotifier({ pkg }).notify();
26
+
27
+ // We inherit from EventEmitter for logging
28
+ inherits(NwBuilder, EventEmitter);
29
+ module.exports = NwBuilder;
30
+ function NwBuilder(options) {
31
+ var defaults = {
32
+ files: null,
33
+ appName: false,
34
+ appVersion: false,
35
+ platforms: [detectCurrentPlatform(process)],
36
+ currentPlatform: detectCurrentPlatform(process),
37
+ version: "latest",
38
+ buildDir: "./build",
39
+ cacheDir: "./cache",
40
+ downloadUrl: "https://dl.nwjs.io/",
41
+ manifestUrl: "https://nwjs.io/versions.json",
42
+ flavor: "sdk",
43
+ buildType: "default",
44
+ forceDownload: false,
45
+ macCredits: false,
46
+ macIcns: false,
47
+ macZip: null,
48
+ zip: null,
49
+ zipOptions: null,
50
+ macPlist: false,
51
+ mergeZip: true,
52
+ winVersionString: {},
53
+ winIco: null,
54
+ useRcedit: false,
55
+ argv: [],
56
+ };
57
+ // Intercept the platforms and check for the legacy platforms of 'osx' and 'win' and
58
+ // replace with 'osx32', 'osx64', and 'win32', 'win64' respectively.
59
+ if (typeof options.platforms != "undefined") {
60
+ if (options.platforms.indexOf("osx") >= 0) {
61
+ options.platforms.splice(
62
+ options.platforms.indexOf("osx"),
63
+ 1,
64
+ "osx32",
65
+ "osx64",
66
+ );
67
+ }
68
+ if (options.platforms.indexOf("win") >= 0) {
69
+ options.platforms.splice(
70
+ options.platforms.indexOf("win"),
71
+ 1,
72
+ "win32",
73
+ "win64",
74
+ );
75
+ }
76
+ if (options.platforms.indexOf("linux") >= 0) {
77
+ options.platforms.splice(
78
+ options.platforms.indexOf("linux"),
79
+ 1,
80
+ "linux32",
81
+ "linux64",
82
+ );
83
+ }
84
+ }
85
+ // Assign options
86
+ this.options = _.defaults(options, defaults);
87
+
88
+ // Some Option checking
89
+ if (!this.options.files) {
90
+ throw new Error("Please specify some files");
91
+ }
92
+
93
+ if (this.options.platforms.length === 0)
94
+ throw new Error("No platform to build!");
95
+
96
+ // verify all the platforms specifed by the user are supported
97
+ // this + previous check assures as we have only buildable platforms specified
98
+ this.options.platforms.forEach(function (platform) {
99
+ if (!(platform in platforms))
100
+ throw new Error("Unknown platform " + platform);
101
+ });
102
+
103
+ this._platforms = _.cloneDeep(platforms);
104
+
105
+ // clear all unused platforms
106
+ for (var name in this._platforms) {
107
+ if (this.options.platforms.indexOf(name) === -1)
108
+ delete this._platforms[name];
109
+ }
110
+ }
111
+
112
+ NwBuilder.prototype.build = function (callback) {
113
+ // Let's create a NWjs app
114
+ var build = this.checkFiles()
115
+ .then(this.resolveLatestVersion.bind(this))
116
+ .then(this.checkVersion.bind(this))
117
+ .then(this.platformFilesForVersion.bind(this))
118
+ .then(this.downloadNwjs.bind(this))
119
+ .then(this.preparePlatformSpecificManifests.bind(this))
120
+ .then(this.createReleaseFolder.bind(this))
121
+ .then(this.copyNwjs.bind(this))
122
+ .then(this.handleMacApp.bind(this))
123
+ .then(this.handleWinApp.bind(this))
124
+ .then(this.zipAppFiles.bind(this))
125
+ .then(this.mergeAppFiles.bind(this))
126
+ .then(function (info) {
127
+ // the promise(s) resolves to nothing in some cases
128
+ return info || this;
129
+ });
130
+
131
+ if (typeof callback === "function") {
132
+ build
133
+ .then(function (result) {
134
+ callback(false, result);
135
+ })
136
+ .catch(callback);
137
+ return true;
138
+ }
139
+
140
+ return build;
141
+ };
142
+
143
+ NwBuilder.prototype.run = function (callback) {
144
+ // We do not want to download nwjs for other platforms if are going to run the App
145
+ var platforms = this.options.platforms;
146
+ this.options.platforms = [this.options.currentPlatform];
147
+
148
+ // Let's run this NWjs app
149
+ var run = this.checkFiles()
150
+ .then(this.resolveLatestVersion.bind(this))
151
+ .then(this.checkVersion.bind(this))
152
+ .then(this.platformFilesForVersion.bind(this))
153
+ .then(this.downloadNwjs.bind(this))
154
+ .then(this.runApp.bind(this));
155
+
156
+ if (typeof callback === "function") {
157
+ run
158
+ .then(function (result) {
159
+ this.options.platforms = platforms;
160
+ callback(false, result);
161
+ })
162
+ .catch(function (error) {
163
+ this.options.platforms = platforms;
164
+ callback(true, error);
165
+ });
166
+ return true;
167
+ }
168
+
169
+ return run;
170
+ };
171
+
172
+ NwBuilder.prototype.checkFiles = function () {
173
+ var self = this;
174
+
175
+ return Utils.getFileList(this.options.files)
176
+ .then(function (data) {
177
+ self._appPkg = data.json;
178
+ self._files = data.files;
179
+ return self._appPkg;
180
+ })
181
+ .then(Utils.getPackageInfo)
182
+ .then(function (appPkg) {
183
+ self._appPkg = appPkg;
184
+
185
+ if (!self.options.appName || !self.options.appVersion) {
186
+ self.options.appName = self.options.appName
187
+ ? self.options.appName
188
+ : appPkg.name;
189
+ self.options.appVersion = self.options.appVersion
190
+ ? self.options.appVersion
191
+ : appPkg.version;
192
+ }
193
+ });
194
+ };
195
+
196
+ NwBuilder.prototype.resolveLatestVersion = function () {
197
+ var self = this;
198
+
199
+ if (self.options.version !== "latest") return Promise.resolve();
200
+
201
+ return NwVersions.getLatestVersion(
202
+ self.options.downloadUrl,
203
+ self.options.manifestUrl,
204
+ self.options.flavor,
205
+ ).then(function (latestVersion) {
206
+ self.emit("log", "Latest Version: v" + latestVersion.version);
207
+ self.options.version = latestVersion.version;
208
+ return latestVersion;
209
+ });
210
+ };
211
+
212
+ NwBuilder.prototype.checkVersion = function () {
213
+ var version = this.options.version,
214
+ flavor =
215
+ semver.valid(version) && semver.satisfies(version, "<0.12.3")
216
+ ? "sdk"
217
+ : this.options.flavor,
218
+ self = this;
219
+
220
+ if (!semver.valid(version)) {
221
+ return Promise.reject("The version " + version + " is not valid.");
222
+ }
223
+
224
+ var getVersionFromManifest = function () {
225
+ return NwVersions.getVersion({
226
+ desiredVersion: version,
227
+ downloadUrl: self.options.downloadUrl,
228
+ manifestUrl: self.options.manifestUrl,
229
+ flavor: flavor,
230
+ });
231
+ };
232
+ var getVersion;
233
+
234
+ // if the user specified the exact version and all its platforms are cached, don't hit the manifest at all;
235
+ // just trust the ones are cached and assume they're supported
236
+ if (self.options.version !== "latest") {
237
+ var areAllPlatformsCached = true;
238
+ this._forEachPlatform(function (name, platform) {
239
+ var platformToCheck = platform;
240
+
241
+ if (semver.satisfies(self.options.version, ">=0.12.3")) {
242
+ platformToCheck = _.clone(platform);
243
+ platformToCheck.files = ["*"]; // otherwise it'll try to check cache legacy version files
244
+ }
245
+
246
+ if (
247
+ !self.isPlatformCached(
248
+ name,
249
+ platformToCheck,
250
+ self.options.version,
251
+ flavor,
252
+ )
253
+ ) {
254
+ areAllPlatformsCached = false;
255
+ }
256
+ });
257
+ if (areAllPlatformsCached) {
258
+ getVersion = Promise.resolve(
259
+ new Version({
260
+ version: version,
261
+ flavors: [flavor],
262
+ downloadUrl: self.options.downloadUrl,
263
+ supportedPlatforms: Object.keys(this._platforms),
264
+ }),
265
+ );
266
+ } else {
267
+ // otherwise hit the manifest
268
+ getVersion = getVersionFromManifest();
269
+ }
270
+ } else {
271
+ // otherwise hit the manifest
272
+ getVersion = getVersionFromManifest();
273
+ }
274
+
275
+ return getVersion.then(function (version) {
276
+ self._version = version;
277
+ self._version.flavor = flavor;
278
+ self.emit(
279
+ "log",
280
+ "Using v" +
281
+ self._version.version +
282
+ " (" +
283
+ (self._version.flavor === "" ? "normal" : self._version.flavor + ")"),
284
+ );
285
+ if (self._version.isLegacy) {
286
+ deprecate("NW.js / node-webkit versions <0.12.3 are deprecated.");
287
+ }
288
+ });
289
+ };
290
+
291
+ NwBuilder.prototype.platformFilesForVersion = function () {
292
+ var self = this;
293
+
294
+ this._forEachPlatform(function (name, platform) {
295
+ var satisfied = self.preparePlatformFiles(name, platform);
296
+
297
+ // need the second condition for newer NW.js versions
298
+ if (
299
+ !(
300
+ satisfied &&
301
+ !!self._version.platforms[name + "-" + self._version.flavor]
302
+ )
303
+ ) {
304
+ throw new Error(
305
+ "Unsupported NW.js version '" +
306
+ self._version.version +
307
+ " (" +
308
+ self._version.flavor +
309
+ ")' for platform '" +
310
+ name +
311
+ "'",
312
+ );
313
+ }
314
+ });
315
+
316
+ return Promise.resolve();
317
+ };
318
+
319
+ NwBuilder.prototype.downloadNwjs = function () {
320
+ var self = this,
321
+ downloads = [];
322
+
323
+ this._forEachPlatform(function (name, platform) {
324
+ self.setPlatformCacheDirectory(
325
+ name,
326
+ platform,
327
+ self._version.version,
328
+ self._version.flavor,
329
+ );
330
+ platform.url = self._version.platforms[name + "-" + self._version.flavor];
331
+
332
+ // Ensure that there is a cache folder
333
+ if (self.options.forceDownload) {
334
+ fs.removeSync(platform.cache);
335
+ }
336
+
337
+ fs.mkdirpSync(platform.cache);
338
+ self.emit(
339
+ "log",
340
+ "Create cache folder in " +
341
+ path.resolve(
342
+ self.options.cacheDir,
343
+ self._version.version + "-" + self._version.flavor,
344
+ ),
345
+ );
346
+
347
+ if (
348
+ !self.isPlatformCached(
349
+ name,
350
+ platform,
351
+ self._version.version,
352
+ self._version.flavor,
353
+ )
354
+ ) {
355
+ downloads.push(
356
+ Downloader.downloadAndUnpack(platform.cache, platform.url).catch(
357
+ function (err) {
358
+ if (err.statusCode === 404) {
359
+ self.emit(
360
+ "log",
361
+ "ERROR: The version " +
362
+ self._version.version +
363
+ " (" +
364
+ self._version.flavor +
365
+ ") does not have a corresponding build posted at " +
366
+ self.options.downloadUrl +
367
+ ". Please choose a version from that list.",
368
+ );
369
+ } else {
370
+ self.emit("log", err.msg);
371
+ }
372
+
373
+ return Promise.reject("Unable to download NWjs.");
374
+ },
375
+ ),
376
+ );
377
+ self.emit("log", "Downloading: " + platform.url);
378
+ } else {
379
+ self.emit("log", "Using cache for: " + name);
380
+ }
381
+ });
382
+
383
+ return Promise.all(downloads).then(function (data) {
384
+ Downloader.clearProgressbar();
385
+ return data;
386
+ });
387
+ };
388
+
389
+ NwBuilder.prototype.buildGypModules = function () {
390
+ // @todo
391
+ // If we trigger a rebuild we have to copy
392
+ // the node_modules to a tmp location because
393
+ // we don't want to change the source files
394
+ };
395
+
396
+ NwBuilder.prototype.preparePlatformSpecificManifests = function () {
397
+ if (
398
+ !(
399
+ this._appPkg.platformOverrides &&
400
+ Object.keys(this._appPkg.platformOverrides).length
401
+ )
402
+ ) {
403
+ return Promise.resolve();
404
+ }
405
+
406
+ var self = this;
407
+ var promises = [];
408
+
409
+ self._forEachPlatform(function (name, platform) {
410
+ promises.push(
411
+ new Promise(function (resolve, reject) {
412
+ var overrides = self._appPkg.platformOverrides;
413
+ if (overrides[name] || overrides[name.substr(0, name.length - 2)]) {
414
+ platformOverrides(
415
+ {
416
+ options: self._appPkg,
417
+ platform: name,
418
+ },
419
+ function (err, result) {
420
+ if (err) {
421
+ return reject(err);
422
+ }
423
+
424
+ platform.platformSpecificManifest = result;
425
+ resolve();
426
+ },
427
+ );
428
+ } else {
429
+ resolve();
430
+ }
431
+ }),
432
+ );
433
+ });
434
+
435
+ return Promise.all(promises);
436
+ };
437
+
438
+ NwBuilder.prototype.createReleaseFolder = function () {
439
+ var self = this,
440
+ releasePath,
441
+ directoryCreationPromises = [];
442
+
443
+ if (_.isFunction(self.options.buildType)) {
444
+ releasePath = self.options.buildType.call(self.options);
445
+ } else {
446
+ // buildTypes
447
+ switch (self.options.buildType) {
448
+ case "timestamped":
449
+ releasePath =
450
+ self.options.appName +
451
+ " - " +
452
+ Math.round(Date.now() / 1000).toString();
453
+ break;
454
+
455
+ case "versioned":
456
+ releasePath = self.options.appName + " - v" + self.options.appVersion;
457
+ break;
458
+
459
+ default:
460
+ releasePath = self.options.appName;
461
+ }
462
+ }
463
+
464
+ this._forEachPlatform(function (name, platform) {
465
+ directoryCreationPromises.push(
466
+ new Promise(function (resolve, reject) {
467
+ platform.releasePath = path.resolve(
468
+ self.options.buildDir,
469
+ releasePath,
470
+ name,
471
+ );
472
+
473
+ // Ensure that there is a release Folder, delete and create it.
474
+ fs.remove(platform.releasePath, function (err) {
475
+ if (err) return reject(err);
476
+
477
+ fs.mkdirp(platform.releasePath, function (err) {
478
+ if (err) return reject(err);
479
+
480
+ self.emit(
481
+ "log",
482
+ "Create release folder in " + platform.releasePath,
483
+ );
484
+ resolve();
485
+ });
486
+ });
487
+ }),
488
+ );
489
+ });
490
+
491
+ return Promise.all(directoryCreationPromises);
492
+ };
493
+
494
+ NwBuilder.prototype.copyNwjs = function () {
495
+ var self = this,
496
+ copiedFiles = [];
497
+
498
+ this._forEachPlatform(function (name, platform) {
499
+ // >= v0.12.3
500
+ // Since we only have `*`, we're going to recursively get all the files, then copy them
501
+ // Since a .app is treated like a directory, we need to ignore files inside them and just copy them entirely
502
+ if (platform.files.length === 1 && platform.files[0] === "*") {
503
+ // convert all paths inside a .app, etc. to just point to the .app
504
+ // then remove duplicates
505
+ var files = recursiveReaddirSync(platform.cache).map(function (file) {
506
+ var matches = file.match(/^(.+?(\.app|\.framework))/);
507
+ if (matches) {
508
+ return matches[1];
509
+ }
510
+ return file;
511
+ });
512
+
513
+ var totalFiles = _.uniq(files);
514
+ platform.files = totalFiles;
515
+
516
+ totalFiles.forEach(function (file) {
517
+ var destFile = path.relative(platform.cache, file);
518
+ var options = {};
519
+
520
+ if (["nw", "nwjs.app", "nw.exe"].indexOf(destFile) !== -1) {
521
+ // ignore nwjs.app/Contents/Resources/*.lproj/InfoPlist.strings,
522
+ // otherwise the app name will show as nwjs.app in Finder.
523
+ // *.lproj directory itself needs to be kept to support multiple locales.
524
+ if (destFile === "nwjs.app") {
525
+ options.filter = function (filepath) {
526
+ return !/nwjs\.app\/Contents\/Resources\/[^.]+\.lproj\/InfoPlist\.strings$/.test(
527
+ filepath,
528
+ );
529
+ };
530
+ }
531
+ // rename executable to app name
532
+ destFile = self.options.appName + path.extname(destFile);
533
+ }
534
+
535
+ copiedFiles.push(
536
+ Utils.copyFile(
537
+ file,
538
+ path.join(platform.releasePath, destFile),
539
+ self,
540
+ options,
541
+ ),
542
+ );
543
+ platform.files.push(destFile);
544
+ });
545
+
546
+ return;
547
+ }
548
+
549
+ // legacy
550
+ platform.files.forEach(function (file, i) {
551
+ var destFile = file;
552
+ if (i === 0) {
553
+ // rename executable to app name
554
+ destFile = self.options.appName + path.extname(file);
555
+ // save new filename back to files list
556
+ platform.files[0] = destFile;
557
+ }
558
+ copiedFiles.push(
559
+ Utils.copyFile(
560
+ path.resolve(platform.cache, file),
561
+ path.resolve(platform.releasePath, destFile),
562
+ self,
563
+ ),
564
+ );
565
+ });
566
+ });
567
+
568
+ return Promise.all(copiedFiles);
569
+ };
570
+
571
+ NwBuilder.prototype.isPlatformNeedingZip = function (name, platform) {
572
+ var self = this,
573
+ needsZip = platform.needsZip;
574
+
575
+ if (name.indexOf("osx") === 0 && self.options.macZip != null) {
576
+ deprecate("macZip is deprecated. Use the zip option instead.");
577
+ needsZip = self.options.macZip;
578
+ } else if (self.options.zip != null) {
579
+ needsZip = self.options.zip;
580
+ }
581
+
582
+ return needsZip;
583
+ };
584
+
585
+ NwBuilder.prototype.zipAppFiles = function () {
586
+ var self = this;
587
+
588
+ // Check if zip is needed
589
+ var doAnyNeedZip = false,
590
+ zipOptions = this.options.zipOptions,
591
+ numberOfPlatformsWithoutOverrides = 0;
592
+
593
+ self._zips = {};
594
+
595
+ this._forEachPlatform(function (name, platform) {
596
+ var needsZip = self.isPlatformNeedingZip(name, platform);
597
+
598
+ if (needsZip) {
599
+ var platformSpecific = !!platform.platformSpecificManifest;
600
+
601
+ self._zips[name] = { platformSpecific: platformSpecific };
602
+
603
+ numberOfPlatformsWithoutOverrides += !platformSpecific;
604
+ }
605
+
606
+ doAnyNeedZip = doAnyNeedZip || needsZip;
607
+ });
608
+
609
+ self._needsZip = doAnyNeedZip;
610
+
611
+ return new Promise(function (resolve, reject) {
612
+ if (!self._needsZip) {
613
+ resolve();
614
+ return;
615
+ }
616
+
617
+ // create (or don't create) a ZIP for multiple platforms
618
+ new Promise(function (resolve, reject) {
619
+ if (numberOfPlatformsWithoutOverrides > 1) {
620
+ Utils.generateZipFile(self._files, self, null, zipOptions).then(
621
+ function (zip) {
622
+ resolve(zip);
623
+ },
624
+ reject,
625
+ );
626
+ } else {
627
+ resolve();
628
+ }
629
+ }).then(function (platformAgnosticZip) {
630
+ var zipPromises = [];
631
+
632
+ _.forEach(self._zips, function (zip, platformName) {
633
+ if (platformAgnosticZip && !zip.platformSpecific) {
634
+ zip.file = platformAgnosticZip;
635
+ return;
636
+ }
637
+
638
+ zipPromises.push(
639
+ Utils.generateZipFile(
640
+ self._files,
641
+ self,
642
+ JSON.stringify(
643
+ self._platforms[platformName].platformSpecificManifest,
644
+ ),
645
+ zipOptions,
646
+ ).then(function (file) {
647
+ zip.file = file;
648
+ }),
649
+ );
650
+ });
651
+
652
+ Promise.all(zipPromises).then(resolve, reject);
653
+ }, reject);
654
+ });
655
+ };
656
+
657
+ NwBuilder.prototype.mergeAppFiles = function () {
658
+ var self = this;
659
+
660
+ var copyPromises = [];
661
+
662
+ this._forEachPlatform(function (name, platform) {
663
+ var zipping = self.isPlatformNeedingZip(name, platform);
664
+ // We copy the app files if we are on mac and don't force zip
665
+ if (!zipping) {
666
+ // no zip, copy the files
667
+ self._files.forEach(function (file) {
668
+ var dest;
669
+
670
+ if (name == "osx32" || name === "osx64") {
671
+ dest = path.resolve(
672
+ self.getResourcesDirectoryPath(platform),
673
+ "app.nw",
674
+ file.dest,
675
+ );
676
+ } else {
677
+ dest = path.resolve(platform.releasePath, file.dest);
678
+ }
679
+
680
+ if (file.dest === "package.json" && platform.platformSpecificManifest) {
681
+ copyPromises.push(self.writePlatformSpecificManifest(platform, dest));
682
+ } else {
683
+ copyPromises.push(Utils.copyFile(file.src, dest, self));
684
+ }
685
+ });
686
+ } else if (!self.options.mergeZip) {
687
+ // copy the zipped package.nw into the app directory
688
+ copyPromises.push(
689
+ Utils.copyFile(
690
+ self.getZipFile(name),
691
+ path.resolve(platform.releasePath, "package.nw"),
692
+ self,
693
+ ),
694
+ );
695
+ } else if (name == "osx32" || name == "osx64") {
696
+ // zip just copy the app.nw
697
+ copyPromises.push(
698
+ Utils.copyFile(
699
+ self.getZipFile(name),
700
+ path.resolve(self.getResourcesDirectoryPath(platform), "app.nw"),
701
+ self,
702
+ ),
703
+ );
704
+ } else {
705
+ var executableToMergeWith = self._version.isLegacy
706
+ ? _.first(platform.files)
707
+ : self.getExecutableName(name);
708
+
709
+ // We cat the app.nw file into the .exe / nw
710
+ copyPromises.push(
711
+ Utils.mergeFiles(
712
+ path.resolve(platform.releasePath, executableToMergeWith),
713
+ self.getZipFile(name),
714
+ platform.chmod,
715
+ ),
716
+ );
717
+ }
718
+ });
719
+
720
+ return Promise.all(copyPromises);
721
+ };
722
+
723
+ NwBuilder.prototype.getZipFile = function (platformName) {
724
+ return (this._zips[platformName] && this._zips[platformName].file) || null;
725
+ };
726
+
727
+ NwBuilder.prototype.writePlatformSpecificManifest = function (platform, dest) {
728
+ return new Promise(function (resolve, reject) {
729
+ var pkgParentDirectory = path.join(dest, "../");
730
+ if (!fs.existsSync(pkgParentDirectory)) fs.mkdirpSync(pkgParentDirectory);
731
+
732
+ fs.writeFile(
733
+ dest,
734
+ JSON.stringify(platform.platformSpecificManifest),
735
+ function (err) {
736
+ if (err) return reject(err);
737
+ resolve();
738
+ },
739
+ );
740
+ });
741
+ };
742
+
743
+ NwBuilder.prototype.handleMacApp = function () {
744
+ var self = this,
745
+ allDone = [];
746
+
747
+ this._forEachPlatform(function (name, platform) {
748
+ if (["osx32", "osx64"].indexOf(name) < 0) return;
749
+
750
+ // Let's first handle the mac icon
751
+ if (self.options.macIcns) {
752
+ if (semver.satisfies(self._version.version, "<=0.12.3")) {
753
+ allDone.push(
754
+ Utils.copyFile(
755
+ self.options.macIcns,
756
+ path.resolve(self.getResourcesDirectoryPath(platform), "nw.icns"),
757
+ self,
758
+ ),
759
+ );
760
+ } else {
761
+ allDone.push(
762
+ Utils.copyFile(
763
+ self.options.macIcns,
764
+ path.resolve(self.getResourcesDirectoryPath(platform), "app.icns"),
765
+ self,
766
+ ),
767
+ );
768
+ allDone.push(
769
+ Utils.copyFile(
770
+ self.options.macIcns,
771
+ path.resolve(
772
+ self.getResourcesDirectoryPath(platform),
773
+ "document.icns",
774
+ ),
775
+ self,
776
+ ),
777
+ );
778
+ }
779
+ }
780
+
781
+ // Handle mac credits
782
+ if (self.options.macCredits) {
783
+ allDone.push(
784
+ Utils.copyFile(
785
+ self.options.macCredits,
786
+ path.resolve(
787
+ self.getResourcesDirectoryPath(platform),
788
+ "Credits.html",
789
+ ),
790
+ self,
791
+ ),
792
+ );
793
+ }
794
+
795
+ // Let's handle the Plist
796
+ var PlistPath = path.resolve(
797
+ platform.releasePath,
798
+ self.options.appName + ".app",
799
+ "Contents",
800
+ "Info.plist",
801
+ );
802
+
803
+ // If the macPlist is a string we just copy the file
804
+ if (typeof self.options.macPlist === "string") {
805
+ allDone.push(Utils.copyFile(self.options.macPlist, PlistPath, self));
806
+ } else {
807
+ // Setup the Plist
808
+ var plistOptions = Utils.getPlistOptions(
809
+ {
810
+ name: self.options.appName,
811
+ version: self.options.appVersion,
812
+ copyright: self._appPkg.copyright,
813
+ },
814
+ self.options.macPlist,
815
+ );
816
+
817
+ allDone.push(Utils.editPlist(PlistPath, PlistPath, plistOptions));
818
+ }
819
+ });
820
+
821
+ return Promise.all(allDone);
822
+ };
823
+
824
+ NwBuilder.prototype.handleWinApp = function () {
825
+ var self = this,
826
+ allDone = [];
827
+
828
+ this._forEachPlatform(function (name, platform) {
829
+ if (
830
+ (!self.options.winIco && !self.options.winVersionString) ||
831
+ ["win32", "win64"].indexOf(name) < 0
832
+ )
833
+ return;
834
+
835
+ var executableName = self._version.isLegacy
836
+ ? _.first(platform.files)
837
+ : self.getExecutableName(name);
838
+ var executablePath = path.resolve(platform.releasePath, executableName);
839
+
840
+ var rcConf = {};
841
+ if (self.options.winVersionString) {
842
+ rcConf["version-string"] = Object.assign(
843
+ {},
844
+ {
845
+ // The process name used in the Task Manager
846
+ FileDescription: self.options.appName,
847
+ },
848
+ self.options.winVersionString,
849
+ );
850
+ }
851
+ if (self.options.winIco && self.options.useRcedit) {
852
+ rcConf["icon"] = path.resolve(self.options.winIco);
853
+ }
854
+
855
+ var updateVersionStringPromise = rcedit(executablePath, rcConf);
856
+
857
+ var updateIconsPromise = updateVersionStringPromise.then(function () {
858
+ return new Promise(function (resolve, reject) {
859
+ if (!self.options.winIco || self.options.useRcedit) {
860
+ resolve();
861
+ } else {
862
+ self.emit("log", "Update " + name + " executable icon");
863
+ // Set icon
864
+ winresourcer(
865
+ {
866
+ operation: "Update",
867
+ exeFile: executablePath,
868
+ resourceType: "Icongroup",
869
+ resourceName: "IDR_MAINFRAME",
870
+ lang: 1033, // Required, except when updating or deleting
871
+ resourceFile: path.resolve(self.options.winIco),
872
+ },
873
+ function (err) {
874
+ if (!err) {
875
+ resolve();
876
+ } else {
877
+ reject(
878
+ "Error while updating the Windows icon." +
879
+ (process.platform !== "win32"
880
+ ? " Wine (winehq.org) must be installed to add custom icons from Mac and Linux."
881
+ : ""),
882
+ );
883
+ }
884
+ },
885
+ );
886
+ }
887
+ });
888
+ });
889
+
890
+ // build a promise chain
891
+ allDone.push(updateIconsPromise);
892
+ });
893
+
894
+ return Promise.all(allDone);
895
+ };
896
+
897
+ NwBuilder.prototype.runApp = function () {
898
+ var self = this;
899
+
900
+ var currentPlatform = this.options.currentPlatform;
901
+ var platform = this._platforms[currentPlatform];
902
+ // if the user is on Windows/OS X 64-bit, but there is no 64-bit build, try the 32-bit build
903
+ if (!platform) {
904
+ if (["osx64", "win64"].indexOf(this.options.currentPlatform) !== -1) {
905
+ currentPlatform = currentPlatform.split("64")[0] + "32";
906
+ platform = this._platforms[currentPlatform];
907
+
908
+ if (!platform) {
909
+ throw new Error(
910
+ "currentPlatform selected (" +
911
+ this.options.currentPlatform +
912
+ ") doesn't exist in selected platforms (" +
913
+ Object.keys(this._platforms).join(", ") +
914
+ "). We also tried " +
915
+ currentPlatform +
916
+ " and that doesn't exist either",
917
+ );
918
+ }
919
+ } else {
920
+ throw new Error(
921
+ "currentPlatform selected (" +
922
+ currentPlatform +
923
+ ") doesn't exist in selected platforms (" +
924
+ Object.keys(this._platforms).join(", ") +
925
+ ")",
926
+ );
927
+ }
928
+ }
929
+
930
+ var runnable;
931
+ if (this._version.isLegacy) {
932
+ runnable = platform.getRunnable(this.options.version);
933
+ } else {
934
+ if (currentPlatform.indexOf("osx") === 0) {
935
+ runnable = "nwjs.app/Contents/MacOS/nwjs";
936
+ } else if (currentPlatform.indexOf("win") === 0) {
937
+ runnable = "nw.exe";
938
+ } else {
939
+ runnable = "nw";
940
+ }
941
+ }
942
+ var executable = path.resolve(platform.cache, runnable);
943
+
944
+ self.emit("log", "Launching App");
945
+ return new Promise(function (resolve, reject) {
946
+ var parentDirectory = (
947
+ _.isArray(self.options.files) ? self.options.files[0] : self.options.files
948
+ ).replace(/\*[/*]*/, "");
949
+ var nwProcess = (self._nwProcess = spawn(
950
+ executable,
951
+ [parentDirectory].concat(self.options.argv),
952
+ {
953
+ detached: true,
954
+ windowsHide: true,
955
+ },
956
+ ));
957
+
958
+ self.emit("appstart");
959
+
960
+ nwProcess.stdout.on("data", function (data) {
961
+ self.emit("stdout", data);
962
+ });
963
+
964
+ nwProcess.stderr.on("data", function (data) {
965
+ self.emit("stderr", data);
966
+ });
967
+
968
+ nwProcess.on("error", function (err) {
969
+ self.emit("log", "App launch error: " + err);
970
+ reject(err);
971
+ });
972
+
973
+ nwProcess.on("close", function (code) {
974
+ self._nwProcess = undefined;
975
+ self.emit("log", "App exited with code " + code);
976
+ resolve();
977
+ });
978
+ });
979
+ };
980
+
981
+ NwBuilder.prototype.isAppRunning = function () {
982
+ return this._nwProcess !== undefined;
983
+ };
984
+
985
+ NwBuilder.prototype.getAppProcess = function () {
986
+ return this._nwProcess;
987
+ };
988
+
989
+ NwBuilder.prototype._forEachPlatform = function (fn) {
990
+ _.forEach(this._platforms, function (platform, name) {
991
+ return fn(name, platform);
992
+ });
993
+ };
994
+
995
+ // Mac only
996
+ NwBuilder.prototype.getResourcesDirectoryPath = function (platform) {
997
+ return path.resolve(
998
+ platform.releasePath,
999
+ this.options.appName + ".app",
1000
+ "Contents",
1001
+ "Resources",
1002
+ );
1003
+ };
1004
+
1005
+ // Don't use if legacy version
1006
+ NwBuilder.prototype.getExecutableName = function (platform) {
1007
+ var executableExtension = "";
1008
+
1009
+ if (platform.indexOf("osx") === 0) {
1010
+ executableExtension = ".app";
1011
+ } else if (platform.indexOf("win") === 0) {
1012
+ executableExtension = ".exe";
1013
+ }
1014
+
1015
+ return this.options.appName + executableExtension;
1016
+ };
1017
+
1018
+ NwBuilder.prototype.setPlatformCacheDirectory = function (
1019
+ platformName,
1020
+ platform,
1021
+ version,
1022
+ flavor,
1023
+ ) {
1024
+ if (!platform.cache) {
1025
+ platform.cache = path.resolve(
1026
+ this.options.cacheDir,
1027
+ version + "-" + flavor,
1028
+ platformName,
1029
+ );
1030
+ }
1031
+ };
1032
+
1033
+ NwBuilder.prototype.isPlatformCached = function (
1034
+ platformName,
1035
+ platform,
1036
+ version,
1037
+ flavor,
1038
+ ) {
1039
+ this.setPlatformCacheDirectory(platformName, platform, version, flavor);
1040
+ if (this.options.forceDownload) {
1041
+ return false;
1042
+ }
1043
+ this.preparePlatformFiles(platformName, platform, version);
1044
+ return checkCache(platform.cache, platform.files);
1045
+ };
1046
+
1047
+ // returns a Boolean; true if the desired platform is supported
1048
+ NwBuilder.prototype.preparePlatformFiles = function (
1049
+ platformName,
1050
+ platform,
1051
+ version,
1052
+ ) {
1053
+ // return if platform.files is already prepared
1054
+ if (
1055
+ Object.keys(platform.files)[0] !==
1056
+ Object.keys(platforms[platformName].files)[0]
1057
+ ) {
1058
+ return true;
1059
+ }
1060
+
1061
+ if (semver.satisfies(version, "<0.12.3")) {
1062
+ return !Object.keys(platform.files).every(function (range) {
1063
+ if (semver.satisfies(version, range)) {
1064
+ platform.files = platform.files[range];
1065
+ if ("string" === typeof platform.files) {
1066
+ platform.files = [platform.files];
1067
+ }
1068
+ return false;
1069
+ }
1070
+ return true;
1071
+ });
1072
+ }
1073
+
1074
+ platform.files = ["*"]; // otherwise bad stuff will happen like at attempt to download legacy version files
1075
+ // all we can do here is assume it's oke because this._version might not exist yet, but callers of this function
1076
+ // will check properly where necessary
1077
+ return true;
1078
+ };