guratan 0.2.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/LICENSE +9 -0
- package/README.md +19 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +40 -0
- package/dist/tsend.d.ts +48 -0
- package/dist/tsend.js +150 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 hankei6km
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# guratan
|
|
2
|
+
|
|
3
|
+
Google Drive へファイルを送信する簡易ツール。
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
$ GOOGLE_APPLICATION_CREDENTIALS=./gha-creds-temp.json npx guratan send --parent-id 12345ABC --dest-file-name test.txt --src-file-name path/to/test.txt
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- `GOOGLE_APPLICATION_CREDENTIALS` にはサービスアカウントの鍵ファイルを指定
|
|
12
|
+
- 送信先フォルダー(`--parent-id`) に同名ファイル(`--dest-file-name`) が存在するときは上書きされる
|
|
13
|
+
- 各オプションは環境変数での指定も可能(例. `--parent-id` = `GURATAN_PARENT_ID`)
|
|
14
|
+
|
|
15
|
+
## License
|
|
16
|
+
|
|
17
|
+
MIT License
|
|
18
|
+
|
|
19
|
+
Copyright (c) 2022 hankei6km
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Writable } from 'stream';
|
|
3
|
+
declare type Opts = {
|
|
4
|
+
parentId: string;
|
|
5
|
+
destFileName: string;
|
|
6
|
+
srcFileName: string;
|
|
7
|
+
printId: boolean;
|
|
8
|
+
stdout: Writable;
|
|
9
|
+
stderr: Writable;
|
|
10
|
+
};
|
|
11
|
+
export declare const cli: ({ parentId, destFileName, srcFileName, printId, stdout, stderr }: Opts) => Promise<number>;
|
|
12
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { driveClient, sendFile } from './tsend.js';
|
|
2
|
+
export const cli = async ({ parentId, destFileName, srcFileName, printId, stdout, stderr }) => {
|
|
3
|
+
try {
|
|
4
|
+
const id = await sendFile(driveClient(), parentId, destFileName, srcFileName);
|
|
5
|
+
if (printId) {
|
|
6
|
+
stdout.write(id);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
stderr.write(err.toString());
|
|
11
|
+
stderr.write('\n');
|
|
12
|
+
return 1;
|
|
13
|
+
}
|
|
14
|
+
return 0;
|
|
15
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sendFile } from './tsend.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sendFile } from './tsend.js';
|
package/dist/main.d.ts
ADDED
package/dist/main.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from 'yargs';
|
|
3
|
+
import { hideBin } from 'yargs/helpers';
|
|
4
|
+
import { cli } from './cli.js';
|
|
5
|
+
const envVarsPrefix = process.env['GURATAN_ENV_VARS_PREFIX'] || 'GURATAN';
|
|
6
|
+
const argv = await yargs(hideBin(process.argv))
|
|
7
|
+
.scriptName('guratan')
|
|
8
|
+
.env(envVarsPrefix)
|
|
9
|
+
.command('$0 send [OPTIONS]', 'send file to folder in Google Drive', (yargs) => {
|
|
10
|
+
return yargs.options({
|
|
11
|
+
'parent-id': {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'id of folder in Google Deive'
|
|
14
|
+
},
|
|
15
|
+
'dest-file-name': {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'file name in Google Drive'
|
|
18
|
+
},
|
|
19
|
+
'src-file-name': {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'file name in local filesystem'
|
|
22
|
+
},
|
|
23
|
+
'print-id': {
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
required: false,
|
|
26
|
+
default: false,
|
|
27
|
+
description: 'print id of file that is sended into Google Drive'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
})
|
|
31
|
+
.demand(0)
|
|
32
|
+
.help().argv;
|
|
33
|
+
process.exit(await cli({
|
|
34
|
+
parentId: argv['parent-id'] || '',
|
|
35
|
+
destFileName: argv['dest-file-name'] || '',
|
|
36
|
+
srcFileName: argv['src-file-name'] || '',
|
|
37
|
+
printId: argv['print-id'] || false,
|
|
38
|
+
stdout: process.stdout,
|
|
39
|
+
stderr: process.stderr
|
|
40
|
+
}));
|
package/dist/tsend.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { drive_v3 } from '@googleapis/drive';
|
|
2
|
+
export declare class GetFileIdError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class UploadFileError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class UpdateFileError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validate value that is used in query parameter.
|
|
13
|
+
* return false if value has included "'">
|
|
14
|
+
* @param s - value string.
|
|
15
|
+
* @returns result of validation.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateQueryValue(s: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Make instacen of drive that is authenticated.
|
|
20
|
+
* @returns instance of drive.
|
|
21
|
+
*/
|
|
22
|
+
export declare function driveClient(): drive_v3.Drive;
|
|
23
|
+
/**
|
|
24
|
+
* Get file id in spesiced parent.
|
|
25
|
+
* @param drive - drive instance.
|
|
26
|
+
* @param parentId - id of folder in Google Deive.
|
|
27
|
+
* @param fileName - file name.
|
|
28
|
+
* @returns id of file or blank(when file is not found)
|
|
29
|
+
*/
|
|
30
|
+
export declare function getFileId(drive: drive_v3.Drive, parentId: string, fileName: string): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Create file using by source file into Google Drive.
|
|
33
|
+
* @param drive - drive instance.
|
|
34
|
+
* @param parentId - id of folder in Google Deive.
|
|
35
|
+
* @param destFileName - file name in Google Drive.
|
|
36
|
+
* @param srcFileName - file name in local filesystem.
|
|
37
|
+
* @returns id of file in Google Drive
|
|
38
|
+
*/
|
|
39
|
+
export declare function uploadFile(drive: drive_v3.Drive, parentId: string, destFileName: string, srcFileName: string): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Update file using by source file into Google Drive.
|
|
42
|
+
* @param drive - drive instance.
|
|
43
|
+
* @param fileId - id of file in Google Deive.
|
|
44
|
+
* @param srcFileName - file name in local filesystem.
|
|
45
|
+
* @returns id of file in Google Drive
|
|
46
|
+
*/
|
|
47
|
+
export declare function updateFile(drive: drive_v3.Drive, fileId: string, srcFileName: string): Promise<string>;
|
|
48
|
+
export declare function sendFile(drive: drive_v3.Drive, parentId: string, destFileName: string, srcFileName: string): Promise<string>;
|
package/dist/tsend.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { drive as gdrive } from '@googleapis/drive';
|
|
4
|
+
import { GoogleAuth } from 'google-auth-library';
|
|
5
|
+
export class GetFileIdError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
//https://stackoverflow.com/questions/41102060/typescript-extending-error-class
|
|
8
|
+
super(message);
|
|
9
|
+
Object.setPrototypeOf(this, GetFileIdError.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class UploadFileError extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
//https://stackoverflow.com/questions/41102060/typescript-extending-error-class
|
|
15
|
+
super(message);
|
|
16
|
+
Object.setPrototypeOf(this, UploadFileError.prototype);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class UpdateFileError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
//https://stackoverflow.com/questions/41102060/typescript-extending-error-class
|
|
22
|
+
super(message);
|
|
23
|
+
Object.setPrototypeOf(this, UpdateFileError.prototype);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validate value that is used in query parameter.
|
|
28
|
+
* return false if value has included "'">
|
|
29
|
+
* @param s - value string.
|
|
30
|
+
* @returns result of validation.
|
|
31
|
+
*/
|
|
32
|
+
export function validateQueryValue(s) {
|
|
33
|
+
if (s.indexOf("'") >= 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Make instacen of drive that is authenticated.
|
|
40
|
+
* @returns instance of drive.
|
|
41
|
+
*/
|
|
42
|
+
export function driveClient() {
|
|
43
|
+
const SCOPES = ['https://www.googleapis.com/auth/drive.file'];
|
|
44
|
+
const auth = new GoogleAuth({
|
|
45
|
+
scopes: SCOPES
|
|
46
|
+
});
|
|
47
|
+
return gdrive({ version: 'v3', auth });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get file id in spesiced parent.
|
|
51
|
+
* @param drive - drive instance.
|
|
52
|
+
* @param parentId - id of folder in Google Deive.
|
|
53
|
+
* @param fileName - file name.
|
|
54
|
+
* @returns id of file or blank(when file is not found)
|
|
55
|
+
*/
|
|
56
|
+
export async function getFileId(drive, parentId, fileName) {
|
|
57
|
+
try {
|
|
58
|
+
if (validateQueryValue(parentId) === false) {
|
|
59
|
+
throw new GetFileIdError(`Invalid paretnt id : ${parentId}`);
|
|
60
|
+
}
|
|
61
|
+
if (validateQueryValue(fileName) === false) {
|
|
62
|
+
throw new GetFileIdError(`Invalid file name : ${fileName}`);
|
|
63
|
+
}
|
|
64
|
+
const list = await drive.files.list({
|
|
65
|
+
pageSize: 10,
|
|
66
|
+
q: `'${parentId}' in parents and name = '${fileName}'`,
|
|
67
|
+
fields: 'files(id, name)'
|
|
68
|
+
});
|
|
69
|
+
if (list.data.files && list.data.files.length > 0) {
|
|
70
|
+
return list.data.files[0].id || '';
|
|
71
|
+
}
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
if (err.errors) {
|
|
76
|
+
throw new GetFileIdError(JSON.stringify(err.errors));
|
|
77
|
+
}
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create file using by source file into Google Drive.
|
|
83
|
+
* @param drive - drive instance.
|
|
84
|
+
* @param parentId - id of folder in Google Deive.
|
|
85
|
+
* @param destFileName - file name in Google Drive.
|
|
86
|
+
* @param srcFileName - file name in local filesystem.
|
|
87
|
+
* @returns id of file in Google Drive
|
|
88
|
+
*/
|
|
89
|
+
export async function uploadFile(drive, parentId, destFileName, srcFileName) {
|
|
90
|
+
try {
|
|
91
|
+
const res = await drive.files.create({
|
|
92
|
+
requestBody: {
|
|
93
|
+
name: path.basename(destFileName),
|
|
94
|
+
parents: [parentId]
|
|
95
|
+
},
|
|
96
|
+
media: {
|
|
97
|
+
// mimeType: 'image/jpeg',
|
|
98
|
+
body: fs.createReadStream(srcFileName)
|
|
99
|
+
},
|
|
100
|
+
fields: 'id'
|
|
101
|
+
});
|
|
102
|
+
return res.data.id || '';
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
throw new UploadFileError(JSON.stringify(err.errors));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update file using by source file into Google Drive.
|
|
110
|
+
* @param drive - drive instance.
|
|
111
|
+
* @param fileId - id of file in Google Deive.
|
|
112
|
+
* @param srcFileName - file name in local filesystem.
|
|
113
|
+
* @returns id of file in Google Drive
|
|
114
|
+
*/
|
|
115
|
+
export async function updateFile(drive, fileId, srcFileName) {
|
|
116
|
+
try {
|
|
117
|
+
const res = await drive.files.update({
|
|
118
|
+
fileId,
|
|
119
|
+
requestBody: {},
|
|
120
|
+
media: {
|
|
121
|
+
// mimeType: 'image/jpeg',
|
|
122
|
+
body: fs.createReadStream(srcFileName)
|
|
123
|
+
},
|
|
124
|
+
fields: 'id'
|
|
125
|
+
});
|
|
126
|
+
return res.data.id || '';
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
throw new UpdateFileError(JSON.stringify(err.errors));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function sendFile(drive, parentId, destFileName, srcFileName) {
|
|
133
|
+
const fileId = await getFileId(drive, parentId, destFileName);
|
|
134
|
+
if (fileId === '') {
|
|
135
|
+
return uploadFile(drive, parentId, destFileName, srcFileName);
|
|
136
|
+
}
|
|
137
|
+
return updateFile(drive, fileId, srcFileName);
|
|
138
|
+
}
|
|
139
|
+
// try {
|
|
140
|
+
// const parentId = process.env['PARENT_ID'] || ''
|
|
141
|
+
// const destFileName = process.env['DEST_FILE_NAME'] || ''
|
|
142
|
+
// const srcFileName = process.env['SRC_FILE_NAME'] || ''
|
|
143
|
+
// const drive = driveClient()
|
|
144
|
+
// const id = await getFileId(drive, parentId, destFileName)
|
|
145
|
+
// console.log(id)
|
|
146
|
+
// console.log(await updateFile(drive, id, srcFileName))
|
|
147
|
+
// } catch (err) {
|
|
148
|
+
// console.error('--err--')
|
|
149
|
+
// console.error(err)
|
|
150
|
+
// }
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "guratan",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Tiny send tool for Google Drive",
|
|
5
|
+
"author": "hankei6km <hankei6km@gmail.com> (https://github.com/hankei6km)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git://github.com/hankei6km/tsend.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/hankei6km/tsend/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"google",
|
|
16
|
+
"drive"
|
|
17
|
+
],
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"exports": "./dist/index.js",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"bin": {
|
|
26
|
+
"guratan": "dist/main.js"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"start": "npm run build && node dist/main.js",
|
|
30
|
+
"build": "npm run clean && tsc && rimraf dist/test && mv dist/src/* dist/ && rimraf dist/src",
|
|
31
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
32
|
+
"clean": "rimraf \"dist/*\"",
|
|
33
|
+
"upgrade-interactive": "npm-check --update",
|
|
34
|
+
"csb:test": "npm test -- --runInBand --watchAll"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@googleapis/drive": "^2.3.0",
|
|
38
|
+
"yargs": "^17.3.1"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/jest": "^27.4.1",
|
|
42
|
+
"@types/node": "^17.0.21",
|
|
43
|
+
"@types/yargs": "^17.0.9",
|
|
44
|
+
"jest": "^27.5.1",
|
|
45
|
+
"rimraf": "^3.0.2",
|
|
46
|
+
"ts-jest": "^27.1.3",
|
|
47
|
+
"ts-node": "^10.7.0",
|
|
48
|
+
"typescript": "^4.6.2"
|
|
49
|
+
}
|
|
50
|
+
}
|