Fix View Options popup not responding to clicks
Remove duplicate popup rendering from render_vertical_tabs_panel. The popup was rendered both inside the panel's stack AND at the workspace level in a Dismiss overlay, causing event dispatch conflicts due to shared MouseStateHandle instances between the two identical popup trees.
This commit is contained in:
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build and deploy Galaxy to Hermes (wst.mini-games.tv)
|
||||
#
|
||||
# Required env vars:
|
||||
# HERMES_PASS - password for Hermes authentication
|
||||
#
|
||||
# Optional env vars:
|
||||
# HERMES_USER - username (defaults to "ryan")
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
APP_DIR="$SCRIPT_DIR/build-and-deploy-hermes"
|
||||
|
||||
if [ -z "$HERMES_PASS" ]; then
|
||||
echo "Error: HERMES_PASS environment variable is required."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install deps if needed
|
||||
if [ ! -d "$APP_DIR/node_modules" ]; then
|
||||
echo "Installing dependencies..."
|
||||
cd "$APP_DIR" && yarn install --frozen-lockfile
|
||||
fi
|
||||
|
||||
cd "$APP_DIR" && yarn --silent start
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
dist/
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "build-and-deploy-hermes",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsx src/index.tsx",
|
||||
"start": "tsx src/index.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"ink": "^5.1.0",
|
||||
"ink-spinner": "^5.0.0",
|
||||
"react": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^26.0.0",
|
||||
"@types/react": "^18.3.12",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.6.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
#!/usr/bin/env tsx
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { render, Text, Box } from "ink";
|
||||
import Spinner from "ink-spinner";
|
||||
import { spawn, execSync } from "child_process";
|
||||
import { statSync, readFileSync } from "fs";
|
||||
import { createHash } from "crypto";
|
||||
import path from "path";
|
||||
|
||||
// ─── Configuration ───────────────────────────────────────────────────────────
|
||||
|
||||
const HERMES_USER = process.env.HERMES_USER ?? "ryan";
|
||||
const HERMES_PASS = process.env.HERMES_PASS;
|
||||
|
||||
if (!HERMES_PASS) {
|
||||
console.error("Error: HERMES_PASS environment variable is required.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const BASE_URL = "https://client.wst.mini-games.tv";
|
||||
const UPLOAD_KEY = "wst-data/ryan-share/galaxy/Galaxy.zip";
|
||||
const CONTENT_TYPE = "application/zip";
|
||||
|
||||
// Workspace root is three levels up from script/build-and-deploy-hermes/src
|
||||
const WORKSPACE_ROOT = path.resolve(import.meta.dirname, "../../..");
|
||||
|
||||
// ─── Types ───────────────────────────────────────────────────────────────────
|
||||
|
||||
type StepStatus = "pending" | "running" | "done" | "error";
|
||||
|
||||
interface Step {
|
||||
label: string;
|
||||
status: StepStatus;
|
||||
detail?: string;
|
||||
logs?: string[];
|
||||
progress?: { bytes: number; totalBytes: number };
|
||||
}
|
||||
|
||||
const MAX_LOG_LINES = 15;
|
||||
|
||||
function runCommandStreaming(
|
||||
cmd: string,
|
||||
cwd: string,
|
||||
onLog: (line: string) => void
|
||||
): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(cmd, {
|
||||
cwd,
|
||||
shell: true,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
let leftover = "";
|
||||
const processChunk = (chunk: Buffer) => {
|
||||
const text = leftover + chunk.toString();
|
||||
const lines = text.split("\n");
|
||||
leftover = lines.pop() || "";
|
||||
for (const line of lines) {
|
||||
if (line.trim()) onLog(line);
|
||||
}
|
||||
};
|
||||
|
||||
child.stdout?.on("data", processChunk);
|
||||
child.stderr?.on("data", processChunk);
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (leftover.trim()) onLog(leftover);
|
||||
if (code === 0) resolve();
|
||||
else reject(new Error(`Command failed with exit code ${code}`));
|
||||
});
|
||||
|
||||
child.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
interface StartUploadResponse {
|
||||
uploadId: string;
|
||||
key: string;
|
||||
totalParts: number;
|
||||
partSize: number;
|
||||
urls: { partNumber: number; url: string }[];
|
||||
}
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
const COMMON_HEADERS: Record<string, string> = {
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:152.0) Gecko/20100101 Firefox/152.0",
|
||||
Accept: "*/*",
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Content-Type": "application/json",
|
||||
Origin: BASE_URL,
|
||||
"Sec-GPC": "1",
|
||||
Connection: "keep-alive",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache",
|
||||
};
|
||||
|
||||
function authHeaders(token: string): Record<string, string> {
|
||||
return { ...COMMON_HEADERS, Authorization: `Bearer ${token}` };
|
||||
}
|
||||
|
||||
async function apiPost<T>(url: string, body: object, headers: Record<string, string>): Promise<T> {
|
||||
const res = await fetch(url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(`POST ${url} failed (${res.status}): ${text}`);
|
||||
}
|
||||
return res.json() as Promise<T>;
|
||||
}
|
||||
|
||||
function computeFileHash(filePath: string): string {
|
||||
const hash = createHash("sha256");
|
||||
const data = readFileSync(filePath);
|
||||
hash.update(data);
|
||||
return hash.digest("hex");
|
||||
}
|
||||
|
||||
async function uploadPart(
|
||||
url: string,
|
||||
filePath: string,
|
||||
partNumber: number,
|
||||
partSize: number,
|
||||
totalParts: number,
|
||||
onProgress: (bytesSent: number) => void
|
||||
): Promise<string> {
|
||||
const fileSize = statSync(filePath).size;
|
||||
const start = (partNumber - 1) * partSize;
|
||||
const end = partNumber === totalParts ? fileSize : start + partSize;
|
||||
const length = end - start;
|
||||
|
||||
// Read the chunk into a buffer
|
||||
const { openSync, readSync, closeSync } = await import("fs");
|
||||
const fd = openSync(filePath, "r");
|
||||
const buffer = Buffer.alloc(length);
|
||||
readSync(fd, buffer, 0, length, start);
|
||||
closeSync(fd);
|
||||
|
||||
// Stream the upload to track progress
|
||||
const CHUNK_SIZE = 256 * 1024; // 256KB reporting chunks
|
||||
let uploaded = 0;
|
||||
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
let offset = 0;
|
||||
function push() {
|
||||
if (offset >= length) {
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
const chunk = buffer.subarray(offset, Math.min(offset + CHUNK_SIZE, length));
|
||||
controller.enqueue(chunk);
|
||||
offset += chunk.length;
|
||||
uploaded += chunk.length;
|
||||
onProgress(uploaded);
|
||||
}
|
||||
// Push all chunks synchronously since data is already in memory
|
||||
while (offset < length) {
|
||||
const chunk = buffer.subarray(offset, Math.min(offset + CHUNK_SIZE, length));
|
||||
controller.enqueue(chunk);
|
||||
offset += chunk.length;
|
||||
uploaded += chunk.length;
|
||||
onProgress(uploaded);
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": CONTENT_TYPE,
|
||||
"Content-Length": String(length),
|
||||
},
|
||||
body: stream,
|
||||
// @ts-ignore - duplex is needed for streaming uploads in Node
|
||||
duplex: "half",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(`PUT part ${partNumber} failed (${res.status}): ${text}`);
|
||||
}
|
||||
|
||||
const etag = res.headers.get("etag");
|
||||
if (!etag) {
|
||||
throw new Error(`No ETag returned for part ${partNumber}`);
|
||||
}
|
||||
return etag;
|
||||
}
|
||||
|
||||
// ─── UI Component ────────────────────────────────────────────────────────────
|
||||
|
||||
const BAR_WIDTH = 30;
|
||||
|
||||
function ProgressBar({ bytes, totalBytes }: { bytes: number; totalBytes: number }) {
|
||||
const pct = Math.min(100, Math.round((bytes / totalBytes) * 100));
|
||||
const filled = Math.round((bytes / totalBytes) * BAR_WIDTH);
|
||||
const empty = BAR_WIDTH - filled;
|
||||
const uploadedMB = (bytes / (1024 * 1024)).toFixed(1);
|
||||
const totalMB = (totalBytes / (1024 * 1024)).toFixed(1);
|
||||
return (
|
||||
<Box marginLeft={3}>
|
||||
<Text color="cyan">{'█'.repeat(filled)}</Text>
|
||||
<Text color="gray">{'░'.repeat(empty)}</Text>
|
||||
<Text color="gray"> {pct}% ({uploadedMB}/{totalMB} MB)</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function StepLine({ step }: { step: Step }) {
|
||||
const icon =
|
||||
step.status === "pending"
|
||||
? "○"
|
||||
: step.status === "running"
|
||||
? ""
|
||||
: step.status === "done"
|
||||
? "✓"
|
||||
: "✗";
|
||||
|
||||
const color =
|
||||
step.status === "pending"
|
||||
? "gray"
|
||||
: step.status === "running"
|
||||
? "cyan"
|
||||
: step.status === "done"
|
||||
? "green"
|
||||
: "red";
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box>
|
||||
{step.status === "running" ? (
|
||||
<Text color="cyan">
|
||||
<Spinner type="dots" />{" "}
|
||||
</Text>
|
||||
) : (
|
||||
<Text color={color}>{icon} </Text>
|
||||
)}
|
||||
<Text color={color}>{step.label}</Text>
|
||||
{step.detail && <Text color="gray"> — {step.detail}</Text>}
|
||||
</Box>
|
||||
{step.logs && step.logs.length > 0 && !step.progress && (
|
||||
<Box flexDirection="column" marginLeft={3}>
|
||||
{step.logs.map((line, i) => (
|
||||
<Text key={i} color="gray" dimColor>
|
||||
{line}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{step.progress && (
|
||||
<ProgressBar bytes={step.progress.bytes} totalBytes={step.progress.totalBytes} />
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [steps, setSteps] = useState<Step[]>([
|
||||
{ label: "Build Galaxy", status: "pending" },
|
||||
{ label: "Create Galaxy.zip", status: "pending" },
|
||||
{ label: "Authenticate with Hermes", status: "pending" },
|
||||
{ label: "Start multipart upload", status: "pending" },
|
||||
{ label: "Upload parts", status: "pending" },
|
||||
{ label: "Complete upload", status: "pending" },
|
||||
]);
|
||||
|
||||
const updateStep = useCallback((index: number, update: Partial<Step>) => {
|
||||
setSteps((prev) => prev.map((s, i) => (i === index ? { ...s, ...update } : s)));
|
||||
}, []);
|
||||
|
||||
const appendLog = useCallback((index: number, line: string) => {
|
||||
setSteps((prev) =>
|
||||
prev.map((s, i) => {
|
||||
if (i !== index) return s;
|
||||
const logs = [...(s.logs || []), line].slice(-MAX_LOG_LINES);
|
||||
return { ...s, logs };
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
// ─── Step 0: Build ──────────────────────────────────────────────
|
||||
updateStep(0, { status: "running" });
|
||||
await runCommandStreaming(
|
||||
"cargo bundle --bin galaxy-oss --package galaxy",
|
||||
WORKSPACE_ROOT,
|
||||
(line) => appendLog(0, line)
|
||||
);
|
||||
updateStep(0, { status: "done" });
|
||||
|
||||
// ─── Step 1: Zip ────────────────────────────────────────────────
|
||||
updateStep(1, { status: "running" });
|
||||
|
||||
// Find the .app bundle — cargo bundle outputs to target/debug/bundle/osx/
|
||||
const appDir = path.join(
|
||||
WORKSPACE_ROOT,
|
||||
"target/debug/bundle/osx"
|
||||
);
|
||||
const zipPath = path.join(WORKSPACE_ROOT, "Galaxy.zip");
|
||||
|
||||
// Remove old zip if exists
|
||||
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
||||
// Zip the .app folder
|
||||
await runCommandStreaming(
|
||||
`cd "${appDir}" && zip -r -y "${zipPath}" Galaxy.app`,
|
||||
WORKSPACE_ROOT,
|
||||
(line) => appendLog(1, line)
|
||||
);
|
||||
|
||||
const fileSize = statSync(zipPath).size;
|
||||
const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(1);
|
||||
updateStep(1, { status: "done", detail: `${fileSizeMB} MB` });
|
||||
|
||||
// ─── Step 2: Authenticate ───────────────────────────────────────
|
||||
updateStep(2, { status: "running" });
|
||||
|
||||
const loginRes = await apiPost<{ token: string }>(
|
||||
`${BASE_URL}/api/auth/login`,
|
||||
{ username: HERMES_USER, password: HERMES_PASS },
|
||||
COMMON_HEADERS
|
||||
);
|
||||
const token = loginRes.token;
|
||||
appendLog(2, `Authenticated as ${HERMES_USER}`);
|
||||
updateStep(2, { status: "done" });
|
||||
|
||||
// ─── Step 3: Start upload ───────────────────────────────────────
|
||||
updateStep(3, { status: "running" });
|
||||
|
||||
const fileHash = computeFileHash(zipPath);
|
||||
|
||||
const startRes = await apiPost<StartUploadResponse>(
|
||||
`${BASE_URL}/api/uploads/start`,
|
||||
{
|
||||
key: UPLOAD_KEY,
|
||||
contentType: CONTENT_TYPE,
|
||||
fileSize,
|
||||
fileHash,
|
||||
},
|
||||
authHeaders(token)
|
||||
);
|
||||
|
||||
const { uploadId, urls: partUrls, totalParts, partSize } = startRes;
|
||||
appendLog(3, `Upload ID: ${uploadId.slice(0, 32)}...`);
|
||||
appendLog(3, `File hash: ${fileHash}`);
|
||||
appendLog(3, `File size: ${fileSizeMB} MB`);
|
||||
appendLog(3, `Parts: ${totalParts}`);
|
||||
updateStep(3, { status: "done", detail: `${totalParts} parts` });
|
||||
|
||||
// ─── Step 4: Upload parts ───────────────────────────────────────
|
||||
updateStep(4, { status: "running", progress: { bytes: 0, totalBytes: fileSize } });
|
||||
|
||||
// Use the partSize from the server response
|
||||
const completedParts: { partNumber: number; etag: string }[] = [];
|
||||
let totalBytesUploaded = 0;
|
||||
|
||||
for (const part of partUrls) {
|
||||
const prevPartsBytes = totalBytesUploaded;
|
||||
const etag = await uploadPart(
|
||||
part.url,
|
||||
zipPath,
|
||||
part.partNumber,
|
||||
partSize,
|
||||
totalParts,
|
||||
(partBytes) => {
|
||||
updateStep(4, {
|
||||
status: "running",
|
||||
progress: { bytes: prevPartsBytes + partBytes, totalBytes: fileSize },
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Update total bytes for next part's baseline
|
||||
const thisPartSize = part.partNumber === totalParts
|
||||
? fileSize - (partSize * (totalParts - 1))
|
||||
: partSize;
|
||||
totalBytesUploaded += thisPartSize;
|
||||
|
||||
completedParts.push({ partNumber: part.partNumber, etag });
|
||||
|
||||
// Notify server of part completion
|
||||
await apiPost(
|
||||
`${BASE_URL}/api/uploads/part-complete`,
|
||||
{
|
||||
uploadId,
|
||||
partNumber: part.partNumber,
|
||||
etag,
|
||||
},
|
||||
authHeaders(token)
|
||||
);
|
||||
}
|
||||
|
||||
updateStep(4, {
|
||||
status: "done",
|
||||
detail: `${fileSizeMB} MB uploaded`,
|
||||
progress: undefined,
|
||||
});
|
||||
|
||||
// ─── Step 5: Complete ────────────────────────────────────────────
|
||||
updateStep(5, { status: "running" });
|
||||
|
||||
await apiPost(
|
||||
`${BASE_URL}/api/uploads/complete`,
|
||||
{
|
||||
key: UPLOAD_KEY,
|
||||
uploadId,
|
||||
parts: completedParts.sort((a, b) => a.partNumber - b.partNumber),
|
||||
},
|
||||
authHeaders(token)
|
||||
);
|
||||
|
||||
appendLog(5, `Key: ${UPLOAD_KEY}`);
|
||||
updateStep(5, { status: "done" });
|
||||
|
||||
// Cleanup zip
|
||||
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
||||
} catch (err: any) {
|
||||
// Mark current running step as error
|
||||
setSteps((prev) =>
|
||||
prev.map((s) =>
|
||||
s.status === "running"
|
||||
? { ...s, status: "error" as StepStatus, detail: err.message }
|
||||
: s
|
||||
)
|
||||
);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const allDone = steps.every((s) => s.status === "done" || s.status === "error");
|
||||
const hasError = steps.some((s) => s.status === "error");
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" padding={1}>
|
||||
<Box marginBottom={1}>
|
||||
<Text bold color="magenta">
|
||||
🚀 Build & Deploy Galaxy → Hermes
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{steps.map((step, i) => (
|
||||
<StepLine key={i} step={step} />
|
||||
))}
|
||||
|
||||
{allDone && (
|
||||
<Box marginTop={1}>
|
||||
{hasError ? (
|
||||
<Text color="red" bold>
|
||||
✗ Deploy failed.
|
||||
</Text>
|
||||
) : (
|
||||
<Text color="green" bold>
|
||||
✓ Deploy complete!
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
render(<App />);
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@alcalzone/ansi-tokenize@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.1.3.tgz#9f89839561325a8e9a0c32360b8d17e48489993f"
|
||||
integrity sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==
|
||||
dependencies:
|
||||
ansi-styles "^6.2.1"
|
||||
is-fullwidth-code-point "^4.0.0"
|
||||
|
||||
"@esbuild/aix-ppc64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz#7a01a8d2ec2fbb2dac78adad09b0fa781e4082be"
|
||||
integrity sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==
|
||||
|
||||
"@esbuild/android-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz#b540a27d14e4afd058496a4dbec4d3f414db110a"
|
||||
integrity sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==
|
||||
|
||||
"@esbuild/android-arm@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz#704bd297de6d762de54eabbeafbf55f6756abe2f"
|
||||
integrity sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==
|
||||
|
||||
"@esbuild/android-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz#d1cb166d34b0fbf0fe8ab460a5594f24a378701e"
|
||||
integrity sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==
|
||||
|
||||
"@esbuild/darwin-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz#1034b26457fc886368fe61bbd09f653f6afa8e54"
|
||||
integrity sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==
|
||||
|
||||
"@esbuild/darwin-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz#65556a432a1e4d72032d8218c1932fcca1a49772"
|
||||
integrity sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz#2e61e0592f9030d7e3dae18ee25ebc535918aef6"
|
||||
integrity sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==
|
||||
|
||||
"@esbuild/freebsd-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz#c95ec289959ef8079c4dca817a1e2c4be66b9bd3"
|
||||
integrity sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz#40b22175dda06182f3ee8141186c5ff304c4a717"
|
||||
integrity sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==
|
||||
|
||||
"@esbuild/linux-arm@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz#c09a0f67917592ac0de892a9be4d3814debd2a6c"
|
||||
integrity sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==
|
||||
|
||||
"@esbuild/linux-ia32@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz#a580f9c676797833891e519fc7a1337c8afd8db3"
|
||||
integrity sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==
|
||||
|
||||
"@esbuild/linux-loong64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz#46452cf321dc7f9e91c2fa780a56bb56e79cd68b"
|
||||
integrity sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz#4211b3184dd6608f53dcb22e39f5d34ee08852c8"
|
||||
integrity sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz#697857c2a61cb9b0b6bb6652e40c1dc5e1ca8e5d"
|
||||
integrity sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz#d192943eb146a40ac4c6497d0cf7be35b986bf08"
|
||||
integrity sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz#acea0356da0e0ebc08f97cf7b9c2e401e1e648dc"
|
||||
integrity sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==
|
||||
|
||||
"@esbuild/linux-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz#6f0c3ce0cb64c534b70c4c45ecb2c16d34e35dfd"
|
||||
integrity sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz#8bcd77077a0dce3378b574fedb26d2a253b73d36"
|
||||
integrity sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz#e7fb2a01e99c830c94e6623cd9fefb4c8fb58347"
|
||||
integrity sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz#c52909372db8b86e2c55e05a8940033b5660a3b2"
|
||||
integrity sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==
|
||||
|
||||
"@esbuild/openbsd-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz#c427b9be5a64c262ff9a7eb70b5fbbaadf446c6c"
|
||||
integrity sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==
|
||||
|
||||
"@esbuild/openharmony-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz#dc9b147baca2e6c4b3c85571741ef4860a489097"
|
||||
integrity sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==
|
||||
|
||||
"@esbuild/sunos-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz#ce866d12df13c15e4c99f073a3d466f6e0649b3a"
|
||||
integrity sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==
|
||||
|
||||
"@esbuild/win32-arm64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz#7468e3692d01d629d5941e5d83817bb80f9e39b4"
|
||||
integrity sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==
|
||||
|
||||
"@esbuild/win32-ia32@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz#a5bc0063fb2bcab6d0ed63f2a1537958bc269ec6"
|
||||
integrity sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==
|
||||
|
||||
"@esbuild/win32-x64@0.28.1":
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz#10064ee44f4347b90c9a02b446bbf80a91632b12"
|
||||
integrity sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==
|
||||
|
||||
"@types/node@^26.0.0":
|
||||
version "26.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-26.0.0.tgz#d4aece9e9412e9f2008d59bc2d74f5279316b665"
|
||||
integrity sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==
|
||||
dependencies:
|
||||
undici-types "~8.3.0"
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.15.tgz#e6e5a86d602beaca71ce5163fadf5f95d70931c7"
|
||||
integrity sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==
|
||||
|
||||
"@types/react@^18.3.12":
|
||||
version "18.3.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.31.tgz#b5e95e28ffcceab8d982f33f2eb076e17653c2a4"
|
||||
integrity sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^3.2.2"
|
||||
|
||||
ansi-escapes@^7.0.0:
|
||||
version "7.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz#5395bb74b2150a4a1d6e3c2565f4aeca78d28627"
|
||||
integrity sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==
|
||||
dependencies:
|
||||
environment "^1.0.0"
|
||||
|
||||
ansi-regex@^6.2.2:
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1"
|
||||
integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==
|
||||
|
||||
ansi-styles@^6.0.0, ansi-styles@^6.2.1:
|
||||
version "6.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041"
|
||||
integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==
|
||||
|
||||
auto-bind@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-5.0.1.tgz#50d8e63ea5a1dddcb5e5e36451c1a8266ffbb2ae"
|
||||
integrity sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==
|
||||
|
||||
chalk@^5.3.0:
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea"
|
||||
integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==
|
||||
|
||||
cli-boxes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145"
|
||||
integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==
|
||||
|
||||
cli-cursor@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea"
|
||||
integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==
|
||||
dependencies:
|
||||
restore-cursor "^4.0.0"
|
||||
|
||||
cli-spinners@^2.7.0:
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
|
||||
integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
|
||||
|
||||
cli-truncate@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a"
|
||||
integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==
|
||||
dependencies:
|
||||
slice-ansi "^5.0.0"
|
||||
string-width "^7.0.0"
|
||||
|
||||
code-excerpt@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-4.0.0.tgz#2de7d46e98514385cb01f7b3b741320115f4c95e"
|
||||
integrity sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==
|
||||
dependencies:
|
||||
convert-to-spaces "^2.0.1"
|
||||
|
||||
convert-to-spaces@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz#61a6c98f8aa626c16b296b862a91412a33bceb6b"
|
||||
integrity sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==
|
||||
|
||||
csstype@^3.2.2:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a"
|
||||
integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==
|
||||
|
||||
emoji-regex@^10.3.0:
|
||||
version "10.6.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.6.0.tgz#bf3d6e8f7f8fd22a65d9703475bc0147357a6b0d"
|
||||
integrity sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==
|
||||
|
||||
environment@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1"
|
||||
integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==
|
||||
|
||||
es-toolkit@^1.22.0:
|
||||
version "1.48.1"
|
||||
resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.48.1.tgz#4e8a7c3b0fe3a80f4d640934c8552238f25430c7"
|
||||
integrity sha512-wfnXlwd5I75eXRtdD2vuEs50xHHESECDsGD7yiQnfFVNoa5522NwXEbmgo98LfiukSQHs+mBM7/YG3qKJB9/mQ==
|
||||
|
||||
esbuild@~0.28.0:
|
||||
version "0.28.1"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.1.tgz#ef45b4634c9c9d97a296aea4114a5f9840f95578"
|
||||
integrity sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.28.1"
|
||||
"@esbuild/android-arm" "0.28.1"
|
||||
"@esbuild/android-arm64" "0.28.1"
|
||||
"@esbuild/android-x64" "0.28.1"
|
||||
"@esbuild/darwin-arm64" "0.28.1"
|
||||
"@esbuild/darwin-x64" "0.28.1"
|
||||
"@esbuild/freebsd-arm64" "0.28.1"
|
||||
"@esbuild/freebsd-x64" "0.28.1"
|
||||
"@esbuild/linux-arm" "0.28.1"
|
||||
"@esbuild/linux-arm64" "0.28.1"
|
||||
"@esbuild/linux-ia32" "0.28.1"
|
||||
"@esbuild/linux-loong64" "0.28.1"
|
||||
"@esbuild/linux-mips64el" "0.28.1"
|
||||
"@esbuild/linux-ppc64" "0.28.1"
|
||||
"@esbuild/linux-riscv64" "0.28.1"
|
||||
"@esbuild/linux-s390x" "0.28.1"
|
||||
"@esbuild/linux-x64" "0.28.1"
|
||||
"@esbuild/netbsd-arm64" "0.28.1"
|
||||
"@esbuild/netbsd-x64" "0.28.1"
|
||||
"@esbuild/openbsd-arm64" "0.28.1"
|
||||
"@esbuild/openbsd-x64" "0.28.1"
|
||||
"@esbuild/openharmony-arm64" "0.28.1"
|
||||
"@esbuild/sunos-x64" "0.28.1"
|
||||
"@esbuild/win32-arm64" "0.28.1"
|
||||
"@esbuild/win32-ia32" "0.28.1"
|
||||
"@esbuild/win32-x64" "0.28.1"
|
||||
|
||||
escape-string-regexp@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
||||
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
||||
|
||||
fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz#216900f91df11a8b2c198c3e1d93d6c035a776b9"
|
||||
integrity sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==
|
||||
|
||||
indent-string@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5"
|
||||
integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==
|
||||
|
||||
ink-spinner@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ink-spinner/-/ink-spinner-5.0.0.tgz#32ec318ef8ebb0ace8f595451f8e93280623429f"
|
||||
integrity sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA==
|
||||
dependencies:
|
||||
cli-spinners "^2.7.0"
|
||||
|
||||
ink@^5.1.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ink/-/ink-5.2.1.tgz#b9ea59f0d1eab2b4566903b35b54fd34323d1694"
|
||||
integrity sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg==
|
||||
dependencies:
|
||||
"@alcalzone/ansi-tokenize" "^0.1.3"
|
||||
ansi-escapes "^7.0.0"
|
||||
ansi-styles "^6.2.1"
|
||||
auto-bind "^5.0.1"
|
||||
chalk "^5.3.0"
|
||||
cli-boxes "^3.0.0"
|
||||
cli-cursor "^4.0.0"
|
||||
cli-truncate "^4.0.0"
|
||||
code-excerpt "^4.0.0"
|
||||
es-toolkit "^1.22.0"
|
||||
indent-string "^5.0.0"
|
||||
is-in-ci "^1.0.0"
|
||||
patch-console "^2.0.0"
|
||||
react-reconciler "^0.29.0"
|
||||
scheduler "^0.23.0"
|
||||
signal-exit "^3.0.7"
|
||||
slice-ansi "^7.1.0"
|
||||
stack-utils "^2.0.6"
|
||||
string-width "^7.2.0"
|
||||
type-fest "^4.27.0"
|
||||
widest-line "^5.0.0"
|
||||
wrap-ansi "^9.0.0"
|
||||
ws "^8.18.0"
|
||||
yoga-layout "~3.2.1"
|
||||
|
||||
is-fullwidth-code-point@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
|
||||
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
|
||||
|
||||
is-fullwidth-code-point@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz#046b2a6d4f6b156b2233d3207d4b5a9783999b98"
|
||||
integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==
|
||||
dependencies:
|
||||
get-east-asian-width "^1.3.1"
|
||||
|
||||
is-in-ci@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-in-ci/-/is-in-ci-1.0.0.tgz#9a86bbda7e42c6129902e0574c54b018fbb6ab88"
|
||||
integrity sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
onetime@^5.1.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
|
||||
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
patch-console@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/patch-console/-/patch-console-2.0.0.tgz#9023f4665840e66f40e9ce774f904a63167433bb"
|
||||
integrity sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==
|
||||
|
||||
react-reconciler@^0.29.0:
|
||||
version "0.29.2"
|
||||
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.29.2.tgz#8ecfafca63549a4f4f3e4c1e049dd5ad9ac3a54f"
|
||||
integrity sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.2"
|
||||
|
||||
react@^18.3.1:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
|
||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
restore-cursor@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9"
|
||||
integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==
|
||||
dependencies:
|
||||
onetime "^5.1.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
scheduler@^0.23.0, scheduler@^0.23.2:
|
||||
version "0.23.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
|
||||
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
signal-exit@^3.0.2, signal-exit@^3.0.7:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
slice-ansi@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
|
||||
integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
|
||||
dependencies:
|
||||
ansi-styles "^6.0.0"
|
||||
is-fullwidth-code-point "^4.0.0"
|
||||
|
||||
slice-ansi@^7.1.0:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.2.tgz#adf7be70aa6d72162d907cd0e6d5c11f507b5403"
|
||||
integrity sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==
|
||||
dependencies:
|
||||
ansi-styles "^6.2.1"
|
||||
is-fullwidth-code-point "^5.0.0"
|
||||
|
||||
stack-utils@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
|
||||
integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==
|
||||
dependencies:
|
||||
escape-string-regexp "^2.0.0"
|
||||
|
||||
string-width@^7.0.0, string-width@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc"
|
||||
integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==
|
||||
dependencies:
|
||||
emoji-regex "^10.3.0"
|
||||
get-east-asian-width "^1.0.0"
|
||||
strip-ansi "^7.1.0"
|
||||
|
||||
strip-ansi@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3"
|
||||
integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==
|
||||
dependencies:
|
||||
ansi-regex "^6.2.2"
|
||||
|
||||
tsx@^4.19.0:
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.22.4.tgz#0ab3b7fb4ec7feeee74e5b1f26337caa71e44700"
|
||||
integrity sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==
|
||||
dependencies:
|
||||
esbuild "~0.28.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
type-fest@^4.27.0:
|
||||
version "4.41.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58"
|
||||
integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==
|
||||
|
||||
typescript@^5.6.0:
|
||||
version "5.9.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
|
||||
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
|
||||
|
||||
undici-types@~8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-8.3.0.tgz#44e9fc9f3244648cdea35e4f9bb2d681e9410809"
|
||||
integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==
|
||||
|
||||
widest-line@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-5.0.0.tgz#b74826a1e480783345f0cd9061b49753c9da70d0"
|
||||
integrity sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==
|
||||
dependencies:
|
||||
string-width "^7.0.0"
|
||||
|
||||
wrap-ansi@^9.0.0:
|
||||
version "9.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98"
|
||||
integrity sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==
|
||||
dependencies:
|
||||
ansi-styles "^6.2.1"
|
||||
string-width "^7.0.0"
|
||||
strip-ansi "^7.1.0"
|
||||
|
||||
ws@^8.18.0:
|
||||
version "8.21.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.0.tgz#012e413fc07429945121b0c153158c4343086951"
|
||||
integrity sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==
|
||||
|
||||
yoga-layout@~3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/yoga-layout/-/yoga-layout-3.2.1.tgz#d2d1ba06f0e81c2eb650c3e5ad8b0b4adde1e843"
|
||||
integrity sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==
|
||||
+28
-82
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# install-galaxy.sh — Clone, build, and install Galaxy.app on macOS.
|
||||
# install-galaxy.sh — Download, sign, and install Galaxy.app on macOS.
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/install-galaxy.sh | bash
|
||||
@@ -10,99 +10,45 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="git@gitlab.com:samnasbo/shared/galaxy.git"
|
||||
CLONE_DIR="$HOME/.galaxy/source"
|
||||
DOWNLOAD_URL="https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/Galaxy.zip"
|
||||
APP_NAME="Galaxy.app"
|
||||
INSTALL_DIR="/Applications"
|
||||
BUNDLE_BIN="galaxy-oss"
|
||||
BUNDLE_PKG="galaxy"
|
||||
|
||||
# ---------- helpers ----------
|
||||
info() { printf "\033[1;34m==>\033[0m %s\n" "$1"; }
|
||||
warn() { printf "\033[1;33m==> WARNING:\033[0m %s\n" "$1"; }
|
||||
fail() { printf "\033[1;31m==> ERROR:\033[0m %s\n" "$1"; exit 1; }
|
||||
|
||||
# ---------- 1. Xcode / CLI tools ----------
|
||||
info "Checking Xcode and Command Line Tools..."
|
||||
# ---------- 1. Download ----------
|
||||
TMP_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
if ! xcode-select -p &>/dev/null; then
|
||||
fail "Xcode Command Line Tools are not installed. Run: xcode-select --install"
|
||||
info "Downloading Galaxy.zip..."
|
||||
curl -fSL -o "$TMP_DIR/Galaxy.zip" "$DOWNLOAD_URL" || fail "Failed to download Galaxy.zip"
|
||||
|
||||
# ---------- 2. Extract ----------
|
||||
info "Extracting Galaxy.app..."
|
||||
unzip -q "$TMP_DIR/Galaxy.zip" -d "$TMP_DIR" || fail "Failed to extract Galaxy.zip"
|
||||
|
||||
# Remove macOS zip artifacts that cause "unsealed contents" errors during signing
|
||||
rm -rf "$TMP_DIR/__MACOSX"
|
||||
find "$TMP_DIR/$APP_NAME" -name '.DS_Store' -delete 2>/dev/null || true
|
||||
find "$TMP_DIR/$APP_NAME" -name '._*' -delete 2>/dev/null || true
|
||||
# Remove custom Icon file from bundle root (causes "unsealed contents" codesign error)
|
||||
rm -f "$TMP_DIR/$APP_NAME/Icon"$'\r' "$TMP_DIR/$APP_NAME/Icon" 2>/dev/null || true
|
||||
|
||||
if [[ ! -d "$TMP_DIR/$APP_NAME" ]]; then
|
||||
fail "$APP_NAME not found after extraction."
|
||||
fi
|
||||
|
||||
if ! xcrun --show-sdk-path &>/dev/null; then
|
||||
fail "Xcode SDK not found. Ensure Xcode or Command Line Tools are properly installed."
|
||||
fi
|
||||
# ---------- 3. Clear quarantine & ad-hoc sign ----------
|
||||
info "Clearing quarantine attributes..."
|
||||
sudo /usr/bin/xattr -cr "$TMP_DIR/$APP_NAME"
|
||||
|
||||
if ! xcrun -f metal &>/dev/null; then
|
||||
warn "Metal compiler not found. Attempting to download Metal toolchain..."
|
||||
xcodebuild -downloadComponent MetalToolchain || warn "Could not download Metal toolchain — build may fail."
|
||||
fi
|
||||
info "Ad-hoc code signing..."
|
||||
codesign --force --deep --sign - "$TMP_DIR/$APP_NAME" || fail "Code signing failed."
|
||||
|
||||
info "Xcode prerequisites look good."
|
||||
|
||||
# ---------- 2. Homebrew ----------
|
||||
if ! command -v brew &>/dev/null; then
|
||||
info "Installing Homebrew..."
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
# Add brew to PATH for Apple Silicon
|
||||
if [[ -f /opt/homebrew/bin/brew ]]; then
|
||||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v pkgconf &>/dev/null && ! command -v pkg-config &>/dev/null; then
|
||||
info "Installing pkgconf via Homebrew..."
|
||||
brew install pkgconf
|
||||
fi
|
||||
|
||||
# ---------- 3. Rust toolchain ----------
|
||||
if ! command -v rustup &>/dev/null; then
|
||||
info "Installing Rust via rustup..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
info "Syncing Rust toolchain (rust-toolchain.toml will pin the exact version)..."
|
||||
rustup show active-toolchain &>/dev/null || rustup default stable
|
||||
|
||||
# aarch64-apple-darwin target for Apple Silicon
|
||||
rustup target add aarch64-apple-darwin 2>/dev/null || true
|
||||
|
||||
# cargo-bundle for producing the .app
|
||||
if ! cargo bundle --help &>/dev/null 2>&1; then
|
||||
info "Installing cargo-bundle..."
|
||||
cargo install cargo-bundle \
|
||||
--git=https://github.com/burtonageo/cargo-bundle \
|
||||
--rev ae4c76e92c08774bf54ff077b1c52e3d1cd6c16d
|
||||
fi
|
||||
|
||||
# ---------- 4. Clone the repo ----------
|
||||
if [[ -d "$CLONE_DIR/.git" ]]; then
|
||||
info "Repository already exists at $CLONE_DIR — pulling latest..."
|
||||
git -C "$CLONE_DIR" fetch origin
|
||||
git -C "$CLONE_DIR" reset --hard origin/master
|
||||
else
|
||||
info "Cloning Galaxy into $CLONE_DIR..."
|
||||
mkdir -p "$(dirname "$CLONE_DIR")"
|
||||
git clone "$REPO_URL" "$CLONE_DIR"
|
||||
fi
|
||||
|
||||
# ---------- 5. Build ----------
|
||||
info "Fetching dependencies..."
|
||||
pushd "$CLONE_DIR" > /dev/null
|
||||
cargo fetch
|
||||
|
||||
info "Building and bundling $APP_NAME (release)..."
|
||||
cargo bundle --release --bin "$BUNDLE_BIN" --package "$BUNDLE_PKG"
|
||||
popd > /dev/null
|
||||
|
||||
BUILT_APP="$CLONE_DIR/target/release/bundle/osx/$APP_NAME"
|
||||
if [[ ! -d "$BUILT_APP" ]]; then
|
||||
fail "Bundle not found at $BUILT_APP — build may have failed."
|
||||
fi
|
||||
|
||||
# ---------- 6. Kill, remove, install, launch ----------
|
||||
# ---------- 4. Kill, remove, install, launch ----------
|
||||
info "Stopping any running Galaxy processes..."
|
||||
pkill -x "Galaxy" 2>/dev/null && sleep 1 || true
|
||||
pkill -9 -x "Galaxy" 2>/dev/null || true
|
||||
@@ -114,7 +60,7 @@ if [[ -d "$INSTALLED_APP" ]]; then
|
||||
fi
|
||||
|
||||
info "Copying $APP_NAME to $INSTALL_DIR..."
|
||||
cp -R "$BUILT_APP" "$INSTALL_DIR/"
|
||||
cp -R "$TMP_DIR/$APP_NAME" "$INSTALL_DIR/"
|
||||
|
||||
info "Launching Galaxy..."
|
||||
open "$INSTALLED_APP"
|
||||
|
||||
Reference in New Issue
Block a user