Skip to content

Commit 9d83697

Browse files
Fix: Detect downloaded scripts from all directories (ct, tools, vm, vw) (#120)
* Fix: Detect downloaded scripts from all directories (ct, tools, vm, vw) - Add getAllDownloadedScripts() method to scan all script directories - Update DownloadedScriptsTab to use new API endpoint - Update ScriptsGrid to use new API endpoint for download status detection - Update main page script counts to use new API endpoint - Add recursive directory scanning to handle subdirectories - Maintain backward compatibility with existing getCtScripts endpoint Fixes issue where scripts downloaded to tools/, vm/, or vw/ directories were not showing in Downloaded Scripts tab or showing correct download status in Available Scripts tab. * Fix: Remove redundant type annotation and method call arguments - Remove redundant string type annotation from relativePath parameter - Fix getScriptsFromDirectory method call to match updated signature
1 parent c12c96c commit 9d83697

File tree

5 files changed

+102
-3
lines changed

5 files changed

+102
-3
lines changed

src/app/_components/DownloadedScriptsTab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function DownloadedScriptsTab({ onInstallScript }: DownloadedScriptsTabPr
3737
const gridRef = useRef<HTMLDivElement>(null);
3838

3939
const { data: scriptCardsData, isLoading: githubLoading, error: githubError, refetch } = api.scripts.getScriptCardsWithCategories.useQuery();
40-
const { data: localScriptsData, isLoading: localLoading, error: localError } = api.scripts.getCtScripts.useQuery();
40+
const { data: localScriptsData, isLoading: localLoading, error: localError } = api.scripts.getAllDownloadedScripts.useQuery();
4141
const { data: scriptData } = api.scripts.getScriptBySlug.useQuery(
4242
{ slug: selectedSlug ?? '' },
4343
{ enabled: !!selectedSlug }

src/app/_components/ScriptsGrid.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function ScriptsGrid({ onInstallScript }: ScriptsGridProps) {
3434
const gridRef = useRef<HTMLDivElement>(null);
3535

3636
const { data: scriptCardsData, isLoading: githubLoading, error: githubError, refetch } = api.scripts.getScriptCardsWithCategories.useQuery();
37-
const { data: localScriptsData, isLoading: localLoading, error: localError } = api.scripts.getCtScripts.useQuery();
37+
const { data: localScriptsData, isLoading: localLoading, error: localError } = api.scripts.getAllDownloadedScripts.useQuery();
3838
const { data: scriptData } = api.scripts.getScriptBySlug.useQuery(
3939
{ slug: selectedSlug ?? '' },
4040
{ enabled: !!selectedSlug }

src/app/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default function Home() {
2121

2222
// Fetch data for script counts
2323
const { data: scriptCardsData } = api.scripts.getScriptCardsWithCategories.useQuery();
24-
const { data: localScriptsData } = api.scripts.getCtScripts.useQuery();
24+
const { data: localScriptsData } = api.scripts.getAllDownloadedScripts.useQuery();
2525
const { data: installedScriptsData } = api.installedScripts.getAllInstalledScripts.useQuery();
2626

2727
// Calculate script counts

src/server/api/routers/scripts.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ export const scriptsRouter = createTRPCRouter({
2727
};
2828
}),
2929

30+
// Get all downloaded scripts from all directories
31+
getAllDownloadedScripts: publicProcedure
32+
.query(async () => {
33+
const scripts = await scriptManager.getAllDownloadedScripts();
34+
return {
35+
scripts,
36+
directoryInfo: scriptManager.getScriptsDirectoryInfo()
37+
};
38+
}),
39+
3040

3141
// Get script content for viewing
3242
getScriptContent: publicProcedure

src/server/lib/scripts.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,95 @@ export class ScriptManager {
141141
}
142142
}
143143

144+
/**
145+
* Get all downloaded scripts from all directories (ct, tools, vm, vw)
146+
*/
147+
async getAllDownloadedScripts(): Promise<ScriptInfo[]> {
148+
this.initializeConfig();
149+
const allScripts: ScriptInfo[] = [];
150+
151+
// Define all script directories to scan
152+
const scriptDirs = ['ct', 'tools', 'vm', 'vw'];
153+
154+
for (const dirName of scriptDirs) {
155+
try {
156+
const dirPath = join(this.scriptsDir!, dirName);
157+
158+
// Check if directory exists
159+
try {
160+
await stat(dirPath);
161+
} catch {
162+
// Directory doesn't exist, skip it
163+
continue;
164+
}
165+
166+
const scripts = await this.getScriptsFromDirectory(dirPath);
167+
allScripts.push(...scripts);
168+
} catch (error) {
169+
console.error(`Error reading ${dirName} scripts directory:`, error);
170+
// Continue with other directories even if one fails
171+
}
172+
}
173+
174+
return allScripts.sort((a, b) => a.name.localeCompare(b.name));
175+
}
176+
177+
/**
178+
* Get scripts from a specific directory (recursively)
179+
*/
180+
private async getScriptsFromDirectory(dirPath: string): Promise<ScriptInfo[]> {
181+
const scripts: ScriptInfo[] = [];
182+
183+
const scanDirectory = async (currentPath: string, relativePath = ''): Promise<void> => {
184+
const files = await readdir(currentPath);
185+
186+
for (const file of files) {
187+
const filePath = join(currentPath, file);
188+
const stats = await stat(filePath);
189+
190+
if (stats.isFile()) {
191+
const extension = extname(file);
192+
193+
// Check if file extension is allowed
194+
if (this.allowedExtensions!.includes(extension)) {
195+
// Check if file is executable
196+
const executable = await this.isExecutable(filePath);
197+
198+
// Extract slug from filename (remove .sh extension)
199+
const slug = file.replace(/\.sh$/, '');
200+
201+
// Try to get logo from JSON data
202+
let logo: string | undefined;
203+
try {
204+
const scriptData = await localScriptsService.getScriptBySlug(slug);
205+
logo = scriptData?.logo ?? undefined;
206+
} catch {
207+
// JSON file might not exist, that's okay
208+
}
209+
210+
scripts.push({
211+
name: file,
212+
path: filePath,
213+
extension,
214+
size: stats.size,
215+
lastModified: stats.mtime,
216+
executable,
217+
logo,
218+
slug
219+
});
220+
}
221+
} else if (stats.isDirectory()) {
222+
// Recursively scan subdirectories
223+
const subRelativePath = relativePath ? join(relativePath, file) : file;
224+
await scanDirectory(filePath, subRelativePath);
225+
}
226+
}
227+
};
228+
229+
await scanDirectory(dirPath);
230+
return scripts;
231+
}
232+
144233
/**
145234
* Check if a file is executable
146235
*/

0 commit comments

Comments
 (0)