-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.js
executable file
·269 lines (240 loc) · 11 KB
/
build.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/usr/bin/env node
// extbuild
// https://github.com/waymondrang/extbuild
const start_time = new Date();
const fs = require('fs-extra');
const { execSync } = require("child_process");
const path = require('path');
const ogl = console.log;
const browser_platforms = ["firefox"];
const manifest_ignore = ["manifest_version"];
// variable isn't used anymore but keeping for future reference
const scripts_directory = __dirname;
var config;
var source_manifest;
var targets; // from build_config.json
/**
* Default log channel
*
* Independent of build_config.json
* @returns void
*/
var log = function () {
a = [];
a.push(`[${new Date().toLocaleTimeString()}][info] \t`);
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
ogl.apply(console, a);
};
/**
* Debug log channel
*
* Do not invoke before build_config.json is loaded
* @returns void
*/
var log_d = function () {
if (!config.debug) return;
a = [];
a.push(`[${new Date().toLocaleTimeString()}][info] \t`);
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
ogl.apply(console, a);
};
/**
* Warning log channel
*
* Independent of build_config.json
* @returns void
*/
var log_w = function () {
a = [];
a.push("\x1b[33m" + `[${new Date().toLocaleTimeString()}][warn] \t`);
a.push(...arguments);
a.push("\x1b[0m")
ogl.apply(console, a);
};
log("\x1b[32m" + "initializing extension builder™ in " + "\x1b[0m");
log("\x1b[32m" + process.cwd() + "\x1b[0m");
process.on("exit", function (code) {
log("\x1b[36m" + "process exited in " + ((new Date() - start_time) / 1000) + " seconds with code " + code + "\x1b[0m");
});
// find and load build_config.json
try {
config = JSON.parse(fs.readFileSync("build_config.json", "utf8"));
log("build_config.json found");
} catch (e) {
log_w("build_config.json not found");
process.exit(99);
}
// find and load source_manifest.json
try {
source_manifest = JSON.parse(fs.readFileSync(config.source.directory + "/" + "manifest.json", "utf8"));
} catch {
log_w("could not read source manifest in ", config.source.directory);
process.exit(99);
}
const force_mode = process.argv.includes("--ignore") || process.argv.includes("--force");
const will_package = process.argv.includes("--all") || process.argv.includes("--package") || config.default_actions.includes("package");
const will_copy = process.argv.includes("--copy") || process.argv.includes("--all") || config.default_actions.includes("copy");
const will_git = process.argv.includes("--git") || process.argv.includes("--all") || config.default_actions.includes("git");
const version_exists = fs.existsSync(`${config.release_directory}/${config.project_name_short}_v${source_manifest.version}_${config.source.platform}.zip`);
targets = config.targets;
log("\x1b[32m" + "actions to perform: " + (will_copy ? "copy " : "") + (will_package ? "package " : "") + (will_git ? "git " : "") + "\x1b[0m");
log_d(config.debug ? "debug mode " : "" +
version_exists ? "version exists " : "" +
force_mode ? "force mode " : "");
if (!fs.existsSync(config.release_directory) || !fs.statSync(config.release_directory).isDirectory()) {
log("creating release directory " + config.release_directory);
fs.mkdirSync(config.release_directory);
log("created release directory " + config.release_directory);
}
// manifest updates happen here
log("updating " + targets.map(e => e.platform).join(", ") + " manifests using " + config.source.platform + " manifest");
// clean manifest
if (config.clean_manifest) {
for (field in source_manifest) {
if (!source_manifest[field] ||
Array.isArray(source_manifest[field]) ? !source_manifest[field].length : false ||
typeof source_manifest[field] === 'object' ? !Object.keys(source_manifest[field]).length : false) {
log_w(field + " field is empty");
delete source_manifest[field];
log("cleaned field " + field);
cleaned = true;
}
}
fs.writeFileSync(config.source.directory + "/manifest.json", JSON.stringify(source_manifest, null, 2));
log("wrote cleaned manifest to source file");
}
for (var target of targets) {
if (target.temp && !will_package) {
log_d("skipping checking if target directory " + target.directory + " exists");
continue;
}
log_d("checking if target directory " + target.directory + " exists");
if (!fs.existsSync(target.directory) || !fs.statSync(target.directory).isDirectory()) {
log("creating target directory " + target.directory);
fs.mkdirSync(target.directory);
log("created target directory " + target.directory);
}
log_d("creating manifest for " + target.platform);
target.manifest = { manifest_version: target.manifest_version };
for (field in source_manifest) {
log_d("processing " + field + " field for " + target.platform + " manifest");
if (manifest_ignore.includes(field)) {
continue;
}
if (source_manifest.manifest_version == 3 && target.manifest_version == 2) {
if (field == "web_accessible_resources") {
target.manifest.web_accessible_resources = source_manifest.web_accessible_resources[0].resources;
continue;
}
if (field == "action") {
target.manifest.browser_action = source_manifest.action;
continue;
}
if (field == "background") {
target.manifest.background = {
scripts: [source_manifest.background.service_worker]
};
continue;
}
}
// If not a special case, just copy the field
target.manifest[field] = source_manifest[field];
}
log_d("writing manifest.json to " + target.directory + "/manifest.json");
fs.writeFileSync(target.directory + "/manifest.json", JSON.stringify(target.manifest, null, 2));
}
log("updated " + targets.map(e => e.platform).join(", ") + " manifests using " + config.source.platform + " manifest");
if (will_copy) {
log("copying files between " + config.source.platform + " and " + targets.map(e => e.platform).join(", ") + " directories");
for (var target of targets) {
if (target.temp && !will_package) {
log_d("skipping copying " + target.directory);
continue;
}
var files = fs.readdirSync(config.source.directory);
for (var file of files) {
let all_js = target.patch.includes("*.js"); // messy "wildcard" support
if (fs.statSync(config.source.directory + "/" + file).isDirectory()) {
log_d("expanding directory " + config.source.directory + "/" + file);
var directory_files = fs.readdirSync(config.source.directory + "/" + file);
files.push(...directory_files.map(e => file + "/" + e));
continue;
}
if (file.includes("manifest.json")) {
log_d("skipping manifest file");
continue;
}
log_d("copying " + (file.length > 30 ? file.substring(0, 30) + "..." : file) + " to " + target.directory + "/" + (file.length > 30 ? file.substring(0, 30) + "..." : file));
fs.copySync(config.source.directory + "/" + file, target.directory + "/" + file);
if (target.patch && (target.patch.includes(file) || (all_js && file.endsWith(".js")))) {
log_d("processing " + file);
var source_file = fs.readFileSync(config.source.directory + "/" + file, { encoding: "utf-8" }).toString();
var target_file;
if (config.source.platform == "chrome") {
if (source_manifest.manifest_version == 3 && target.manifest_version == 2) {
target_file = browser_platforms.includes(target.platform) ? source_file
.replace(/chrome\.action/gm, "browser.browserAction")
.replace(/chrome\./gm, "browser\.") :
source_file
.replace(/chrome\.action/gm, "chrome.browserAction");
} else if (source_manifest.manifest_version == 2 && target.manifest_version == 3) {
log("bump manifest version not yet supported");
process.exit(1);
} else {
log("manifest is equal, still will process browser api compatibility " + file);
target_file = browser_platforms.includes(target.platform) ? source_file
.replace(/chrome\./gm, "browser\.") :
source_file;
}
} else {
log("platform not yet supported for directory sync");
process.exit(1);
}
fs.writeFileSync(target.directory + "/" + file, target_file);
log_d("finished processing " + file);
}
}
log_d("finished copying " + files.length + " files from " + config.source.platform + " into " + target.platform + " directory");
}
log("copied files between " + config.source.platform + " and " + targets.map(e => e.platform).join(", ") + " directories");
if (will_git) {
log("pushing synced directories to github");
execSync(`${path.join(scripts_directory, "git.sh")} \"${config.git_messages.directory_sync}\"`, { shell: true, windowsHide: true });
}
log("copying finished");
}
// packaging section
// first, validation
if (version_exists) {
if (config["enforce_version_control"] && will_package && !force_mode) {
log_w("will not overwrite existing packages for version " + source_manifest.version);
process.exit(99);
}
if (will_package)
log_w("overwriting existing packages for version " + source_manifest.version);
}
// then, package
if (will_package) {
log(`packaging ${source_manifest.version} for ` + targets.map(e => e.platform).join(", ") + " & " + config.source.platform);
var packages = targets;
packages.push(config.source);
for (var package of packages) {
var command = `${path.join(scripts_directory, config.debug ? "package.d.sh" : "package.sh")} \"v${source_manifest.version}\" \"${config.project_name_short}\" \"${package.platform}\" \"${package.directory}\" \"${config.release_directory}\" ${package.temp ? "--temp" : ""}`;
log_d("executing " + command);
execSync(command, { shell: true, windowsHide: true });
log(`packaged ${source_manifest.version} for ` + package.platform);
if (package.temp) {
log("removing temporary target directory " + package.directory);
fs.removeSync(package.directory);
log("removed temporary target directory " + package.directory);
}
}
if (will_git) {
log("pushing completed packages to github");
execSync(`${path.join(scripts_directory, "git.sh")} \"${config.git_messages.packages}\"`, { shell: true, windowsHide: true });
}
}