gdrive-syncer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/Readme.md +36 -0
- package/gdrive.config.json +16 -0
- package/index.js +13 -0
- package/package.json +34 -0
- package/run.js +101 -0
- package/src/cfgManager.js +92 -0
- package/src/config.js +22 -0
- package/src/helpers.js +141 -0
- package/src/list.js +149 -0
- package/src/login.js +21 -0
- package/src/sync.js +84 -0
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
12.14.1
|
package/Readme.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Google Drive Syncer
|
|
2
|
+
> A command line tool to manage sync folders with google drive
|
|
3
|
+
|
|
4
|
+
### Prerequsites
|
|
5
|
+
|
|
6
|
+
Install and setup [gdrive-sync](https://github.com/DrauzJu/gdrive-sync)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Installation
|
|
10
|
+
```
|
|
11
|
+
$ npm i -g gdrive-syncer
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Usage
|
|
15
|
+
```
|
|
16
|
+
$ gdrive-syncer <command_name>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Available commands
|
|
20
|
+
```
|
|
21
|
+
---- Drive ----
|
|
22
|
+
login
|
|
23
|
+
---- Operations----
|
|
24
|
+
search
|
|
25
|
+
list
|
|
26
|
+
mkdir
|
|
27
|
+
delete
|
|
28
|
+
---- Sync ---
|
|
29
|
+
diff
|
|
30
|
+
upload
|
|
31
|
+
listSync
|
|
32
|
+
---- Config ----
|
|
33
|
+
cfgAdd
|
|
34
|
+
cfgRm
|
|
35
|
+
cfgShow
|
|
36
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"syncs": [
|
|
3
|
+
{
|
|
4
|
+
"localpath": "project_envs/php-sayhey",
|
|
5
|
+
"driveId": "1jN1oOZKETwQL4FyoEoCCLlqBwLmYJLRd"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"localpath": "project_envs/sayhey",
|
|
9
|
+
"driveId": "1movI2Vgu2OMFRUl_aWvJqeQ65c_LZJG8"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"localpath": "project_envs/pipeline-test",
|
|
13
|
+
"driveId": "19rP3yIsLNQ2V4ViahgGyK-BJu60W6rEp"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gdrive-syncer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Google Drive Syncer",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"bin": "./run.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"No test specified\""
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"Google",
|
|
12
|
+
"Drive",
|
|
13
|
+
"Sync"
|
|
14
|
+
],
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Surya Chandra",
|
|
17
|
+
"email": "intuitionist.coder@gmail.com"
|
|
18
|
+
},
|
|
19
|
+
"license": "ISC",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"ansi-colors": "^4.1.1",
|
|
22
|
+
"cli-progress": "^3.10.0",
|
|
23
|
+
"fs-extra": "^10.0.0",
|
|
24
|
+
"inquirer": "^8.2.0",
|
|
25
|
+
"inquirer-file-tree-selection-prompt": "^1.0.15",
|
|
26
|
+
"minimist": "^1.2.5",
|
|
27
|
+
"shelljs": "^0.8.5"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {},
|
|
30
|
+
"np": {
|
|
31
|
+
"yarn": false,
|
|
32
|
+
"2fa": false
|
|
33
|
+
}
|
|
34
|
+
}
|
package/run.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const { runLogin } = require('./src/login');
|
|
5
|
+
const { cfgAdd, cfgRm, cfgShow } = require('./src/cfgManager');
|
|
6
|
+
const { runSync } = require('./src/sync');
|
|
7
|
+
const { runList, runSearch, runDelete, runMkdir, runListSync } = require('./src/list');
|
|
8
|
+
|
|
9
|
+
const [, , ...args] = process.argv;
|
|
10
|
+
const [firstArg] = args;
|
|
11
|
+
|
|
12
|
+
(async () => {
|
|
13
|
+
try {
|
|
14
|
+
const choices = [
|
|
15
|
+
'login',
|
|
16
|
+
'search',
|
|
17
|
+
'list',
|
|
18
|
+
'mkdir',
|
|
19
|
+
'delete',
|
|
20
|
+
'cfgAdd',
|
|
21
|
+
'cfgRm',
|
|
22
|
+
'cfgShow',
|
|
23
|
+
'listSync',
|
|
24
|
+
'diff',
|
|
25
|
+
'upload',
|
|
26
|
+
];
|
|
27
|
+
let choice = choices.find((c) => c === firstArg);
|
|
28
|
+
|
|
29
|
+
if (!choice) {
|
|
30
|
+
if (firstArg) {
|
|
31
|
+
console.log('No matching command for', firstArg);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const answers = await inquirer.prompt([
|
|
35
|
+
{
|
|
36
|
+
name: 'type',
|
|
37
|
+
type: 'list',
|
|
38
|
+
loop: false,
|
|
39
|
+
pageSize: 20,
|
|
40
|
+
message: 'What would you like to do?',
|
|
41
|
+
choices: [
|
|
42
|
+
new inquirer.Separator('---- Drive ----'),
|
|
43
|
+
'login',
|
|
44
|
+
new inquirer.Separator('---- Operations ----'),
|
|
45
|
+
'search',
|
|
46
|
+
'list',
|
|
47
|
+
'mkdir',
|
|
48
|
+
'delete',
|
|
49
|
+
new inquirer.Separator('---- Sync ----'),
|
|
50
|
+
'diff',
|
|
51
|
+
'upload',
|
|
52
|
+
'listSync',
|
|
53
|
+
new inquirer.Separator('---- Config ----'),
|
|
54
|
+
'cfgShow',
|
|
55
|
+
'cfgAdd',
|
|
56
|
+
'cfgRm',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
]);
|
|
60
|
+
choice = answers.type;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
switch (choice) {
|
|
64
|
+
case 'login':
|
|
65
|
+
await runLogin();
|
|
66
|
+
break;
|
|
67
|
+
case 'search':
|
|
68
|
+
await runSearch();
|
|
69
|
+
break;
|
|
70
|
+
case 'list':
|
|
71
|
+
await runList();
|
|
72
|
+
break;
|
|
73
|
+
case 'mkdir':
|
|
74
|
+
await runMkdir();
|
|
75
|
+
break;
|
|
76
|
+
case 'delete':
|
|
77
|
+
await runDelete();
|
|
78
|
+
break;
|
|
79
|
+
case 'diff':
|
|
80
|
+
await runSync(true);
|
|
81
|
+
break;
|
|
82
|
+
case 'upload':
|
|
83
|
+
await runSync(false);
|
|
84
|
+
break;
|
|
85
|
+
case 'listSync':
|
|
86
|
+
await runListSync();
|
|
87
|
+
break;
|
|
88
|
+
case 'cfgShow':
|
|
89
|
+
await cfgShow();
|
|
90
|
+
break;
|
|
91
|
+
case 'cfgAdd':
|
|
92
|
+
await cfgAdd();
|
|
93
|
+
break;
|
|
94
|
+
case 'cfgRm':
|
|
95
|
+
await cfgRm();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.error(e.message);
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const { addSyncCfg, fileSelector, removeSyncCfg, getCfgFile } = require('./helpers');
|
|
5
|
+
|
|
6
|
+
const cfgAdd = async () => {
|
|
7
|
+
console.log('Running cfgAdd');
|
|
8
|
+
try {
|
|
9
|
+
const { fullpath } = await fileSelector('Select local folder to sync to gdrive\n');
|
|
10
|
+
|
|
11
|
+
const answers = await inquirer.prompt([
|
|
12
|
+
/* Pass your questions in here */
|
|
13
|
+
{
|
|
14
|
+
type: 'input',
|
|
15
|
+
name: 'driveId',
|
|
16
|
+
message: 'Enter the DRIVE FILEID of the folder to sync with',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: 'input',
|
|
20
|
+
name: 'name',
|
|
21
|
+
message: 'Set a unique name for the new sync config',
|
|
22
|
+
default: path.basename(fullpath),
|
|
23
|
+
},
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const driveId = (answers.driveId || '').trim();
|
|
27
|
+
const name = (answers.name || '').trim();
|
|
28
|
+
if (!driveId || !name) {
|
|
29
|
+
throw new Error('Invalid Input!');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log(`Adding sync config for ${fullpath} ---> ${driveId}`);
|
|
33
|
+
|
|
34
|
+
addSyncCfg({
|
|
35
|
+
name,
|
|
36
|
+
fullpath: fullpath,
|
|
37
|
+
driveId,
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error(e.message);
|
|
41
|
+
} finally {
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const cfgRm = async () => {
|
|
46
|
+
console.log('Running cfgRm');
|
|
47
|
+
try {
|
|
48
|
+
// const { fullpath } = await fileSelector('Select local folder to sync to gdrive\n');
|
|
49
|
+
|
|
50
|
+
const { syncs } = getCfgFile();
|
|
51
|
+
const sep = ' || ';
|
|
52
|
+
const answers = await inquirer.prompt([
|
|
53
|
+
/* Pass your questions in here */
|
|
54
|
+
{
|
|
55
|
+
type: 'list',
|
|
56
|
+
name: 'pick',
|
|
57
|
+
message: 'Pick the sync cfg to delete',
|
|
58
|
+
choices: syncs.map((c) => c.name + sep + c.driveId + sep + c.fullpath),
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
const name = (answers.pick || '').split(sep)[0].trim();
|
|
63
|
+
|
|
64
|
+
console.log(`Removing sync config ...`);
|
|
65
|
+
|
|
66
|
+
removeSyncCfg({
|
|
67
|
+
name,
|
|
68
|
+
});
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error(e.message);
|
|
71
|
+
} finally {
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const cfgShow = async () => {
|
|
76
|
+
console.log('Running cfgShow');
|
|
77
|
+
try {
|
|
78
|
+
// const { fullpath } = await fileSelector('Select local folder to sync to gdrive\n');
|
|
79
|
+
|
|
80
|
+
const cfg = getCfgFile();
|
|
81
|
+
console.log(cfg);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.error(e.message);
|
|
84
|
+
} finally {
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
cfgAdd,
|
|
90
|
+
cfgRm,
|
|
91
|
+
cfgShow,
|
|
92
|
+
};
|
package/src/config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// import os module
|
|
2
|
+
const os = require('os');
|
|
3
|
+
|
|
4
|
+
// check the available memory
|
|
5
|
+
const userHomeDir = os.homedir();
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const rootFolderPath = path.join(__dirname, '..');
|
|
8
|
+
const names = {
|
|
9
|
+
cfgFolder: '.gdrive_syncer',
|
|
10
|
+
cfgFile: 'gdrive.config.json',
|
|
11
|
+
};
|
|
12
|
+
const createCfgFolger = path.join(userHomeDir, names.cfgFolder);
|
|
13
|
+
|
|
14
|
+
const paths = {
|
|
15
|
+
cfgFile: path.join(createCfgFolger, names.cfgFile),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
rootFolderPath,
|
|
20
|
+
paths,
|
|
21
|
+
names,
|
|
22
|
+
};
|
package/src/helpers.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const { paths } = require('./config');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const prettyJson = (jsonString) => JSON.stringify(JSON.parse(jsonString), null, 2);
|
|
7
|
+
const prettyPrintJson = (jsonString) => console.log(prettyJson(jsonString));
|
|
8
|
+
const delay = (ms) => {
|
|
9
|
+
return new Promise((resolve) =>
|
|
10
|
+
setTimeout(() => {
|
|
11
|
+
resolve(0);
|
|
12
|
+
}, ms)
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
function capitalizeFirstLetter(string) {
|
|
16
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getCfgFile() {
|
|
20
|
+
const cfgPath = paths.cfgFile;
|
|
21
|
+
createEmptyCfgFile();
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(cfgPath)) {
|
|
24
|
+
throw new Error('No cfg config file detected');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const imp = fs.readFileSync(cfgPath, { encoding: 'utf-8' });
|
|
28
|
+
const syncsCfg = JSON.parse(imp);
|
|
29
|
+
|
|
30
|
+
return syncsCfg;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function addSyncCfg({ driveId, fullpath, name }) {
|
|
34
|
+
// const syncObject = { driveId, fullpath, name };
|
|
35
|
+
createEmptyCfgFile();
|
|
36
|
+
if (!driveId || !fullpath || !name) {
|
|
37
|
+
throw new Error('Missing sync file details');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const syncsCfg = getCfgFile();
|
|
41
|
+
const found = syncsCfg.syncs.find(
|
|
42
|
+
(c) => c.fullpath === fullpath || c.name === name || c.driveId === driveId
|
|
43
|
+
);
|
|
44
|
+
if (found) {
|
|
45
|
+
throw new Error('Existing Sync found!! ' + JSON.stringify(found, null, 2));
|
|
46
|
+
}
|
|
47
|
+
syncsCfg.syncs.push({
|
|
48
|
+
fullpath,
|
|
49
|
+
name,
|
|
50
|
+
driveId,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
saveCfgFile(syncsCfg);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function removeSyncCfg({ name }) {
|
|
57
|
+
// const syncObject = { driveId, fullpath, name };
|
|
58
|
+
if (!name) {
|
|
59
|
+
throw new Error('Missing sync file details');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const syncsCfg = getCfgFile();
|
|
63
|
+
const foundIndex = syncsCfg.syncs.find((c) => c.name === name);
|
|
64
|
+
if (foundIndex === -1) {
|
|
65
|
+
throw new Error('No Existing Sync found!! ');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
syncsCfg.syncs.splice(foundIndex, 1);
|
|
69
|
+
saveCfgFile(syncsCfg);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createEmptyCfgFile() {
|
|
73
|
+
if (!fs.existsSync(paths.cfgFile)) {
|
|
74
|
+
saveCfgFile({ syncs: [] });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const saveCfgFile = (syncsJson) => {
|
|
79
|
+
if (!syncsJson) {
|
|
80
|
+
throw new Error('No Syncs Config');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fs.outputFileSync(paths.cfgFile, `${JSON.stringify(syncsJson, null, 2)}`);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Select local folder to sync to gdrive\n
|
|
87
|
+
const fileSelector = async (message) => {
|
|
88
|
+
inquirer.registerPrompt('file-tree-selection', require('inquirer-file-tree-selection-prompt'));
|
|
89
|
+
|
|
90
|
+
const basepath = path.join(process.cwd());
|
|
91
|
+
const answers = await inquirer.prompt([
|
|
92
|
+
/* Pass your questions in here */
|
|
93
|
+
{
|
|
94
|
+
type: 'file-tree-selection',
|
|
95
|
+
name: 'fullpath',
|
|
96
|
+
message: `\n\n\x1b[45m\x1b[33m ${message}\x1b[0m`,
|
|
97
|
+
root: basepath,
|
|
98
|
+
onlyShowDir: true,
|
|
99
|
+
loop: false,
|
|
100
|
+
// validate: (item) => {
|
|
101
|
+
// const name = item.split(path.sep).pop();
|
|
102
|
+
// if (name[0] != '.') {
|
|
103
|
+
// return 'please select another file in the format ".env.{0|1|2}.{env_name}"';
|
|
104
|
+
// }
|
|
105
|
+
// try {
|
|
106
|
+
// getEnvFileNameParams(name);
|
|
107
|
+
// } catch (e) {
|
|
108
|
+
// return 'please select another file in the format ".env.{0|1|2}.{env_name}"';
|
|
109
|
+
// }
|
|
110
|
+
|
|
111
|
+
// // try {
|
|
112
|
+
// // getInfoJsonParams(item);
|
|
113
|
+
// // } catch (e) {
|
|
114
|
+
// // return e.message || 'Error info.json';
|
|
115
|
+
// // }
|
|
116
|
+
// return true;
|
|
117
|
+
// },
|
|
118
|
+
onlyShowValid: true,
|
|
119
|
+
},
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
const fullpath = answers.fullpath;
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
basepath,
|
|
126
|
+
fullpath,
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
module.exports = {
|
|
131
|
+
prettyJson,
|
|
132
|
+
delay,
|
|
133
|
+
prettyPrintJson,
|
|
134
|
+
capitalizeFirstLetter,
|
|
135
|
+
getCfgFile,
|
|
136
|
+
saveCfgFile,
|
|
137
|
+
createEmptyCfgFile,
|
|
138
|
+
addSyncCfg,
|
|
139
|
+
removeSyncCfg,
|
|
140
|
+
fileSelector,
|
|
141
|
+
};
|
package/src/list.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const shell = require('shelljs');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
|
|
5
|
+
const runSearch = async () => {
|
|
6
|
+
console.log('Running Search');
|
|
7
|
+
try {
|
|
8
|
+
const answers = await inquirer.prompt([
|
|
9
|
+
/* Pass your questions in here */
|
|
10
|
+
{
|
|
11
|
+
type: 'input',
|
|
12
|
+
name: 'search',
|
|
13
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
14
|
+
message: 'Enter the folder/file name to search in drive',
|
|
15
|
+
default: 'bitbucket-env-manager',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: 'number',
|
|
19
|
+
name: 'max',
|
|
20
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
21
|
+
message: 'maxResults',
|
|
22
|
+
default: 100,
|
|
23
|
+
},
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const search = (answers.search || '').trim();
|
|
27
|
+
const max = answers.max || 100;
|
|
28
|
+
if (!search) {
|
|
29
|
+
throw new Error('Invalid Input!');
|
|
30
|
+
}
|
|
31
|
+
shell.exec(`gdrive list --max ${max} --query "name contains '${search}'" --absolute`);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error(e.message);
|
|
34
|
+
} finally {
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const runList = async () => {
|
|
39
|
+
console.log('Running List');
|
|
40
|
+
try {
|
|
41
|
+
const answers = await inquirer.prompt([
|
|
42
|
+
/* Pass your questions in here */
|
|
43
|
+
{
|
|
44
|
+
type: 'input',
|
|
45
|
+
name: 'driveId',
|
|
46
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
47
|
+
message: 'Enter the drive fileId to view files/folder inside',
|
|
48
|
+
validate: (item) => !!item,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: 'number',
|
|
52
|
+
name: 'max',
|
|
53
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
54
|
+
message: 'maxResults',
|
|
55
|
+
default: 100,
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
const driveId = (answers.driveId || '').trim();
|
|
60
|
+
const max = answers.max || 100;
|
|
61
|
+
if (!driveId) {
|
|
62
|
+
throw new Error('Invalid Input!');
|
|
63
|
+
}
|
|
64
|
+
shell.exec(`gdrive list --max ${max} --query "parents in '${driveId}'" --absolute`);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error(e.message);
|
|
67
|
+
} finally {
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const runListSync = async () => {
|
|
72
|
+
console.log('Running runListSync');
|
|
73
|
+
try {
|
|
74
|
+
shell.exec(`gdrive sync list`);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.error(e.message);
|
|
77
|
+
} finally {
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const runMkdir = async () => {
|
|
82
|
+
console.log('Running mkdir');
|
|
83
|
+
try {
|
|
84
|
+
const answers = await inquirer.prompt([
|
|
85
|
+
/* Pass your questions in here */
|
|
86
|
+
{
|
|
87
|
+
type: 'input',
|
|
88
|
+
name: 'parentId',
|
|
89
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
90
|
+
message: 'Enter the drive fileId to make a new directory',
|
|
91
|
+
validate: (item) => !!item,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'input',
|
|
95
|
+
name: 'folder',
|
|
96
|
+
message: 'Enter the folder name to create',
|
|
97
|
+
validate: (item) => !!item,
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
const parentId = (answers.parentId || '').trim();
|
|
102
|
+
const folder = (answers.folder || '').trim();
|
|
103
|
+
if (!parentId) {
|
|
104
|
+
throw new Error('Invalid fileId!');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!folder) {
|
|
108
|
+
throw new Error('Invalid folder name!');
|
|
109
|
+
}
|
|
110
|
+
shell.exec(`gdrive mkdir -p ${parentId} ${folder}`);
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.error(e.message);
|
|
113
|
+
} finally {
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const runDelete = async () => {
|
|
118
|
+
console.log('Running Delete');
|
|
119
|
+
try {
|
|
120
|
+
const answers = await inquirer.prompt([
|
|
121
|
+
/* Pass your questions in here */
|
|
122
|
+
{
|
|
123
|
+
type: 'input',
|
|
124
|
+
name: 'driveId',
|
|
125
|
+
// message: `\n\x1b[45m\x1b[33mSelect info.json file for the desired repo\n\x1b[0m\x1b[36m"Arrow keys" -> Navigate\n"Enter" -> Select file\n\x1b[0m`,
|
|
126
|
+
message: 'Enter the drive fileId to PERMANENTLY DELETE',
|
|
127
|
+
validate: (item) => !!item,
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
const driveId = (answers.driveId || '').trim();
|
|
132
|
+
if (!driveId) {
|
|
133
|
+
throw new Error('Invalid fileId!');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
shell.exec(`gdrive delete -r ${driveId}`);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
console.error(e.message);
|
|
139
|
+
} finally {
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
runSearch,
|
|
145
|
+
runList,
|
|
146
|
+
runListSync,
|
|
147
|
+
runMkdir,
|
|
148
|
+
runDelete,
|
|
149
|
+
};
|
package/src/login.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const shell = require('shelljs');
|
|
4
|
+
|
|
5
|
+
const runLogin = async () => {
|
|
6
|
+
console.log('Running Login');
|
|
7
|
+
try {
|
|
8
|
+
console.warn(
|
|
9
|
+
'Make sure you have gdrive cli installed from (https://github.com/nurdtechie98/drive-cli)!\n'
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
shell.exec(`gdrive about`);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.error(e.message);
|
|
15
|
+
} finally {
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
runLogin,
|
|
21
|
+
};
|
package/src/sync.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const shell = require('shelljs');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const inquirer = require('inquirer');
|
|
7
|
+
const { getCfgFile } = require('./helpers');
|
|
8
|
+
|
|
9
|
+
const homedir = os.homedir();
|
|
10
|
+
const syncAllText = '0: SYNC ALL';
|
|
11
|
+
|
|
12
|
+
const getQuery = ({ dry, pth, dId }) =>
|
|
13
|
+
`gdrive sync upload ${dry ? '--dry-run' : ''} --keep-local --delete-extraneous ${pth} ${dId}`;
|
|
14
|
+
|
|
15
|
+
const showPick = (s, index) =>
|
|
16
|
+
`${index + 1}: ${s.name}\n\t${s.driveId}\n\t${s.fullpath.replace(homedir, '~')} `;
|
|
17
|
+
|
|
18
|
+
const syncOne = (cfg, dryRun) => {
|
|
19
|
+
const fullpath = cfg.fullpath;
|
|
20
|
+
const driveId = cfg.driveId;
|
|
21
|
+
|
|
22
|
+
console.log(`\x1b[33m\nSyncing ${fullpath} to drive:${driveId}\x1b[0m\n`);
|
|
23
|
+
|
|
24
|
+
if (!driveId || !fullpath) {
|
|
25
|
+
console.error(`SKIP: Invalid Params - ${fullpath} ${driveId}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const exists = fs.existsSync(fullpath);
|
|
30
|
+
if (!exists) {
|
|
31
|
+
console.error(`SKIP: File/Folder does not exist - ${fullpath}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
shell.exec(getQuery({ dry: !!dryRun, dId: driveId, pth: fullpath }));
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const syncAll = (syncs, dryRun) => {
|
|
39
|
+
try {
|
|
40
|
+
for (const cfg of syncs) {
|
|
41
|
+
syncOne(cfg, dryRun);
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
console.error(e);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const runSync = async (dryRun) => {
|
|
49
|
+
try {
|
|
50
|
+
console.log(
|
|
51
|
+
`\x1b[32m\n${dryRun ? '--- Running Dry Run ---' : ' --- Actual Sync ---'}\x1b[0m\n`
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const { syncs } = getCfgFile();
|
|
55
|
+
|
|
56
|
+
const picks = syncs.map((s, index) => showPick(s, index));
|
|
57
|
+
const syncAnswer = await inquirer.prompt([
|
|
58
|
+
{
|
|
59
|
+
name: 'picked',
|
|
60
|
+
type: 'list',
|
|
61
|
+
message: 'What folder do you like to sync to google drive?',
|
|
62
|
+
choices: [...picks, new inquirer.Separator(), syncAllText],
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
if (syncAnswer.picked === syncAllText) {
|
|
67
|
+
syncAll(syncs, dryRun);
|
|
68
|
+
} else {
|
|
69
|
+
const i = syncs.findIndex((p, ind) => {
|
|
70
|
+
return syncAnswer.picked === showPick(p, ind);
|
|
71
|
+
});
|
|
72
|
+
if (i !== -1) {
|
|
73
|
+
syncOne(syncs[i], dryRun);
|
|
74
|
+
} else {
|
|
75
|
+
console.error('Failed!', i);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(e);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
module.exports = {
|
|
83
|
+
runSync,
|
|
84
|
+
};
|