107 lines
3.8 KiB
TypeScript
107 lines
3.8 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import { ROOT } from './rootDir';
|
|
|
|
const STORAGE_DIR = path.join( ROOT, 'build', 'data', 'storage' );
|
|
if (!fs.existsSync(STORAGE_DIR)) fs.mkdirSync(STORAGE_DIR, { recursive: true });
|
|
|
|
const INITIAL_HTML = `<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head><meta charset="UTF-8"><title>New Page</title></head>
|
|
<body><page-content><h1>Hello World!</h1></page-content></body>
|
|
</html>`;
|
|
|
|
export interface FileNode {
|
|
name: string;
|
|
path: string;
|
|
type: 'file' | 'directory';
|
|
children?: FileNode[];
|
|
}
|
|
|
|
export function createProjectStorage(projectId: string): void {
|
|
const rootDir = path.join(STORAGE_DIR, projectId, 'root');
|
|
fs.mkdirSync(rootDir, { recursive: true });
|
|
fs.writeFileSync(path.join(rootDir, 'index.html'), INITIAL_HTML);
|
|
}
|
|
|
|
function buildTree(absDir: string, rootDir: string): FileNode[] {
|
|
return fs.readdirSync(absDir).map(name => {
|
|
const abs = path.join(absDir, name);
|
|
const rel = path.relative(rootDir, abs).replace(/\\/g, '/');
|
|
if (fs.statSync(abs).isDirectory()) {
|
|
return { name, path: rel, type: 'directory' as const, children: buildTree(abs, rootDir) };
|
|
}
|
|
return { name, path: rel, type: 'file' as const };
|
|
});
|
|
}
|
|
|
|
export function getFileTree(projectId: string): FileNode[] {
|
|
const rootDir = path.join(STORAGE_DIR, projectId, 'root');
|
|
if (!fs.existsSync(rootDir)) return [];
|
|
return buildTree(rootDir, rootDir);
|
|
}
|
|
|
|
function safeResolve(projectId: string, filePath: string): string | null {
|
|
const rootDir = path.resolve(path.join(STORAGE_DIR, projectId, 'root'));
|
|
const full = path.resolve(path.join(rootDir, filePath));
|
|
if (!full.startsWith(rootDir + path.sep) && full !== rootDir) return null;
|
|
return full;
|
|
}
|
|
|
|
export function readProjectFile(projectId: string, filePath: string): string | null {
|
|
const full = safeResolve(projectId, filePath);
|
|
if (!full || !fs.existsSync(full)) return null;
|
|
return fs.readFileSync(full, 'utf8');
|
|
}
|
|
|
|
export function writeProjectFile(projectId: string, filePath: string, content: string): boolean {
|
|
const full = safeResolve(projectId, filePath);
|
|
if (!full) return false;
|
|
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
fs.writeFileSync(full, content, 'utf8');
|
|
return true;
|
|
}
|
|
|
|
export function createProjectFile(projectId: string, filePath: string): boolean {
|
|
const full = safeResolve(projectId, filePath);
|
|
if (!full || fs.existsSync(full)) return false;
|
|
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
fs.writeFileSync(full, '', 'utf8');
|
|
return true;
|
|
}
|
|
|
|
export function createProjectDirectory(projectId: string, dirPath: string): boolean {
|
|
const full = safeResolve(projectId, dirPath);
|
|
if (!full || fs.existsSync(full)) return false;
|
|
fs.mkdirSync(full, { recursive: true });
|
|
return true;
|
|
}
|
|
|
|
export function projectPathExists(projectId: string, filePath: string): boolean {
|
|
const full = safeResolve(projectId, filePath);
|
|
return !!full && fs.existsSync(full);
|
|
}
|
|
|
|
export function renameProjectEntry( projectId: string, oldPath: string, newName: string ): boolean
|
|
{
|
|
if ( !oldPath || !newName ) return false;
|
|
if ( newName.includes( '/' ) || newName.includes( '\\' ) ) return false;
|
|
const full = safeResolve( projectId, oldPath );
|
|
if ( !full || !fs.existsSync( full ) ) return false;
|
|
const rootDir = path.resolve( path.join( STORAGE_DIR, projectId, 'root' ) );
|
|
const newFull = path.join( path.dirname( full ), newName );
|
|
if ( !newFull.startsWith( rootDir + path.sep ) ) return false;
|
|
if ( fs.existsSync( newFull ) ) return false;
|
|
fs.renameSync( full, newFull );
|
|
return true;
|
|
}
|
|
|
|
export function deleteProjectEntry( projectId: string, targetPath: string ): boolean
|
|
{
|
|
if ( !targetPath ) return false;
|
|
const full = safeResolve( projectId, targetPath );
|
|
if ( !full || !fs.existsSync( full ) ) return false;
|
|
fs.rmSync( full, { recursive: true, force: true } );
|
|
return true;
|
|
}
|