Skip to content

Commit 2344ae1

Browse files
committed
Convert to bun
1 parent 38fb506 commit 2344ae1

File tree

8 files changed

+134
-841
lines changed

8 files changed

+134
-841
lines changed

.github/workflows/update-and-release.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ jobs:
1818
- name: Checkout repository
1919
uses: actions/checkout@v4
2020

21-
- name: Setup deno @ v1
22-
uses: denoland/setup-deno@v1
23-
with:
24-
deno-version: v1.x
21+
- name: Setup bun
22+
uses: oven-sh/setup-bun@v2
23+
24+
- run: bun install
2525

2626
- name: Update and release 🚀
27-
run: deno task run
27+
run: bun start
2828
env:
2929
GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}

bun.lockb

40.5 KB
Binary file not shown.

deno.json

-5
This file was deleted.

deno.lock

-750
This file was deleted.

main.ts

+68-80
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
1-
import "https://deno.land/[email protected]/dotenv/load.ts";
2-
import { ensureDir } from "https://deno.land/[email protected]/fs/mod.ts";
3-
import {
4-
basename,
5-
dirname,
6-
join,
7-
relative,
8-
resolve,
9-
} from "https://deno.land/[email protected]/path/mod.ts";
10-
import { getInput } from "npm:@actions/core@^1.10.1";
11-
import { context } from "npm:@actions/github@^5.1.0";
12-
import JSZip from "npm:jszip@^3.10.1";
13-
// @deno-types="npm:@types/lodash.maxby@^4"
14-
import maxBy from "npm:lodash.maxby@^4.6.0";
15-
import { Octokit } from "npm:octokit@^3.1.2";
16-
// @deno-types="npm:@types/parse-github-url@^1"
17-
import gh from "npm:parse-github-url@^1.0.2";
18-
import { simpleGit } from "npm:simple-git@^3.22.0";
19-
// @deno-types="npm:@types/semver@^7"
20-
import {
21-
clean,
22-
coerce,
23-
inc,
24-
parse,
25-
Range,
26-
satisfies,
27-
valid,
28-
} from "npm:semver@^7.6.0";
29-
import { z } from "npm:zod@^3.22.4";
1+
import { readFile, writeFile } from "node:fs/promises";
2+
import { EOL } from "node:os";
3+
import { basename, dirname, join, relative, resolve } from "node:path";
4+
import { env, exit } from "node:process";
5+
import { Glob, inspect } from "bun";
6+
import { getInput } from "@actions/core";
7+
import { context } from "@actions/github";
8+
import { ensureDir } from "fs-extra";
9+
import JSZip from "jszip";
10+
import maxBy from "lodash.maxby";
11+
import { Octokit } from "octokit";
12+
import gh from "parse-github-url";
13+
import { simpleGit } from "simple-git";
14+
import { coerce, inc, parse, Range, satisfies } from "semver";
15+
import { z } from "zod";
3016
import payloadJson from "./payload.json" with { type: "json" };
3117

3218
const repoSchema = z.object({
@@ -120,51 +106,54 @@ const createMetadata = (
120106
}) satisfies Metadata;
121107

122108
async function* getFilePaths(dir: string): AsyncGenerator<string> {
123-
for await (const entry of Deno.readDir(dir)) {
124-
const path = resolve(dir, entry.name);
125-
if (entry.isDirectory) {
126-
yield* getFilePaths(path);
127-
} else {
128-
yield path;
129-
}
109+
const glob = new Glob("**/*");
110+
for await (
111+
const entry of glob.scan({
112+
cwd: dir,
113+
onlyFiles: true,
114+
})
115+
) {
116+
yield resolve(dir, entry);
130117
}
131118
}
132119

133-
const handleReleaseError = (error: unknown, repo: Repo) => {
120+
const handleReleaseError = (error: unknown, { owner, repo }: Repo) => {
134121
// an error occured while attempting to get the latest release
135122
const parsed = httpErrorSchema.safeParse(error);
136123
if (parsed.success) {
137124
const message = parsed.data.status === 404
138125
? "No releases were found"
139126
: "Could not retrieve releases";
140127

141-
console.error(
142-
`${message} for repo: /${repo.owner}/${repo.repo}`,
143-
`${parsed.data.status} ${parsed.data.message}`,
144-
);
128+
return [
129+
`${message} for repo: /${owner}/${repo}`,
130+
parsed.data.status,
131+
parsed.data.message,
132+
].join(" ");
145133
} else {
146-
console.error(
147-
`Could not retrieve releases for repo: /${repo.owner}/${repo.repo}`,
148-
error,
149-
);
134+
return [
135+
`Could not retrieve releases for repo: /${owner}/${repo}`,
136+
inspect(error, { colors: true }),
137+
].join(EOL);
150138
}
151139
};
152140

153-
const handleAssetError = (error: unknown, asset: Asset) => {
141+
const handleAssetError = (error: unknown, { name }: Asset) => {
154142
// an error occured while attempting to get the latest release
155143
const parsed = httpErrorSchema.safeParse(error);
156144
if (parsed.success) {
157145
const message = parsed.data.status === 404
158-
? `Asset ${asset.name} not found`
159-
: `Could not retrieve asset ${asset.name}`;
146+
? `Asset ${name} not found`
147+
: `Could not retrieve asset ${name}`;
160148

161149
console.error(
162150
`${message} for repo: /${BEPINEX_REPO.owner}/${BEPINEX_REPO.repo}`,
163-
`${parsed.data.status} ${parsed.data.message}`,
151+
parsed.data.status,
152+
parsed.data.message,
164153
);
165154
} else {
166155
console.error(
167-
`Could not retrieve asset ${asset.name} for repo: /${BEPINEX_REPO.owner}/${BEPINEX_REPO.repo}`,
156+
`Could not retrieve asset ${name} for repo: /${BEPINEX_REPO.owner}/${BEPINEX_REPO.repo}`,
168157
error,
169158
);
170159
}
@@ -234,7 +223,7 @@ const embedPayload = async (archive: JSZip) => {
234223
for (
235224
const path of ((await Array.fromAsync(getFilePaths(PAYLOAD_DIR))).sort())
236225
) {
237-
archive.file(relative(PAYLOAD_DIR, path), await Deno.readFile(path));
226+
archive.file(relative(PAYLOAD_DIR, path), await readFile(path));
238227
}
239228

240229
return archive;
@@ -263,7 +252,7 @@ const writeArchiveToDisk = (path: string, archive: JSZip) => {
263252
console.log(`Writing archive to disk: ${path}`);
264253
return archive.generateInternalStream({ type: "uint8array" })
265254
.accumulate()
266-
.then((data) => Deno.writeFile(resolve(path), data));
255+
.then((data) => writeFile(resolve(path), data));
267256
};
268257

269258
const getBepInExArchive = async (
@@ -327,32 +316,33 @@ const mergeArchives = async (...archives: JSZip[]) => {
327316
};
328317

329318
if (import.meta.main) {
330-
if (!Deno.env.get("GITHUB_PERSONAL_ACCESS_TOKEN") && Deno.env.get("CI")) {
331-
console.error("GitHub PAT not set.");
332-
Deno.exit(1);
319+
const { GITHUB_PERSONAL_ACCESS_TOKEN, CI, GITHUB_ACTOR } = env;
320+
321+
if (!GITHUB_PERSONAL_ACCESS_TOKEN && CI) {
322+
throw ("GitHub PAT not set.");
333323
}
334324

335325
const { pusher } = context.payload;
336326
const gitConfigName = (getInput("git-config-email") ||
337327
pusher?.name satisfies string | undefined) ??
338-
Deno.env.get("GITHUB_ACTOR") ??
328+
GITHUB_ACTOR ??
339329
"GitHub Workflow Update and Release";
340330
const gitConfigEmail = (getInput("git-config-email") ||
341331
pusher?.email satisfies string | undefined) ??
342332
`${
343-
Deno.env.get("GITHUB_ACTOR") ?? "github-workflow-update-and-release"
333+
GITHUB_ACTOR ?? "github-workflow-update-and-release"
344334
}@users.noreply.github.com`;
345335

346336
const octokit = new Octokit({
347-
auth: Deno.env.get("GITHUB_PERSONAL_ACCESS_TOKEN"),
337+
auth: GITHUB_PERSONAL_ACCESS_TOKEN,
348338
});
349339

350340
console.log("Getting latest release...");
351341
let latestRelease: Release | undefined;
352342
try {
353343
latestRelease = (await octokit.rest.repos.getLatestRelease(REPO)).data;
354344
} catch (error) {
355-
handleReleaseError(error, REPO);
345+
throw handleReleaseError(error, REPO);
356346
}
357347

358348
const latestReleaseVersion = latestRelease
@@ -364,8 +354,7 @@ if (import.meta.main) {
364354
latestBepInExRelease =
365355
(await octokit.rest.repos.getLatestRelease(BEPINEX_REPO)).data;
366356
} catch (error) {
367-
handleReleaseError(error, BEPINEX_REPO);
368-
Deno.exit(1);
357+
throw handleReleaseError(error, BEPINEX_REPO);
369358
}
370359

371360
const latestPayloadReleases: Release[] = [];
@@ -398,11 +387,10 @@ if (import.meta.main) {
398387
}
399388
}
400389
} catch (error) {
401-
handleReleaseError(error, {
390+
throw handleReleaseError(error, {
402391
owner: repo?.owner ?? JSON.stringify(repo?.owner),
403392
repo: repo?.name ?? JSON.stringify(repo?.name),
404393
});
405-
Deno.exit(1);
406394
}
407395
}
408396

@@ -454,9 +442,10 @@ if (import.meta.main) {
454442
inc(metadata.payload, "patch") ??
455443
payloadJson.version;
456444

457-
await Deno.writeTextFile(
445+
await writeFile(
458446
"payload.json",
459447
JSON.stringify(payloadJson, null, 2),
448+
"utf8",
460449
);
461450
}
462451
}
@@ -476,7 +465,7 @@ if (import.meta.main) {
476465
) {
477466
// both bepinex and our payload have not released an update since last check, so we should cancel
478467
console.log("No updates since last check.");
479-
Deno.exit();
468+
exit();
480469
}
481470

482471
// we have a new release, let's handle it
@@ -504,14 +493,11 @@ if (import.meta.main) {
504493
for (const failure of failed) {
505494
console.error(`Failed to get archive`, failure.asset);
506495
}
507-
Deno.exit(1);
496+
exit(1);
508497
}
509498

510499
if (failed.length === archives.length) {
511-
console.error(
512-
`No valid assets were found in repo /${BEPINEX_REPO.owner}/${BEPINEX_REPO.repo}`,
513-
);
514-
Deno.exit(1);
500+
throw `No valid assets were found in repo /${BEPINEX_REPO.owner}/${BEPINEX_REPO.repo}`;
515501
}
516502

517503
const merged = await mergeArchives(
@@ -572,12 +558,10 @@ if (import.meta.main) {
572558
merged,
573559
);
574560

575-
if (!Deno.env.get("CI")) {
576-
Deno.exit();
577-
}
561+
if (!CI) exit();
578562

579563
// at this point all assets have been successfully downloaded and saved to disk with our payload embedded
580-
await Deno.writeTextFile(METADATA_FILE, JSON.stringify(metadata));
564+
await writeFile(METADATA_FILE, JSON.stringify(metadata), "utf8");
581565

582566
const git = simpleGit();
583567
const status = await git.status();
@@ -587,14 +571,15 @@ if (import.meta.main) {
587571
);
588572

589573
if (!metadataPath) {
590-
console.error("Metadata unchanged!");
591-
Deno.exit(1);
574+
throw "Metadata unchanged!";
592575
}
593576

577+
const { GITHUB_WORKSPACE } = env;
578+
594579
await Promise.all([
595580
git.addConfig(
596581
"safe.directory",
597-
Deno.env.get("GITHUB_WORKSPACE") || "",
582+
GITHUB_WORKSPACE || "",
598583
false,
599584
"global",
600585
),
@@ -665,12 +650,15 @@ ${
665650
...REPO,
666651
release_id: release.data.id,
667652
name: basename(asset),
668-
data: (await Deno.readFile(asset)),
653+
data: await readFile(asset),
669654
},
670655
);
671656
}
672657
} catch (error) {
673-
console.error("Failed to create release", error);
674-
Deno.exit(1);
658+
throw [
659+
"Failed to create release",
660+
inspect(error, { colors: true }),
661+
]
662+
.join(EOL);
675663
}
676664
}

package.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "bepinex.subnautica",
3+
"description": "Tobey's BepInEx Pack for Subnautica",
4+
"private": true,
5+
"module": "main.ts",
6+
"type": "module",
7+
"scripts": {
8+
"start": "bun main.ts"
9+
},
10+
"devDependencies": {
11+
"@total-typescript/ts-reset": "^0.5.1",
12+
"@types/bun": "latest",
13+
"@types/fs-extra": "^11.0.4",
14+
"@types/lodash.maxby": "^4.6.9",
15+
"@types/parse-github-url": "^1.0.3",
16+
"@types/semver": "^7.5.8"
17+
},
18+
"peerDependencies": {
19+
"typescript": "^5.0.0"
20+
},
21+
"dependencies": {
22+
"@actions/core": "^1.10.1",
23+
"@actions/github": "^6.0.0",
24+
"fs-extra": "^11.2.0",
25+
"jszip": "^3.10.1",
26+
"lodash.maxby": "^4.6.0",
27+
"octokit": "^3",
28+
"parse-github-url": "^1.0.3",
29+
"semver": "^7.6.3",
30+
"simple-git": "^3.25.0",
31+
"zod": "^3.23.8"
32+
}
33+
}

reset.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
// Do not add any other lines of code to this file!
2-
import "npm:@total-typescript/ts-reset";
2+
import "@total-typescript/ts-reset";

tsconfig.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"compilerOptions": {
3+
// Enable latest features
4+
"lib": ["ESNext", "DOM"],
5+
"target": "ESNext",
6+
"module": "ESNext",
7+
"moduleDetection": "force",
8+
"jsx": "react-jsx",
9+
"allowJs": true,
10+
11+
// Bundler mode
12+
"moduleResolution": "bundler",
13+
"allowImportingTsExtensions": true,
14+
"verbatimModuleSyntax": true,
15+
"noEmit": true,
16+
17+
// Best practices
18+
"strict": true,
19+
"skipLibCheck": true,
20+
"noFallthroughCasesInSwitch": true,
21+
22+
// Some stricter flags (disabled by default)
23+
"noUnusedLocals": false,
24+
"noUnusedParameters": false,
25+
"noPropertyAccessFromIndexSignature": false
26+
}
27+
}

0 commit comments

Comments
 (0)