fix: derive script path for PocketBase-sourced scripts on install (#522)

PocketBase API records do not include a `script` field in
`install_methods_json` (only local JSON scripts do). Since v0.5.7
migrated to PocketBase as the data source, `handleExecuteScript` in
ScriptDetailModal was silently doing nothing — it checked for
`method.script` which is always absent for PocketBase scripts, so
`onInstallScript` was never called and the terminal never opened.

Fix by adding a `deriveScriptPath()` helper (mirroring the logic
already in `scriptDownloader.js`) and using it as a fallback when
`method.script` is absent. Also forward `script` through `pbToScript`
and add it to `PBInstallMethod` for forward compatibility.

Fixes #520
This commit is contained in:
mojotaker
2026-03-29 02:49:36 -05:00
committed by GitHub
parent 5eaffcb9ff
commit 4da8840d78
3 changed files with 22 additions and 5 deletions

View File

@@ -19,6 +19,21 @@ import {
import { Button } from "./ui/button"; import { Button } from "./ui/button";
import { useRegisterModal } from "./modal/ModalStackProvider"; import { useRegisterModal } from "./modal/ModalStackProvider";
function deriveScriptPath(scriptType: string, methodType: string, slug: string): string {
const type = (scriptType || "ct").toLowerCase().trim();
const method = (methodType || "default").toLowerCase().trim();
if (method === "alpine" && (type === "ct" || type === "lxc")) return `ct/alpine-${slug}.sh`;
switch (type) {
case "ct":
case "lxc": return `ct/${slug}.sh`;
case "pve": return `tools/pve/${slug}.sh`;
case "addon": return `tools/addon/${slug}.sh`;
case "vm": return `vm/${slug}.sh`;
case "turnkey": return `turnkey/${slug}.sh`;
default: return `ct/${slug}.sh`;
}
}
interface ScriptDetailModalProps { interface ScriptDetailModalProps {
script: Script | null; script: Script | null;
isOpen: boolean; isOpen: boolean;
@@ -190,12 +205,12 @@ export function ScriptDetailModal({
// Find the script path based on selected version type // Find the script path based on selected version type
const versionType = selectedVersionType ?? "default"; const versionType = selectedVersionType ?? "default";
const scriptMethod = const scriptMethod =
script.install_methods?.find( script.install_methods?.find((method) => method.type === versionType) ??
(method) => method.type === versionType && method.script, script.install_methods?.[0];
) ?? script.install_methods?.find((method) => method.script);
if (scriptMethod?.script) { if (scriptMethod) {
const scriptPath = `scripts/${scriptMethod.script}`; const scriptFile = scriptMethod.script ?? deriveScriptPath(script.type, scriptMethod.type, script.slug);
const scriptPath = `scripts/${scriptFile}`;
const scriptName = script.name; const scriptName = script.name;
// Pass execution mode, server info, and envVars to the parent // Pass execution mode, server info, and envVars to the parent

View File

@@ -38,6 +38,7 @@ function pbToScript(pb: PBScript): Script {
description: pb.description, description: pb.description,
install_methods: pb.install_methods_json.map((m) => ({ install_methods: pb.install_methods_json.map((m) => ({
type: m.type, type: m.type,
script: m.script,
resources: m.resources, resources: m.resources,
config_path: m.config_path, config_path: m.config_path,
})), })),

View File

@@ -24,6 +24,7 @@ export interface PBScriptType {
export interface PBInstallMethod { export interface PBInstallMethod {
type: string; // "default", "alpine", etc. type: string; // "default", "alpine", etc.
script?: string; // e.g. "ct/adguard.sh" present in local JSON scripts, absent in PocketBase records
resources: { resources: {
cpu: number; cpu: number;
ram: number; ram: number;