this repo has no description

Begin work on Moonbase update installation

Changed files
+121 -33
packages
core-extensions
+2 -1
packages/core-extensions/package.json
···
"private": true,
"dependencies": {
"@moonlight-mod/core": "workspace:*",
-
"@moonlight-mod/types": "workspace:*"
}
}
···
"private": true,
"dependencies": {
"@moonlight-mod/core": "workspace:*",
+
"@moonlight-mod/types": "workspace:*",
+
"nanotar": "^0.1.1"
}
}
+5 -1
packages/core-extensions/src/moonbase/manifest.json
···
"description": "Save extension filter in config",
"type": "boolean"
}
-
}
}
···
"description": "Save extension filter in config",
"type": "boolean"
}
+
},
+
"cors": [
+
"https://github.com/moonlight-mod/moonlight/releases/download/",
+
"https://objects.githubusercontent.com/github-production-release-asset-"
+
]
}
+87 -12
packages/core-extensions/src/moonbase/native.ts
···
import type { MoonbaseNatives, RepositoryManifest } from "./types";
import extractAsar from "@moonlight-mod/core/asar";
import { repoUrlFile } from "@moonlight-mod/types/constants";
-
export const githubRepo = "moonlight-mod/moonlight";
-
export const nightlyRefUrl = "https://moonlight-mod.github.io/moonlight/ref";
export const userAgent = `moonlight/${moonlightNode.version} (https://github.com/moonlight-mod/moonlight)`;
export default function getNatives(): MoonbaseNatives {
const fs = moonlightNode.fs;
const logger = moonlightNode.getLogger("moonbase/natives");
···
async checkForMoonlightUpdate() {
try {
if (moonlightNode.branch === MoonlightBranch.STABLE) {
-
const req = await fetch(
-
`https://api.github.com/repos/${githubRepo}/releases/latest?_=${Date.now()}`,
-
{
-
headers: {
-
"User-Agent": userAgent
-
}
-
}
-
);
-
const json: { name: string } = await req.json();
return json.name !== moonlightNode.version ? json.name : null;
} else if (moonlightNode.branch === MoonlightBranch.NIGHTLY) {
-
const req = await fetch(`${nightlyRefUrl}?_=${Date.now()}`, {
headers: {
"User-Agent": userAgent
}
···
}
},
async fetchRepositories(repos) {
const ret: Record<string, RepositoryManifest[]> = {};
for (const repo of repos) {
try {
const req = await fetch(repo, {
headers: {
"User-Agent": userAgent
}
···
import type { MoonbaseNatives, RepositoryManifest } from "./types";
import extractAsar from "@moonlight-mod/core/asar";
import { repoUrlFile } from "@moonlight-mod/types/constants";
+
import { parseTarGzip } from "nanotar";
+
const githubRepo = "moonlight-mod/moonlight";
+
const githubApiUrl = `https://api.github.com/repos/${githubRepo}/releases/latest`;
+
const artifactName = "dist.tar.gz";
+
+
const nightlyRefUrl = "https://moonlight-mod.github.io/moonlight/ref";
+
const nightlyZipUrl = "https://moonlight-mod.github.io/moonlight/dist.tar.gz";
+
export const userAgent = `moonlight/${moonlightNode.version} (https://github.com/moonlight-mod/moonlight)`;
+
async function getStableRelease(): Promise<{
+
name: string;
+
assets: {
+
name: string;
+
browser_download_url: string;
+
}[];
+
}> {
+
const req = await fetch(githubApiUrl, {
+
cache: "no-store",
+
headers: {
+
"User-Agent": userAgent
+
}
+
});
+
return await req.json();
+
}
+
export default function getNatives(): MoonbaseNatives {
const fs = moonlightNode.fs;
const logger = moonlightNode.getLogger("moonbase/natives");
···
async checkForMoonlightUpdate() {
try {
if (moonlightNode.branch === MoonlightBranch.STABLE) {
+
const json = await getStableRelease();
return json.name !== moonlightNode.version ? json.name : null;
} else if (moonlightNode.branch === MoonlightBranch.NIGHTLY) {
+
const req = await fetch(nightlyRefUrl, {
+
cache: "no-store",
headers: {
"User-Agent": userAgent
}
···
}
},
+
async updateMoonlight() {
+
// Note: this won't do anything on browser, we should probably disable it
+
// entirely when running in browser.
+
async function downloadStable() {
+
const json = await getStableRelease();
+
const asset = json.assets.find((a) => a.name === artifactName);
+
if (!asset) throw new Error("Artifact not found");
+
+
logger.debug(`Downloading ${asset.browser_download_url}`);
+
const req = await fetch(asset.browser_download_url, {
+
cache: "no-store",
+
headers: {
+
"User-Agent": userAgent
+
}
+
});
+
+
return await req.arrayBuffer();
+
}
+
+
async function downloadNightly() {
+
logger.debug(`Downloading ${nightlyZipUrl}`);
+
const req = await fetch(nightlyZipUrl, {
+
cache: "no-store",
+
headers: {
+
"User-Agent": userAgent
+
}
+
});
+
+
return await req.arrayBuffer();
+
}
+
+
const tar =
+
moonlightNode.branch === MoonlightBranch.STABLE
+
? await downloadStable()
+
: moonlightNode.branch === MoonlightBranch.NIGHTLY
+
? await downloadNightly()
+
: null;
+
+
if (!tar) return;
+
+
const distDir = fs.join(moonlightNode.getMoonlightDir(), "dist");
+
if (await fs.exists(distDir)) await fs.rmdir(distDir);
+
await fs.mkdir(distDir);
+
+
logger.debug("Extracting update");
+
const files = await parseTarGzip(tar);
+
for (const file of files) {
+
if (!file.data) continue;
+
// @ts-expect-error What do you mean their own types are wrong
+
if (file.type !== "file") continue;
+
+
const fullFile = fs.join(distDir, file.name);
+
const fullDir = fs.dirname(fullFile);
+
if (!(await fs.exists(fullDir))) await fs.mkdir(fullDir);
+
await fs.writeFile(fullFile, file.data);
+
}
+
logger.debug("Update extracted");
+
},
+
async fetchRepositories(repos) {
const ret: Record<string, RepositoryManifest[]> = {};
for (const repo of repos) {
try {
const req = await fetch(repo, {
+
cache: "no-store",
headers: {
"User-Agent": userAgent
}
+2
packages/core-extensions/src/moonbase/types.ts
···
export type MoonbaseNatives = {
checkForMoonlightUpdate(): Promise<string | null>;
fetchRepositories(
repos: string[]
): Promise<Record<string, RepositoryManifest[]>>;
···
export type MoonbaseNatives = {
checkForMoonlightUpdate(): Promise<string | null>;
+
updateMoonlight(): Promise<void>;
+
fetchRepositories(
repos: string[]
): Promise<Record<string, RepositoryManifest[]>>;
+17 -19
packages/core-extensions/src/moonbase/webpackModules/updates.ts
···
Notices.addNotice({
element: message,
color: "moonbase-updates-notice",
-
buttons: hasExtensionUpdates
-
? [
-
{
-
name: "Open Moonbase",
-
onClick: () => {
-
const { open } = spacepack.findByExports(
-
"setSection",
-
"clearSubsection"
-
)[0].exports.Z;
-
// settings is lazy loaded thus lazily patched
-
// FIXME: figure out a way to detect if settings has been opened
-
// alreadyjust so the transition isnt as jarring
-
open(UserSettingsSections.ACCOUNT);
-
setTimeout(() => open("moonbase", 0), 0);
-
return true;
-
}
-
}
-
]
-
: []
});
}
}
···
Notices.addNotice({
element: message,
color: "moonbase-updates-notice",
+
buttons: [
+
{
+
name: "Open Moonbase",
+
onClick: () => {
+
const { open } = spacepack.findByExports(
+
"setSection",
+
"clearSubsection"
+
)[0].exports.Z;
+
// settings is lazy loaded thus lazily patched
+
// FIXME: figure out a way to detect if settings has been opened
+
// alreadyjust so the transition isnt as jarring
+
open(UserSettingsSections.ACCOUNT);
+
setTimeout(() => open("moonbase", 0), 0);
+
return true;
+
}
+
}
+
]
});
}
}
+8
pnpm-lock.yaml
···
'@moonlight-mod/types':
specifier: workspace:*
version: link:../types
packages/injector:
dependencies:
···
ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
···
brace-expansion: 2.0.1
ms@2.1.2: {}
natural-compare@1.4.0: {}
···
'@moonlight-mod/types':
specifier: workspace:*
version: link:../types
+
nanotar:
+
specifier: ^0.1.1
+
version: 0.1.1
packages/injector:
dependencies:
···
ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+
nanotar@0.1.1:
+
resolution: {integrity: sha512-AiJsGsSF3O0havL1BydvI4+wR76sKT+okKRwWIaK96cZUnXqH0uNBOsHlbwZq3+m2BR1VKqHDVudl3gO4mYjpQ==}
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
···
brace-expansion: 2.0.1
ms@2.1.2: {}
+
+
nanotar@0.1.1: {}
natural-compare@1.4.0: {}