Skip to content

Commit

Permalink
Internal: Unify file system interfaces and replace mkdirp to make-dir (
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Jan 16, 2019
1 parent c406564 commit 5d341dc
Show file tree
Hide file tree
Showing 84 changed files with 250 additions and 284 deletions.
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

0 comments on commit 5d341dc

Please sign in to comment.