|
|
@ -1,41 +1,53 @@ |
|
|
|
import { PluginClient } from "@remixproject/plugin"; |
|
|
|
|
|
|
|
import { createElectronClient } from "./lib/electronPluginClient" |
|
|
|
|
|
|
|
import { Plugin } from '@remixproject/engine'; |
|
|
|
|
|
|
|
import fs from 'fs/promises' |
|
|
|
import fs from 'fs/promises' |
|
|
|
import { Stats } from "fs"; |
|
|
|
import { Stats } from "fs"; |
|
|
|
import { Profile } from "@remixproject/plugin-utils"; |
|
|
|
import { Profile } from "@remixproject/plugin-utils"; |
|
|
|
import chokidar from 'chokidar' |
|
|
|
import chokidar from 'chokidar' |
|
|
|
|
|
|
|
import { ElectronBasePlugin, ElectronBasePluginClient, ElectronBasePluginInterface } from "./lib/electronBasePlugin"; |
|
|
|
|
|
|
|
import { dialog } from 'electron'; |
|
|
|
|
|
|
|
|
|
|
|
const profile: Profile = { |
|
|
|
const profile: Profile = { |
|
|
|
displayName: 'fs', |
|
|
|
displayName: 'fs', |
|
|
|
name: 'fs', |
|
|
|
name: 'fs', |
|
|
|
description: 'fs', |
|
|
|
description: 'fs' |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export class FSPlugin extends Plugin { |
|
|
|
export class FSPlugin extends ElectronBasePlugin { |
|
|
|
client: FSPluginClient |
|
|
|
clients: FSPluginClient[] = [] |
|
|
|
constructor() { |
|
|
|
constructor() { |
|
|
|
super(profile) |
|
|
|
super(profile) |
|
|
|
this.methods = ['closeWatch'] |
|
|
|
this.methods = [...super.methods, 'closeWatch'] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async createClient(webContentsId: number): Promise<void> { |
|
|
|
|
|
|
|
this.clients.push(new FSPluginClient(webContentsId)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onActivation(): void { |
|
|
|
async closeClient(webContentsId: number): Promise<void> { |
|
|
|
this.client = new FSPluginClient() |
|
|
|
console.log('closeClient', webContentsId) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async closeWatch(): Promise<void> { |
|
|
|
async closeWatch(): Promise<void> { |
|
|
|
console.log('closeWatch')
|
|
|
|
for (const client of this.clients) { |
|
|
|
await this.client.closeWatch()
|
|
|
|
await client.closeWatch() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class FSPluginClient extends PluginClient { |
|
|
|
const clientProfile: Profile = { |
|
|
|
|
|
|
|
name: 'fs', |
|
|
|
|
|
|
|
displayName: 'fs', |
|
|
|
|
|
|
|
description: 'fs', |
|
|
|
|
|
|
|
methods: ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'exists', 'currentPath', 'watch', 'closeWatch', 'setWorkingDir'] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FSPluginClient extends ElectronBasePluginClient { |
|
|
|
watcher: chokidar.FSWatcher |
|
|
|
watcher: chokidar.FSWatcher |
|
|
|
constructor() { |
|
|
|
workingDir: string = '/Volumes/bunsen/code/rmproject2/remix-project/apps/remix-ide/contracts/' |
|
|
|
super() |
|
|
|
|
|
|
|
this.methods = ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'exists', 'watch', 'closeWatch', 'currentPath'] |
|
|
|
constructor(webContentsId: number) {
|
|
|
|
createElectronClient(this, profile) |
|
|
|
super(webContentsId, clientProfile) |
|
|
|
this.onload(() => { |
|
|
|
this.onload(() => { |
|
|
|
console.log('fsPluginClient onload') |
|
|
|
console.log('fsPluginClient onload') |
|
|
|
}) |
|
|
|
}) |
|
|
@ -43,39 +55,39 @@ class FSPluginClient extends PluginClient { |
|
|
|
|
|
|
|
|
|
|
|
async readdir(path: string): Promise<string[]> { |
|
|
|
async readdir(path: string): Promise<string[]> { |
|
|
|
// call node fs.readdir
|
|
|
|
// call node fs.readdir
|
|
|
|
return fs.readdir(path) |
|
|
|
return fs.readdir(this.fixPath(path)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async readFile(path: string): Promise<string> { |
|
|
|
async readFile(path: string): Promise<string> { |
|
|
|
return fs.readFile(path, 'utf8') |
|
|
|
return fs.readFile(this.fixPath(path), 'utf8') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async writeFile(path: string, content: string): Promise<void> { |
|
|
|
async writeFile(path: string, content: string): Promise<void> { |
|
|
|
return fs.writeFile(path, content, 'utf8') |
|
|
|
return fs.writeFile(this.fixPath(path), content, 'utf8') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async mkdir(path: string): Promise<void> { |
|
|
|
async mkdir(path: string): Promise<void> { |
|
|
|
return fs.mkdir(path) |
|
|
|
return fs.mkdir(this.fixPath(path)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async rmdir(path: string): Promise<void> { |
|
|
|
async rmdir(path: string): Promise<void> { |
|
|
|
return fs.rmdir(path) |
|
|
|
return fs.rmdir(this.fixPath(path)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async unlink(path: string): Promise<void> { |
|
|
|
async unlink(path: string): Promise<void> { |
|
|
|
return fs.unlink(path) |
|
|
|
return fs.unlink(this.fixPath(path)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async rename(oldPath: string, newPath: string): Promise<void> { |
|
|
|
async rename(oldPath: string, newPath: string): Promise<void> { |
|
|
|
return fs.rename(oldPath, newPath) |
|
|
|
return fs.rename(this.fixPath(oldPath), this.fixPath(newPath)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async stat(path: string): Promise<Stats> { |
|
|
|
async stat(path: string): Promise<Stats> { |
|
|
|
return fs.stat(path) |
|
|
|
return fs.stat(this.fixPath(path)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async exists(path: string): Promise<boolean> { |
|
|
|
async exists(path: string): Promise<boolean> { |
|
|
|
return fs.access(path).then(() => true).catch(() => false) |
|
|
|
return fs.access(this.fixPath(path)).then(() => true).catch(() => false) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async currentPath(): Promise<string> { |
|
|
|
async currentPath(): Promise<string> { |
|
|
@ -83,19 +95,37 @@ class FSPluginClient extends PluginClient { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async watch(path: string): Promise<void> { |
|
|
|
async watch(path: string): Promise<void> { |
|
|
|
console.log('watch', path) |
|
|
|
|
|
|
|
if (this.watcher) this.watcher.close() |
|
|
|
if (this.watcher) this.watcher.close() |
|
|
|
this.watcher = |
|
|
|
this.watcher = |
|
|
|
chokidar.watch(path).on('change', (path, stats) => { |
|
|
|
chokidar.watch(this.fixPath(path)).on('change', (path, stats) => { |
|
|
|
console.log('change', path, stats) |
|
|
|
console.log('change', path, stats) |
|
|
|
this.emit('change', path, stats) |
|
|
|
this.emit('change', path, stats) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async closeWatch(): Promise<void> { |
|
|
|
async closeWatch(): Promise<void> { |
|
|
|
console.log('closeWatch') |
|
|
|
console.log('closing Watcher', this.webContentsId) |
|
|
|
if (this.watcher) this.watcher.close() |
|
|
|
if (this.watcher) this.watcher.close() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async setWorkingDir(): Promise<void> { |
|
|
|
|
|
|
|
const dirs = dialog.showOpenDialogSync(this.window, { |
|
|
|
|
|
|
|
properties: ['openDirectory'] |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
if (dirs && dirs.length > 0) |
|
|
|
|
|
|
|
this.workingDir = dirs[0] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.emit('workingDirChanged', dirs[0]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fixPath(path: string): string { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (path.startsWith('/')) { |
|
|
|
|
|
|
|
path = path.slice(1) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
path = this.workingDir + path |
|
|
|
|
|
|
|
return path |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |