UNPKG

6.99 kBJavaScriptView Raw
1import fs from "node:fs";
2import path from "node:path";
3import url from 'node:url';
4
5import decompress from "./decompress.js";
6import ffmpeg from "./ffmpeg.js";
7import node from "./node.js";
8import nw from "./nw.js";
9
10import util from "./util.js";
11
12/**
13 * @typedef {object} GetOptions
14 * @property {string | "latest" | "stable" | "lts"} [version = "latest"] Runtime version
15 * @property {"normal" | "sdk"} [flavor = "normal"] Build flavor
16 * @property {"linux" | "osx" | "win"} [platform] Target platform
17 * @property {"ia32" | "x64" | "arm64"} [arch] Target arch
18 * @property {string} [downloadUrl = "https://dl.nwjs.io"] Download server.
19 * @property {string} [cacheDir = "./cache"] Cache directory
20 * @property {boolean} [cache = true] If false, remove cache and redownload.
21 * @property {boolean} [ffmpeg = false] If true, ffmpeg is not downloaded.
22 * @property {false | "gyp"} [nativeAddon = false] Rebuild native modules
23 */
24
25/**
26 * Get binaries.
27 *
28 * @async
29 * @function
30 * @param {GetOptions} options Get mode options
31 * @return {Promise<void>}
32 */
33async function get(options) {
34
35 const uri = new url.URL(options.downloadUrl);
36
37 /* Download server is the cached directory. */
38 if (uri.protocol === 'file:') {
39 options.cacheDir = path.resolve(decodeURIComponent(options.downloadUrl.slice('file://'.length)));
40 }
41
42 /**
43 * If `options.cacheDir` exists, then `true`. Otherwise, it is `false`.
44 *
45 * @type {boolean}
46 */
47 const cacheDirExists = await util.fileExists(options.cacheDir);
48 if (cacheDirExists === false) {
49 await fs.promises.mkdir(options.cacheDir, { recursive: true });
50 }
51
52 /**
53 * File path to compressed binary.
54 *
55 * @type {string}
56 */
57 let nwFilePath = path.resolve(
58 options.cacheDir,
59 `nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${options.platform}-${options.arch}.${options.platform === "linux" ? "tar.gz" : "zip"
60 }`,
61 );
62
63 /**
64 * File path to directory which contain NW.js and related binaries.
65 *
66 * @type {string}
67 */
68 let nwDirPath = path.resolve(
69 options.cacheDir,
70 `nwjs${options.flavor === "sdk" ? "-sdk" : ""}-v${options.version}-${options.platform}-${options.arch}`,
71 );
72
73 // If `options.cache` is false, then remove the compressed binary.
74 if (options.cache === false) {
75 await fs.promises.rm(nwFilePath, {
76 recursive: true,
77 force: true,
78 });
79 }
80
81 // We remove the nwDir to prevent the edge case where you download with ffmpeg flag enabled
82 // but want a subsequent build with ffmpeg flag disabled. By removing the directory and
83 // decompressing it again, we prevent the community ffmpeg files from being left over.
84 // This is important since the community ffmpeg builds have specific licensing constraints.
85 await fs.promises.rm(nwDirPath, { recursive: true, force: true });
86
87 /**
88 * If the compressed binary exists, then `true`. Otherwise, it is `false`.
89 *
90 * @type {boolean}
91 */
92 const nwFilePathExists = await util.fileExists(nwFilePath);
93 if (nwFilePathExists === false) {
94 nwFilePath = await nw(options.downloadUrl, options.version, options.flavor, options.platform, options.arch, options.cacheDir);
95 }
96
97 await decompress(nwFilePath, options.cacheDir);
98
99 await fs.promises.symlink(nwDirPath, './nwjs', );
100
101 if (options.ffmpeg === true) {
102
103 /**
104 * File path to compressed binary which contains community FFmpeg binary.
105 *
106 * @type {string}
107 */
108 let ffmpegFilePath = path.resolve(
109 options.cacheDir,
110 `ffmpeg-${options.version}-${options.platform}-${options.arch}.zip`,
111 );
112
113 // If `options.cache` is false, then remove the compressed binary.
114 if (options.cache === false) {
115 await fs.promises.rm(ffmpegFilePath, {
116 recursive: true,
117 force: true,
118 });
119 }
120
121 /**
122 * If the compressed binary exists, then `true`. Otherwise, it is `false`.
123 *
124 * @type {boolean}
125 */
126 const ffmpegFilePathExists = await util.fileExists(ffmpegFilePath);
127 if (ffmpegFilePathExists === false) {
128 // Do not update the options.downloadUrl with the ffmpeg URL here. Doing so would lead to error when options.ffmpeg and options.nativeAddon are both enabled.
129 const downloadUrl =
130 "https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download";
131 ffmpegFilePath = await ffmpeg(downloadUrl, options.version, options.platform, options.arch, options.cacheDir);
132 }
133
134 await decompress(ffmpegFilePath, options.cacheDir);
135
136 /**
137 * Platform dependant file name of FFmpeg binary.
138 *
139 * @type {string}
140 */
141 let ffmpegFileName = "";
142
143 if (options.platform === "linux") {
144 ffmpegFileName = "libffmpeg.so";
145 } else if (options.platform === "win") {
146 ffmpegFileName = "ffmpeg.dll";
147 } else if (options.platform === "osx") {
148 ffmpegFileName = "libffmpeg.dylib";
149 }
150
151 /**
152 * File path to platform specific FFmpeg file.
153 *
154 * @type {string}
155 */
156 let ffmpegBinaryPath = path.resolve(options.cacheDir, ffmpegFileName);
157
158 /**
159 * File path of where FFmpeg will be copied to.
160 *
161 * @type {string}
162 */
163 let ffmpegBinaryDest = "";
164
165 if (options.platform === "linux") {
166 ffmpegBinaryDest = path.resolve(nwDirPath, "lib", ffmpegFileName);
167 } else if (options.platform === "win") {
168 ffmpegBinaryDest = path.resolve(nwDirPath, ffmpegFileName);
169 } else if (options.platform === "osx") {
170 ffmpegBinaryDest = path.resolve(
171 nwDirPath,
172 "nwjs.app",
173 "Contents",
174 "Frameworks",
175 "nwjs Framework.framework",
176 "Versions",
177 "Current",
178 ffmpegFileName,
179 );
180 }
181
182 await fs.promises.copyFile(ffmpegBinaryPath, ffmpegBinaryDest);
183
184 }
185
186 if (options.nativeAddon === "gyp") {
187
188 /**
189 * File path to NW'js Node headers tarball.
190 *
191 * @type {string}
192 */
193 let nodeFilePath = path.resolve(
194 options.cacheDir,
195 `headers-v${options.version}.tar.gz`,
196 );
197
198 // If `options.cache` is false, then remove the compressed binary.
199 if (options.cache === false) {
200 await fs.promises.rm(nodeFilePath, {
201 recursive: true,
202 force: true,
203 });
204 }
205
206 /**
207 * If the compressed binary exists, then `true`. Otherwise, it is `false`.
208 *
209 * @type {boolean}
210 */
211 const nodeFilePathExists = await util.fileExists(nodeFilePath);
212 if (nodeFilePathExists === false) {
213 nodeFilePath = await node(options.downloadUrl, options.version, options.cacheDir);
214 }
215
216 await decompress(nodeFilePath, options.cacheDir);
217
218 }
219}
220
221export default get;