-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuildFullModule.ts
More file actions
105 lines (84 loc) · 3.8 KB
/
buildFullModule.ts
File metadata and controls
105 lines (84 loc) · 3.8 KB
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
import { $, Glob } from "bun";
import { mkdir, rm } from "node:fs/promises";
import { join } from "node:path";
// MARK: Constants
const ATTRIBUTE = "ClientLoaderSource";
const BUILD_DIRECTORY = "out";
const BUILD_LOCK_PATH = join(BUILD_DIRECTORY, "build.lock");
const CLIENT_PAYLOAD_HEADER =
'local clientArguments = assert(({...})[1] or owner:FindFirstChild(owner:GetAttribute("getClientArgumentsName")), "failed getting remote function arguments"):InvokeServer()\n';
// See <https://github.com/techs-sus/azalea> for more details.
const AZALEA_FLAGS: string = "--minify --novel --level 22";
try {
await mkdir(BUILD_DIRECTORY);
} catch (e) {}
// exists() is slow but i don't wanna handle the error
while (await Bun.file(BUILD_LOCK_PATH).exists()) {
const pid = ~~(await Bun.file(BUILD_LOCK_PATH).text());
try {
process.kill(pid, 0);
} catch (e) {
await Bun.file(BUILD_LOCK_PATH).delete();
break;
}
console.log(`Waiting for build lock to be released by ${pid}...`);
await Bun.sleep(1000);
}
// MARK: Create build lock
await Bun.write(Bun.file(BUILD_LOCK_PATH), process.pid.toString());
// cleanup build directory
const glob = new Glob("build/*.{luau,rbxm,json}");
for await (const path of glob.scan()) {
// do something
await rm(path);
console.log("rm", path);
}
const benchmark = async (fn: () => Promise<unknown>) => {
const start = performance.now();
await fn();
return (performance.now() - start).toFixed(0);
};
const compile = async (rbxmPath: string, projectJsonPath: string, payloadOutPath: string) => {
const rojoTime = await benchmark(async () => await $`rojo build -o ${rbxmPath} ${projectJsonPath}`.quiet());
console.log(`Rojo took ${rojoTime} ms to process ${projectJsonPath}`);
const azaleaTime = await benchmark(
async () =>
await $`azalea generate-full-script -i ${rbxmPath} -o ${payloadOutPath} ${{ raw: AZALEA_FLAGS }}`.quiet(),
);
console.log(`Azalea took ${azaleaTime} ms to generate ${payloadOutPath}`);
};
const mapBuildPathToServer = (p: string) => join("../server/", p);
// MARK: Compile client src
const clientPayloadOut = join(BUILD_DIRECTORY, "client.luau");
await compile(join(BUILD_DIRECTORY, "client.rbxm"), "client/default.project.json", clientPayloadOut);
const fullClientSource = CLIENT_PAYLOAD_HEADER + (await Bun.file(clientPayloadOut).text());
const serverProjectJson = await Bun.file("server/default.project.json").json();
serverProjectJson.globIgnorePaths = serverProjectJson.globIgnorePaths.map(mapBuildPathToServer);
// MARK: Patch paths
const recurseTree = (tree: { $path: string | undefined; [key: string]: unknown }) => {
if (tree.$path !== undefined) tree.$path = mapBuildPathToServer(tree.$path);
Object.keys(tree)
.filter((key) => !key.startsWith("$") && typeof tree[key] === "object")
.forEach((key) => recurseTree((tree as any)[key]));
};
recurseTree(serverProjectJson.tree);
// ensure that if there are other properties we don't delete them
serverProjectJson.tree.$properties ??= {};
serverProjectJson.tree.$properties.Attributes ??= {};
// MARK: Inject attribute
// inject client source as an attribute
// https://rojo.space/docs/v7/properties/#attributes & https://rojo.space/docs/v7/properties/#string
serverProjectJson.tree.$properties.Attributes[ATTRIBUTE] = {
String: fullClientSource,
};
const time = await benchmark(async () => {
// MARK: Compile server src
const injectedServerProjectJsonPath = join(BUILD_DIRECTORY, "final.project.json");
// write the modified project.json
await Bun.write(Bun.file(injectedServerProjectJsonPath), JSON.stringify(serverProjectJson, undefined, 2));
// then build the final payload
await compile(join(BUILD_DIRECTORY, "final.rbxm"), injectedServerProjectJsonPath, join(BUILD_DIRECTORY, "run.luau"));
});
console.log(`Took ${time} ms to build ${BUILD_DIRECTORY}/run.luau`);
// MARK: Release build lock
await Bun.file(BUILD_LOCK_PATH).delete();