diff --git a/package-lock.json b/package-lock.json index 54085b1..b0185ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2755,6 +2755,11 @@ } } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -3924,6 +3929,14 @@ "readable-stream": "^2.3.6" } }, + "folder-encrypt": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/folder-encrypt/-/folder-encrypt-1.1.7.tgz", + "integrity": "sha512-mLJdPrrjo49w2ysRTje9jqWRmqqUwd/2dHFqpEEKl22bn7vK70/gWCAXszy7QmUUcmF1ICpQPzHlhaxVghfE+Q==", + "requires": { + "tar-fs": "^2.0.0" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3951,6 +3964,11 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-extra": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", @@ -5813,6 +5831,11 @@ "minimist": "^1.2.5" } }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "module-alias": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", @@ -7873,6 +7896,52 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "terminal-paginator": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/terminal-paginator/-/terminal-paginator-2.0.2.tgz", diff --git a/package.json b/package.json index 847daeb..5819074 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "dotenv": "^8.2.0", "eventemitter2": "^6.4.4", "filendir": "^2.0.1", + "folder-encrypt": "^1.1.7", "gulp": "^4.0.2", "ignore": "^5.1.8", "inquirer": "^8.2.0", diff --git a/src/app/devsync/compute/Uploader.ts b/src/app/devsync/compute/Uploader.ts index 4a38271..259c0f2 100644 --- a/src/app/devsync/compute/Uploader.ts +++ b/src/app/devsync/compute/Uploader.ts @@ -546,7 +546,12 @@ export default class Uploader { // debug: true }); this.client.on('close', () => { - this.connect(callback); + setTimeout(()=>{ + if(this.client == null){ + return; + } + this.connect(callback); + },1000); }) callback(null, 'Connected'); } catch (ex) { @@ -573,6 +578,7 @@ export default class Uploader { _exeHandlePush: Function = null; clientClose(): void { this.client.end(); + this.client = null; } async _executeCommand(whatCommand: string, callback?: Function) { try { @@ -654,6 +660,12 @@ export default class Uploader { debounceClose(); } return (entry: any, first_time_out: number) => { + + if(this.client == null){ + this._pendingQueue = {}; + return; + } + this._orders[entry.queue_no] = Object.create({ ...entry, queue_no: entry.queue_no @@ -689,6 +701,10 @@ export default class Uploader { var fileName = entry.fileName; var action = entry.action; + if(this.client == null){ + return; + } + switch (action) { case 'add_change': /* Check the size of file first */ diff --git a/src/app/devsync/services/DevSyncService.ts b/src/app/devsync/services/DevSyncService.ts index d16efde..7281385 100644 --- a/src/app/devsync/services/DevSyncService.ts +++ b/src/app/devsync/services/DevSyncService.ts @@ -624,6 +624,7 @@ const DevSyncService = BaseService.extend({ this.watcher = null; /* Restart the syncronize */ + this.uploader.clientClose(); this.uploader.onListener('RESTART', {}); this.uploader = null; @@ -634,7 +635,7 @@ const DevSyncService = BaseService.extend({ setTimeout(() => { this.construct(this._cli); - }, 3000); + }, 1000); } var closeRemote = () => { if (this._currentConf.devsync.script.remote.on_stop != "" && this._currentConf.devsync.script.remote.on_stop != null) { diff --git a/src/app/devsync2/compute/HttpEvent.ts b/src/app/devsync2/compute/HttpEvent.ts index a83b939..27f46d5 100644 --- a/src/app/devsync2/compute/HttpEvent.ts +++ b/src/app/devsync2/compute/HttpEvent.ts @@ -12,7 +12,7 @@ import { CliInterface } from "../services/CliService"; var size = require('window-size'); import os from 'os'; import { ConfigInterface } from "./Config"; -import { fstatSync, readFileSync, Stats, statSync, writeFileSync } from "fs"; +import { existsSync, fstatSync, readFileSync, Stats, statSync, writeFileSync } from "fs"; import parseGitIgnore from '@root/tool/parse-gitignore' import ignore from 'ignore' import { uniq } from "lodash"; @@ -336,7 +336,7 @@ const HttpEvent = BaseModel.extend>({ try { // await this._client.delete(remoteFilePath); await this._client.mkdir(path.dirname(remoteFilePath)); - } catch (ex) { + } catch (ex) { console.log(ex); } try { @@ -371,14 +371,19 @@ const HttpEvent = BaseModel.extend>({ generateSSHConfig() { let _direct_access: DirectAccessType = this._config.direct_access as any; let _configFilePath = upath.normalizeSafe(os.homedir() + '/.ssh/config'); - + let _privateKey = null; + if (existsSync(upath.normalize(process.cwd() + "/" + this._config.privateKey)) == true) { + _privateKey = upath.normalize(process.cwd() + "/" + this._config.privateKey); + } else { + _privateKey = this._config.privateKey + } /* Persisten ssh_config */ let ssh_confi = { Host: "temp_reverse_port_ssh", HostName: this._config.host, User: this._config.username, Port: this._config.port, - IdentityFile: this._config.privateKey, + IdentityFile: _privateKey, RequestTTY: "force", StrictHostKeyChecking: "no" } diff --git a/src/app/devsync2/compute/Uploader.ts b/src/app/devsync2/compute/Uploader.ts index 5aa9bf3..71e3b51 100644 --- a/src/app/devsync2/compute/Uploader.ts +++ b/src/app/devsync2/compute/Uploader.ts @@ -32,6 +32,12 @@ export class Uploader extends DevSyncUploader { debounceClose(); } return (entry: any, first_time_out: number) => { + + if (this.client == null) { + this._pendingQueue = {}; + return; + } + this._orders[entry.queue_no] = Object.create({ ...entry, queue_no: entry.queue_no @@ -39,9 +45,15 @@ export class Uploader extends DevSyncUploader { if (this._pendingUpload[entry.path] != null) { this._pendingUpload[entry.path].cancel(); } + /* Mengikuti kelipatan concurent */ let _debouncePendingOut = first_time_out == null ? (100 * (entry.queue_no == 0 ? 1 : entry.queue_no + 1)) : first_time_out; this._pendingUpload[entry.path] = debounce(async (entry: any) => { + + if (this.client == null) { + return; + } + let deleteQueueFunc = () => { this._pendingUpload[entry.path] = null; delete this._pendingUpload[entry.path]; diff --git a/src/app/devsync2/services/DevSync2Service.ts b/src/app/devsync2/services/DevSync2Service.ts index 5279cd3..f0edc79 100644 --- a/src/app/devsync2/services/DevSync2Service.ts +++ b/src/app/devsync2/services/DevSync2Service.ts @@ -736,6 +736,7 @@ const DevRsyncService = BaseService.extend({ /* Restart the syncronize */ if (this.uploader != null) { + this.uploader.clientClose(); this.uploader.onListener('RESTART', {}); this.uploader = null; } @@ -746,7 +747,7 @@ const DevRsyncService = BaseService.extend({ process.stdout.write(chalk.green('Remote | ') + 'Restarting...' + '\r'); setTimeout(() => { this.construct(this._cli); - }, 3000); + }, 1000); } var closeRemote = () => { if (this._currentConf.devsync.script.remote.on_stop != "" && this._currentConf.devsync.script.remote.on_stop != null) { diff --git a/src/app/load_save/services/LoadSaveDataService.ts b/src/app/load_save/services/LoadSaveDataService.ts index 8657afa..b5dc812 100644 --- a/src/app/load_save/services/LoadSaveDataService.ts +++ b/src/app/load_save/services/LoadSaveDataService.ts @@ -1,5 +1,5 @@ import BaseService from "@root/base/BaseService"; -import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync, writeFileSync } from "fs"; +import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "fs"; import inquirer from 'inquirer'; import path from "path"; import upath from 'upath'; @@ -9,6 +9,7 @@ import Config, { ConfigInterface } from "../compute/Config"; import YAML from 'yaml'; import readdirp from "readdirp"; import filendir from 'filendir'; +import * as folderEncrypt from 'folder-encrypt'; export interface LoadSaveServiceInterface extends BaseServiceInterface { _completeData: { @@ -47,21 +48,28 @@ export default BaseService.extend({ return existsSync(path); }, construct: function (cli, action) { - this._config = this.returnConfig(cli); - /* Display project folder base path */ - if (this._existConfig(this._config._filename) == false) { - process.exit(); - } + try { + this._config = this.returnConfig(cli); + /* Display project folder base path */ + if (this._existConfig(this._config._filename) == false) { + process.exit(); + } - this._sync_collection_src = this._config.sync_collection.src; - let test: any = existsSync(upath.normalizeSafe(this._sync_collection_src)); - if (test == false) { - mkdirSync(upath.normalizeSafe(this._sync_collection_src)); - } - if (action == "auto_save") { - return this.autoSave(); + this._sync_collection_src = this._config.sync_collection.src; + let test: any = existsSync(upath.normalizeSafe(this._sync_collection_src)); + + if (test == false) { + mkdirSync(upath.normalizeSafe(this._sync_collection_src)); + } + if (action == "auto_save") { + return this.autoSave(); + } + this.defaultPrompt(); + } catch (ex) { + console.clear(); + console.log(ex); + process.exit(0); } - this.defaultPrompt(); }, defaultPrompt() { let questions: inquirer.QuestionCollection = [ @@ -146,9 +154,14 @@ export default BaseService.extend({ }, }, { - type: 'default', - name: "Enter again " + String.fromCodePoint(0x00002386) + type: "password", + name: "fill_password", + message: "Put the password :", }, + // { + // type: 'default', + // name: "Enter again " + String.fromCodePoint(0x00002386) + // }, ]; this._promptAction("", questions); }, @@ -174,7 +187,12 @@ export default BaseService.extend({ name: "new_sync_name", message: "New File Name :", when: (answers: any) => answers.target_save === "New file" - } + }, + { + type: "password", + name: "fill_password", + message: "Put the password :", + }, ]; this._promptAction("", questions); }, @@ -240,7 +258,7 @@ export default BaseService.extend({ }, createUpdateNewSave: async function () { try { - let { new_sync_name, target_save } = this._completeData; + let { new_sync_name, target_save, fill_password } = this._completeData; let whatSyncName = target_save; if (new_sync_name != null) { whatSyncName = new_sync_name; @@ -251,6 +269,22 @@ export default BaseService.extend({ bodyData = YAML.parse(bodyData.toString()) as any; bodyData.sync_config_name = whatSyncName; + let _existFilesSrc = await readdirp.promise(upath.normalize(`${this._sync_collection_src}/${whatSyncName}`), { + type: "all", + depth: 0, // One level + }); + + // Keep cleaning first + for (var a = 0; a < _existFilesSrc.length; a++) { + if (lstatSync(_existFilesSrc[a].fullPath).isDirectory() == true) { + rmdirSync(_existFilesSrc[a].fullPath, { + recursive: true + }) + } else if (lstatSync(_existFilesSrc[a].fullPath).isFile() == true) { + rmSync(_existFilesSrc[a].fullPath); + } + } + filendir.writeFileSync(upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/sync-config.yaml'), YAML.stringify(bodyData, null), 'utf8'); /* Add sync_ignore can self by owner ngi-sync */ if (existsSync(".sync_ignore")) { @@ -281,22 +315,79 @@ export default BaseService.extend({ if (statSync(_sync_collection_files[a]) != null) { let _file_resolve = path.resolve("", _sync_collection_files[a]); let _readFile = readFileSync(_file_resolve); - writeFileSync(upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/' + _sync_collection_files[a]), _readFile, "utf8"); + let _filePath = upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/' + _sync_collection_files[a]); + writeFileSync(_filePath, _readFile, "utf8"); } break; } console.log(`${upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/' + _sync_collection_files[a])} is created!`); } + + let _filesReadDirSrcEnc = await readdirp.promise(upath.normalize(`${this._sync_collection_src}/${whatSyncName}`), { + type: "all", + depth: 0 + }); + for (var a = 0; a < _filesReadDirSrcEnc.length; a++) { + await folderEncrypt.encrypt({ + password: fill_password, + input: _filesReadDirSrcEnc[a].fullPath, + output: _filesReadDirSrcEnc[a].fullPath + "_encrypto" // optional, default will be input path with extension `encrypted` + }) + if (existsSync(_filesReadDirSrcEnc[a].fullPath) == true) { + if (lstatSync(_filesReadDirSrcEnc[a].fullPath).isDirectory() == true) { + rmdirSync(_filesReadDirSrcEnc[a].fullPath, { + recursive: true + }) + } else if (lstatSync(_filesReadDirSrcEnc[a].fullPath).isFile() == true) { + rmSync(_filesReadDirSrcEnc[a].fullPath); + } + } + } + } catch (ex) { console.error('createNewSave - ex ', ex); } }, loadDataSave: async function () { try { - let { target_load } = this._completeData; + let { target_load, fill_password } = this._completeData; let whatSyncName = target_load; let _config = this._config; - let bodyData: any = readFileSync(upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/sync-config.yaml')); + + // Descript first + let _filesReadDirSrcEnc = await readdirp.promise(upath.normalize(`${this._sync_collection_src}/${whatSyncName}`), { + type: "all", + depth: 0, // One level + }); + + // Keep cleaning first + for (var a = 0; a < _filesReadDirSrcEnc.length; a++) { + if (_filesReadDirSrcEnc[a].fullPath.includes("_encrypto")) { + + } else { + if (lstatSync(_filesReadDirSrcEnc[a].fullPath).isDirectory() == true) { + rmdirSync(_filesReadDirSrcEnc[a].fullPath, { + recursive: true + }) + } else if (lstatSync(_filesReadDirSrcEnc[a].fullPath).isFile() == true) { + rmSync(_filesReadDirSrcEnc[a].fullPath); + } + } + } + + // Create again + for (var a = 0; a < _filesReadDirSrcEnc.length; a++) { + if (_filesReadDirSrcEnc[a].fullPath.includes("_encrypto")) { + await folderEncrypt.decrypt({ + password: fill_password, + input: _filesReadDirSrcEnc[a].fullPath, + output: _filesReadDirSrcEnc[a].fullPath.replace("_encrypto", ""), + }) + } + } + + let fileSyncConfigPath = upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/sync-config.yaml'); + let bodyData: any = readFileSync(fileSyncConfigPath); bodyData = YAML.parse(bodyData.toString()) as any; bodyData.sync_config_name = whatSyncName; bodyData.sync_collection.src = this._sync_collection_src; @@ -307,26 +398,31 @@ export default BaseService.extend({ writeFileSync(".sync_ignore", syncIgnoreData, 'utf8'); } + // console.log(`${this._sync_collection_src + '/' + whatSyncName + '/sync-config.yaml'} is created!`); // console.log(`${this._sync_collection_src + '/' + whatSyncName + '/.sync_ignore'} is created!`); let _filesReadDirSrc = await readdirp.promise(upath.normalize(`${this._sync_collection_src}/${whatSyncName}`), { - type: "all" + type: "all", }); for (var a = 0; a < _filesReadDirSrc.length; a++) { // console.log("_filesReadDirSrc :: ", _filesReadDirSrc[a]); - switch (_filesReadDirSrc[a].basename) { - case 'sync-config.yaml': - case '.sync_ignore': - break; - default: - if (lstatSync(_filesReadDirSrc[a].fullPath).isFile() == true) { - // console.log('_filesReadDirSrc :: ', _filesReadDirSrc[a]); - let _readFile = readFileSync(upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/' + _filesReadDirSrc[a].path)); - filendir.writeFileSync(upath.normalize(path.resolve("", _filesReadDirSrc[a].path)), _readFile, "utf8"); - console.log(`${upath.normalize(path.resolve("", _filesReadDirSrc[a].path))} is loaded!`); - } - break; + if (_filesReadDirSrc[a].basename.includes("_encrypto")) { + + } else { + switch (_filesReadDirSrc[a].basename) { + case 'sync-config.yaml': + case '.sync_ignore': + break; + default: + if (lstatSync(_filesReadDirSrc[a].fullPath).isFile() == true) { + // console.log('_filesReadDirSrc :: ', _filesReadDirSrc[a]); + let _readFile = readFileSync(upath.normalize(this._sync_collection_src + '/' + whatSyncName + '/' + _filesReadDirSrc[a].path)); + filendir.writeFileSync(upath.normalize(path.resolve("", _filesReadDirSrc[a].path)), _readFile, "utf8"); + console.log(`${upath.normalize(path.resolve("", _filesReadDirSrc[a].path))} is loaded!`); + } + break; + } } } } catch (ex) {