-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.mjs
127 lines (114 loc) · 3.3 KB
/
build.mjs
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
import { execSync } from "node:child_process";
import { readFile, readdir } from "node:fs/promises";
import { createReadStream } from "node:fs";
import { resolve } from "node:path";
import { build, context } from "esbuild";
import alias from "esbuild-plugin-alias";
import { postcssModules, sassPlugin } from "esbuild-sass-plugin";
import chokidar from "chokidar";
import { listen } from "listhen";
import * as colors from "colorette";
const dev = process.argv.includes("--dev");
const tsconfig = JSON.parse(await readFile("./tsconfig.json"));
const aliases = Object.fromEntries(Object.entries(tsconfig.compilerOptions.paths).map(([alias, [target]]) => [alias, resolve(target)]));
const hash = execSync("git rev-parse --short HEAD").toString().trim() + (dev ? "-dev" : "");
/** @type import("esbuild").BuildOptions */
const options = {
entryPoints: ["./src/index.ts"],
outfile: "./dist/ropeswing.js",
minify: !dev,
bundle: true,
format: "iife",
target: "esnext",
plugins: [
alias(aliases),
sassPlugin({
type: "style",
transform: postcssModules({
localsConvention: "camelCaseOnly",
}),
}),
{
name: "extensions",
setup: (build) => {
const filter = /@ext\/all/;
build.onResolve({ filter }, ({ path }) => ({ path, namespace: "extensions" }));
build.onLoad({ filter, namespace: "extensions" }, async () => {
const exts = await readdir("./src/ext");
let i = 0;
const exp = [];
const imports = exts.map((e) => (exp.push(`e${i}`), `import e${i++} from "./${e.replace(".ts", ".js")}";`)).join("\n");
return {
contents: `${imports}export const extensions = [${exp.join(", ")}];`,
resolveDir: "./src/ext",
};
});
},
},
],
define: {
ROPESWING_COMMIT: `"${hash}"`,
},
footer: { js: "//# sourceURL=ropeswing" },
legalComments: "none",
};
if (!dev) {
console.log(`Building commit ${hash}...`);
try {
await build(options);
console.log("Build finished");
} catch (e) {
console.error("Build failed");
}
} else {
console.log("Watching for changes");
const ctx = await context(options);
const watcher = chokidar.watch(".", {
ignored: ["**/{.git,node_modules}/**", "dist"],
ignoreInitial: true,
ignorePermissionErrors: true,
});
const debouncedBuild = debouncePromise(
() => ctx.rebuild(),
100,
() => {},
);
watcher.on("all", (ev, path) => {
console.log("Changed", path);
debouncedBuild();
});
const listener = await listen((req, res) => {
res.writeHead(200, {
"Access-Control-Allow-Origin": "*",
});
const stream = createReadStream("./dist/ropeswing.js");
stream.pipe(res);
}, { showURL: false });
const bundle = listener.url + "ropeswing.js";
console.log(` > ${colors.cyan("https://w96.kasi.workers.dev/install?bundle=" + encodeURIComponent(bundle))}\n`);
debouncedBuild();
}
function debouncePromise(fn, delay, onError) {
let timeout;
let promiseInFly;
let callbackPending;
return function debounced(...args) {
if (promiseInFly) {
callbackPending = () => {
debounced(...args);
callbackPending = undefined;
};
} else {
if (timeout != null) clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = undefined;
promiseInFly = fn(...args)
.catch(onError)
.finally(() => {
promiseInFly = undefined;
if (callbackPending) callbackPending();
});
}, delay);
}
};
}