+16
-2
@@ -1,5 +1,5 @@
|
||||
import { readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
||||
import { join, relative, sep } from 'node:path'
|
||||
import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
||||
import { dirname, join, relative, sep } from 'node:path'
|
||||
import { listFiles } from './search-service'
|
||||
|
||||
export interface FileNode {
|
||||
@@ -120,6 +120,20 @@ export async function writeProjectFile(root: string, rel: string, content: strin
|
||||
await writeFile(join(root, rel), content, 'utf8')
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new, empty text file (relative path). Creates parent folders as
|
||||
* needed, refuses to escape the project root, and throws if the file already
|
||||
* exists so an accidental name collision never clobbers existing content.
|
||||
*/
|
||||
export async function createProjectFile(root: string, rel: string): Promise<void> {
|
||||
const target = join(root, rel)
|
||||
if (relative(root, target).startsWith('..')) throw new Error('outside project root')
|
||||
const existing = await stat(target).catch(() => null)
|
||||
if (existing) throw new Error('file already exists')
|
||||
await mkdir(dirname(target), { recursive: true })
|
||||
await writeFile(target, '', { encoding: 'utf8', flag: 'wx' })
|
||||
}
|
||||
|
||||
/** Delete a project file or folder (relative path). Stays inside the project root. */
|
||||
export async function deleteProjectFile(root: string, rel: string): Promise<void> {
|
||||
const target = join(root, rel)
|
||||
|
||||
+2
-1
@@ -4,7 +4,7 @@ import { spawn } from 'node:child_process'
|
||||
import { app, dialog, shell, BrowserWindow, ipcMain, Menu } from 'electron'
|
||||
import { watch, type FSWatcher } from 'chokidar'
|
||||
import { addRecentProject, getName, getRecentProjects, getRoot, openDialog, setRoot } from './project'
|
||||
import { deleteProjectFile, readAll, readProjectFile, readTree, writeProjectFile } from './fs-service'
|
||||
import { createProjectFile, deleteProjectFile, readAll, readProjectFile, readTree, writeProjectFile } from './fs-service'
|
||||
import { commit, discard, load, stage, unstage } from './git-service'
|
||||
import { createPty, killAllPtys, killPty, ptyAvailable, resizePty, writePty } from './pty-service'
|
||||
import { getConfig, getRecent, getThemeCss, resolveConfig, setRecent } from './config'
|
||||
@@ -206,6 +206,7 @@ function registerIpc(): void {
|
||||
ipcMain.handle('fs:read', (_e, rel: string) => { const r = getRoot(); return r ? readProjectFile(r, rel) : '' })
|
||||
ipcMain.handle('fs:write', (_e, rel: string, content: string) => { const r = getRoot(); if (r) return writeProjectFile(r, rel, content) })
|
||||
ipcMain.handle('fs:delete', (_e, rel: string) => { const r = getRoot(); if (r) return deleteProjectFile(r, rel) })
|
||||
ipcMain.handle('fs:create', (_e, rel: string) => { const r = getRoot(); if (r) return createProjectFile(r, rel) })
|
||||
ipcMain.handle('shell:reveal', (_e, rel: string) => { const r = getRoot(); if (r) shell.showItemInFolder(join(r, rel)) })
|
||||
|
||||
ipcMain.handle('git:load', () => { const r = getRoot(); return r ? load(r) : null })
|
||||
|
||||
Reference in New Issue
Block a user