Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal: Unify file system interfaces and replace mkdirp to make-dir #1867

Merged
merged 9 commits into from
Jan 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
"keytar": "^4.3.0",
"load-json-file": "^5.1.0",
"luxon": "^1.9.0",
"mkdirp": "^0.5.1",
"make-dir": "^1.3.0",
"monaco-editor": "^0.15.6",
"mousetrap": "^1.6.2",
"node-forge": "^0.7.6",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Injectable } from "@angular/core";
@Injectable({providedIn: "root"})
export class ClipboardService {
private _clipboard: Electron.Clipboard;

constructor() {
this._clipboard = require("electron").clipboard;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Injectable, OnDestroy } from "@angular/core";
import { autobind } from "@batch-flask/core";
import { ElectronRemote } from "@batch-flask/electron";
import { BrowserWindow } from "electron";
import { BehaviorSubject, Observable } from "rxjs";
import { ElectronRemote } from "../remote.service";

@Injectable({providedIn: "root"})
@Injectable()
export class CurrentBrowserWindow implements OnDestroy {
/**
* Observable that emit if the window is in full screen mode
Expand Down
22 changes: 22 additions & 0 deletions src/@batch-flask/electron/electron-app.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Injectable } from "@angular/core";

@Injectable({ providedIn: "root" })
export class ElectronApp {
public _app: import("electron").App;
public require: (module: string) => any;

constructor() {
if (process && process.type === "renderer") {
this._app = require("electron").remote.app;
this.require = require("electron").remote.require;
} else {
this._app = require("electron").app;
this.require = require;
}

}

public getPath(name: string): string {
return this._app.getPath(name);
}
}
4 changes: 4 additions & 0 deletions src/@batch-flask/electron/electron-main.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { NgModule } from "@angular/core";
import { AUTO_UPDATE_MAIN_SERVICE_TOKEN, AutoUpdateService } from "./auto-update";
import { AutoUpdateMainService } from "./auto-update/auto-update-main.service";
import { FileSystemService } from "./fs.service";
import { OSService } from "./os.service";

@NgModule({
imports: [],
providers: [
{ provide: AutoUpdateService, useClass: AutoUpdateMainService },
{ provide: AUTO_UPDATE_MAIN_SERVICE_TOKEN, useExisting: AutoUpdateService },
FileSystemService,
OSService,
],
})
export class ElectronMainModule {
Expand Down
6 changes: 6 additions & 0 deletions src/@batch-flask/electron/electron-renderer.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { NgModule } from "@angular/core";
import { AutoUpdateRendererService, AutoUpdateService } from "./auto-update";
import { CurrentBrowserWindow } from "./current-browser-window";
import { FileSystemService } from "./fs.service";
import { IpcService } from "./ipc.service";
import { OSService } from "./os.service";
import { ElectronRemote } from "./remote.service";
import { SharedServiceInjector } from "./shared-service-injector";
import { ElectronShell } from "./shell.service";
Expand All @@ -16,6 +19,9 @@ import { ElectronShell } from "./shell.service";
ElectronShell,
ElectronRemote,
IpcService,
FileSystemService,
OSService,
CurrentBrowserWindow,
],
})
export class ElectronRendererModule {
Expand Down
123 changes: 68 additions & 55 deletions src/client/core/fs.ts → src/@batch-flask/electron/fs.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { Injectable } from "@angular/core";
import { log } from "@batch-flask/utils";
import * as chokidar from "chokidar";
import { FileUtils } from "client/api";
import { app } from "electron";
import { FSWatcher } from "chokidar";
import * as fs from "fs";
import * as glob from "glob";
import * as mkdirp from "mkdirp";
import * as path from "path";
import { ElectronApp } from "./electron-app.service";

export interface CommonFolders {
temp: string;
Expand All @@ -16,47 +13,54 @@ export interface CommonFolders {
home: string;
}

/**
* Service to handle saving files to the client FileSystem
*/
@Injectable()
export class FileSystem {
public commonFolders: CommonFolders;
private _fileUtils: FileUtils;

constructor() {
this._fileUtils = new FileUtils();
if (process.env.NODE_ENV !== "test") { // App is not defined in the test
this.commonFolders = {
temp: path.join(app.getPath("temp"), "batch-explorer"),
downloads: app.getPath("downloads"),
appData: app.getPath("appData"),
userData: app.getPath("userData"),
home: app.getPath("home"),
};
}
export class FileSystemService {
public commonFolders: any;
private _fs: typeof import("fs");
private _makeDir: typeof import("make-dir");
private _glob: typeof import("glob");
private _chokidar: typeof import("chokidar");
private _download: typeof import("download");
private _extractZip: typeof import("extract-zip");

constructor(app: ElectronApp) {
this._fs = app.require("fs");
this._makeDir = app.require("make-dir");
this._glob = app.require("glob");
this._chokidar = app.require("chokidar");
this._download = app.require("download");
this._extractZip = app.require("extract-zip");

this.commonFolders = {
temp: path.join(app.getPath("temp"), "batch-explorer"),
downloads: app.getPath("downloads"),
appData: app.getPath("appData"),
userData: app.getPath("userData"),
home: app.getPath("home"),
};
}

/**
* Check if a file exists async
* @param path Full path to the file
*/
public exists(path: string): Promise<boolean> {
public async exists(path: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
fs.exists(path, (exists) => {
this._fs.exists(path, (exists) => {
resolve(exists);
});
});
}

/**
* This make sure the given dir exists. Will recusrivelly create any missing directory.
* @param directory: Path that we expect to exist
* @param directory: Path that we expect to exists
*/
public ensureDir(directory: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
mkdirp(directory, (err) => {
if (err) { reject(err); }
resolve();
});
});
return this._makeDir(directory);
}

/**
Expand All @@ -82,10 +86,30 @@ export class FileSystem {
});
}

public download(source: string, dest: string): Promise<string> {
return this.ensureDir(path.dirname(dest)).then(() => {
return this._fileUtils.download(source, dest);
public async readdir(dir: string, recursive = true): Promise<string[]> {
const content = await this._readDir(dir);
if (!recursive) { return content; }
let result: string[] = [];
for (const entry of content) {
const stats = await this.lstat(path.join(dir, entry));
if (stats.isFile()) {
result.push(entry);
} else {
const subFiles = await this.readdir(path.join(dir, entry), true);
result = result.concat(subFiles.map((x) => {
return path.join(path.join(entry, x));
}));
}
}
return result;
}

public async download(source: string, dest: string): Promise<string> {
await this.ensureDir(path.dirname(dest));
await this._download(source, path.dirname(dest), {
filename: path.basename(dest),
});
return dest;
}

/**
Expand All @@ -94,7 +118,14 @@ export class FileSystem {
* @param dest Folder where the zip file should be extracted
*/
public unzip(source: string, dest: string): Promise<void> {
return this._fileUtils.unzip(source, dest);
return new Promise((resolve, reject) => {
this._extractZip(source, { dir: dest }, (err) => {
if (err) {
return reject(err);
}
resolve();
});
});
}

public async lstat(path: string): Promise<fs.Stats> {
Expand All @@ -119,37 +150,19 @@ export class FileSystem {
});
}

public async readdir(dir: string, recursive = true): Promise<string[]> {
const content = await this._readDir(dir);
if (!recursive) { return content; }
let result: string[] = [];
for (const entry of content) {
const stats = await this.lstat(path.join(dir, entry));
if (stats.isFile()) {
result.push(entry);
} else {
const subFiles = await this.readdir(path.join(dir, entry), true);
result = result.concat(subFiles.map((x) => {
return path.join(path.join(entry, x));
}));
}
}
return result;
public watch(path: string): FSWatcher {
return this._chokidar.watch(path);
}

public async glob(pattern: string): Promise<string[]> {
public glob(pattern: string): Promise<string[]> {
return new Promise<string[]>((resolve, reject) => {
glob(pattern, (err, files) => {
this._glob(pattern, (err, files) => {
if (err) { reject(err); return; }
resolve(files);
});
});
}

public watch(path: string): chokidar.FSWatcher {
return chokidar.watch(path);
}

private _writeFile(path: string, content: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
fs.writeFile(path, content, (err) => {
Expand Down
10 changes: 7 additions & 3 deletions src/@batch-flask/electron/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export * from "./auto-update";
export * from "./clipboard.service";
export * from "./current-browser-window";
export * from "./electron-app.service";
export * from "./electron-renderer.module";
export * from "./fs.service";
export * from "./ipc.service";
export * from "./os.service";
export * from "./remote.service";
export * from "./shell.service";
export * from "./ipc.service";
// export * from "./electron-main.module";
export * from "./electron-renderer.module";
13 changes: 10 additions & 3 deletions src/@batch-flask/electron/ipc.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Injectable } from "@angular/core";
import { Injectable, OnDestroy } from "@angular/core";
import { Subscription } from "rxjs";

/**
* Internal events used by the ipc promise utility to be able to use promise
Expand All @@ -16,18 +17,24 @@ export const IpcPromiseEvent = {
* Wrapper around electron ipcRenderer
*/
@Injectable({providedIn: "root"})
export class IpcService {
export class IpcService implements OnDestroy {
private _ipcRenderer: Electron.IpcRenderer;
constructor() {
this._ipcRenderer = require("electron").ipcRenderer;
}

public ngOnDestroy() {
// Nothing
}

public async sendEvent(eventName: string, data?: any) {
this._ipcRenderer.send(eventName, data);
}

public async on(eventName: string, callback: (...args) => void) {
public on(eventName: string, callback: (...args) => void): Subscription {
this._ipcRenderer.on(eventName, callback);

return new Subscription(() => this._ipcRenderer.removeListener(eventName, callback));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from "@angular/core";
import { OS, Platform } from "@batch-flask/utils";

@Injectable({providedIn: "root"})
@Injectable()
export class OSService {
public platform: Platform;

Expand Down
2 changes: 1 addition & 1 deletion src/@batch-flask/electron/remote.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { IpcService } from "./ipc.service";
* Injectable service wrapping electron shell.
* This makes it easier to mock the electron shell.
*/
@Injectable({providedIn: "root"})
@Injectable()
export class ElectronRemote {
// tslint:disable-next-line:variable-name
public Menu: typeof Electron.Menu;
Expand Down
2 changes: 1 addition & 1 deletion src/@batch-flask/ui/activity/activity-fifo-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class ActivityFifoQueue {

private _dequeue() {
if (this.fifoQueue.length === 0) { return; }
this._run(this.fifoQueue.shift());
this._run(this.fifoQueue.shift()!);
}

private _run(activity: Activity) {
Expand Down
2 changes: 0 additions & 2 deletions src/@batch-flask/ui/batchui.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { DialogsModule } from "./dialogs";
import { DropdownModule } from "./dropdown";
import { DurationPickerModule } from "./duration-picker";
import { EditorModule } from "./editor";
import { ElectronModule } from "./electron";
import { EntityCommandsListModule } from "./entity-commands-list";
import { FileModule } from "./file";
import { FocusSectionModule } from "./focus-section";
Expand Down Expand Up @@ -96,7 +95,6 @@ const modules = [
SummaryCardModule,
VirtualScrollModule,
VTabsModule,
ElectronModule,
WorkspaceModule,
DatetimePickerModule,
];
Expand Down
25 changes: 0 additions & 25 deletions src/@batch-flask/ui/electron/electron.module.ts

This file was deleted.

Loading