guratan 0.4.0 → 0.5.2

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # guratan
2
2
 
3
- Google Drive へファイルを送信する簡易ツール。
3
+ Google Drive を操作する簡易ツール。
4
4
 
5
5
  ## Usage
6
6
 
@@ -17,6 +17,18 @@ $ GOOGLE_APPLICATION_CREDENTIALS=./gha-creds-temp.json npx guratan send --parent
17
17
  - 各オプションは環境変数での指定も可能(例. `--parent-id` = `GURATAN_PARENT_ID`)
18
18
  - `guratan` からは upload と update のみ可能
19
19
 
20
+ ### recv
21
+
22
+ ```
23
+ $ GOOGLE_APPLICATION_CREDENTIALS=./gha-creds-temp.json npx guratan recv --parent-id 12345ABC --src-file-name test.txt --dest-file-name path/to/test.txt
24
+ ```
25
+
26
+ - `GOOGLE_APPLICATION_CREDENTIALS` にはサービスアカウントの鍵ファイルを指定
27
+ - 受信元フォルダー(`--parent-id`) のファイル(`--dest-file-name`)を受信する
28
+ - 同名ファイルが複数ある場合は最初にヒットしたものを受信する
29
+ - `--parent-id` `--src-file-name` の代わりに `--file-id` で受信ファイルを指定できる
30
+ - 各オプションは環境変数での指定も可能(例. `--parent-id` = `GURATAN_PARENT_ID`)
31
+
20
32
  ### share
21
33
 
22
34
  ```
package/dist/cli.d.ts CHANGED
@@ -13,6 +13,14 @@ declare type OptsSend = Opts & {
13
13
  srcMimeType: string;
14
14
  printId: boolean;
15
15
  };
16
+ declare type OptsRecv = Opts & {
17
+ fileId: string;
18
+ parentId: string;
19
+ srcFileName: string;
20
+ destFileName: string;
21
+ destMimeType: string;
22
+ printId: boolean;
23
+ };
16
24
  declare type OptsShare = Opts & {
17
25
  fileId: string;
18
26
  parentId: string;
@@ -30,5 +38,6 @@ declare type OptsShare = Opts & {
30
38
  printId: boolean;
31
39
  };
32
40
  export declare const cliSend: ({ fileId, parentId, destFileName, srcFileName, destMimeType, srcMimeType, printId, stdout, stderr }: OptsSend) => Promise<number>;
41
+ export declare const cliRecv: ({ fileId, parentId, srcFileName, destFileName, destMimeType, printId, stdout, stderr }: OptsRecv) => Promise<number>;
33
42
  export declare const cliShare: ({ fileId, parentId, destFileName, type, role, emailAddress, domain, allowFileDiscovery, view, moveToNewOwnersRoot, transferOwnership, sendNotificationEmail, emailMessage, printId, stdout, stderr }: OptsShare) => Promise<number>;
34
43
  export {};
package/dist/cli.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { driveClient } from './tdrive.js';
2
- import { sendFile } from './tsend.js';
3
- import { createPermisson } from './tshare.js';
4
2
  export const cliSend = async ({ fileId, parentId, destFileName, srcFileName, destMimeType, srcMimeType, printId, stdout, stderr }) => {
5
3
  try {
4
+ const { sendFile } = await import('./tsend.js');
6
5
  const id = await sendFile(driveClient(), {
7
6
  fileId,
8
7
  parentId,
@@ -22,8 +21,30 @@ export const cliSend = async ({ fileId, parentId, destFileName, srcFileName, des
22
21
  }
23
22
  return 0;
24
23
  };
24
+ export const cliRecv = async ({ fileId, parentId, srcFileName, destFileName, destMimeType, printId, stdout, stderr }) => {
25
+ try {
26
+ const { recvFile } = await import('./trecv.js');
27
+ const id = await recvFile(driveClient(), {
28
+ fileId,
29
+ parentId,
30
+ srcFileName,
31
+ destFileName,
32
+ destMimeType
33
+ });
34
+ if (printId) {
35
+ stdout.write(id);
36
+ }
37
+ }
38
+ catch (err) {
39
+ stderr.write(err.toString());
40
+ stderr.write('\n');
41
+ return 1;
42
+ }
43
+ return 0;
44
+ };
25
45
  export const cliShare = async ({ fileId, parentId, destFileName, type, role, emailAddress, domain, allowFileDiscovery, view, moveToNewOwnersRoot, transferOwnership, sendNotificationEmail, emailMessage, printId, stdout, stderr }) => {
26
46
  try {
47
+ const { createPermisson } = await import('./tshare.js');
27
48
  const id = await createPermisson(driveClient(), {
28
49
  fileId,
29
50
  parentId,
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { driveClient } from './tdrive.js';
2
2
  export { sendFile } from './tsend.js';
3
+ export { recvFile } from './trecv.js';
3
4
  export { createPermisson } from './tshare.js';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { driveClient } from './tdrive.js';
2
2
  export { sendFile } from './tsend.js';
3
+ export { recvFile } from './trecv.js';
3
4
  export { createPermisson } from './tshare.js';
package/dist/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from 'yargs';
3
3
  import { hideBin } from 'yargs/helpers';
4
- import { cliSend, cliShare } from './cli.js';
4
+ import { cliRecv, cliSend, cliShare } from './cli.js';
5
5
  const envVarsPrefix = process.env['GURATAN_ENV_VARS_PREFIX'] || 'GURATAN';
6
6
  const argv = await yargs(hideBin(process.argv))
7
7
  .scriptName('guratan')
@@ -50,6 +50,45 @@ const argv = await yargs(hideBin(process.argv))
50
50
  description: 'Print the id of the file that is sended into remote'
51
51
  }
52
52
  });
53
+ })
54
+ .command('recv [OPTIONS]', 'receive file from Google Drive to local file', (yargs) => {
55
+ return yargs.options({
56
+ 'file-id': {
57
+ type: 'string',
58
+ default: '',
59
+ required: false,
60
+ description: 'The ID of the file or shared drive.'
61
+ },
62
+ 'parent-id': {
63
+ type: 'string',
64
+ default: '',
65
+ required: false,
66
+ description: 'The IDs of the parent folders which contain the file.'
67
+ },
68
+ 'src-file-name': {
69
+ type: 'string',
70
+ required: false,
71
+ description: 'The name of the file in remote'
72
+ },
73
+ 'dest-file-name': {
74
+ type: 'string',
75
+ default: '',
76
+ required: true,
77
+ description: 'The name(path) of the file in local filesystem'
78
+ },
79
+ 'dest-mime-type': {
80
+ type: 'string',
81
+ required: false,
82
+ default: '',
83
+ description: 'Media mime-type'
84
+ },
85
+ 'print-id': {
86
+ type: 'boolean',
87
+ required: false,
88
+ default: false,
89
+ description: 'Print the id of the file that is received from remote'
90
+ }
91
+ });
53
92
  })
54
93
  .command('share [OPTIONS]', 'share file in Google Drive', (yargs) => {
55
94
  return yargs.options({
@@ -152,6 +191,18 @@ switch (`${argv._[0]}`) {
152
191
  stderr: process.stderr
153
192
  }));
154
193
  break;
194
+ case 'recv':
195
+ process.exit(await cliRecv({
196
+ fileId: argv['file-id'],
197
+ parentId: argv['parent-id'] || '',
198
+ srcFileName: argv['src-file-name'] || '',
199
+ destFileName: argv['dest-file-name'] || '',
200
+ destMimeType: argv['dest-mime-type'] || '',
201
+ printId: argv['print-id'] || false,
202
+ stdout: process.stdout,
203
+ stderr: process.stderr
204
+ }));
205
+ break;
155
206
  case 'share':
156
207
  process.exit(await cliShare({
157
208
  fileId: argv['file-id'],
package/dist/tdrive.d.ts CHANGED
@@ -1,3 +1,15 @@
1
+ import { drive_v3 } from '@googleapis/drive';
2
+ export declare class GetFileIdError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Get file id in spesiced parent.
7
+ * @param drive - drive instance.
8
+ * @param parentId - id of folder in Google Deive.
9
+ * @param fileName - file name.
10
+ * @returns id of file or blank(when file is not found)
11
+ */
12
+ export declare function getFileId(drive: drive_v3.Drive, parentId: string, fileName: string): Promise<string>;
1
13
  /**
2
14
  * Validate value that is used in query parameter.
3
15
  * return false if value has included "'">
@@ -9,4 +21,4 @@ export declare function validateQueryValue(s: string): boolean;
9
21
  * Make instacen of drive that is authenticated.
10
22
  * @returns instance of drive.
11
23
  */
12
- export declare function driveClient(): import("@googleapis/drive").drive_v3.Drive;
24
+ export declare function driveClient(): drive_v3.Drive;
package/dist/tdrive.js CHANGED
@@ -1,5 +1,44 @@
1
1
  import { GoogleAuth } from 'google-auth-library';
2
2
  import { drive as gdrive } from '@googleapis/drive';
3
+ export class GetFileIdError extends Error {
4
+ constructor(message) {
5
+ //https://stackoverflow.com/questions/41102060/typescript-extending-error-class
6
+ super(message);
7
+ Object.setPrototypeOf(this, GetFileIdError.prototype);
8
+ }
9
+ }
10
+ /**
11
+ * Get file id in spesiced parent.
12
+ * @param drive - drive instance.
13
+ * @param parentId - id of folder in Google Deive.
14
+ * @param fileName - file name.
15
+ * @returns id of file or blank(when file is not found)
16
+ */
17
+ export async function getFileId(drive, parentId, fileName) {
18
+ try {
19
+ if (validateQueryValue(parentId) === false) {
20
+ throw new GetFileIdError(`Invalid paretnt id : ${parentId}`);
21
+ }
22
+ if (validateQueryValue(fileName) === false) {
23
+ throw new GetFileIdError(`Invalid file name : ${fileName}`);
24
+ }
25
+ const list = await drive.files.list({
26
+ pageSize: 10,
27
+ q: `'${parentId}' in parents and name = '${fileName}'`,
28
+ fields: 'files(id, name)'
29
+ });
30
+ if (list.data.files && list.data.files.length > 0) {
31
+ return list.data.files[0].id || '';
32
+ }
33
+ return '';
34
+ }
35
+ catch (err) {
36
+ if (err.errors) {
37
+ throw new GetFileIdError(JSON.stringify(err.errors));
38
+ }
39
+ throw err;
40
+ }
41
+ }
3
42
  /**
4
43
  * Validate value that is used in query parameter.
5
44
  * return false if value has included "'">
@@ -0,0 +1,44 @@
1
+ import { drive_v3 } from '@googleapis/drive';
2
+ export declare class DownloadFileError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Options for recvFile().
7
+ */
8
+ export declare type RecvFileOpts = {
9
+ /**
10
+ * @type The ID of the file or shared drive.
11
+ */
12
+ fileId: string;
13
+ /**
14
+ /**
15
+ * @type The IDs of the parent folders which contain the file.
16
+ */
17
+ parentId: string;
18
+ /**
19
+ * @type The name of the file in remote
20
+ */
21
+ srcFileName: string;
22
+ /**
23
+ @type The name(path) of the file in local filesystem
24
+ */
25
+ destFileName: string;
26
+ /**
27
+ * @type Media mime-type.
28
+ */
29
+ destMimeType: string;
30
+ };
31
+ /**
32
+ * Download the file from Google Drive to the locale file
33
+ * @param drive - drive instance.
34
+ * @param opts - options.
35
+ * @returns
36
+ */
37
+ export declare function downloadFile(drive: drive_v3.Drive, opts: Pick<RecvFileOpts, 'fileId' | 'destFileName' | 'destMimeType'>): Promise<void>;
38
+ /**
39
+ * Receive the file from Google Drive to the locale file
40
+ * @param drive - drive instance.
41
+ * @param opts - options.
42
+ * @returns id of file in Google Drive
43
+ */
44
+ export declare function recvFile(drive: drive_v3.Drive, opts: RecvFileOpts): Promise<string>;
package/dist/trecv.js ADDED
@@ -0,0 +1,79 @@
1
+ import * as fs from 'fs';
2
+ import { promisify } from 'util';
3
+ import { getFileId, GetFileIdError } from './tdrive.js';
4
+ export class DownloadFileError extends Error {
5
+ constructor(message) {
6
+ //https://stackoverflow.com/questions/41102060/typescript-extending-error-class
7
+ super(message);
8
+ Object.setPrototypeOf(this, DownloadFileError.prototype);
9
+ }
10
+ }
11
+ /**
12
+ * Download the file from Google Drive to the locale file
13
+ * @param drive - drive instance.
14
+ * @param opts - options.
15
+ * @returns
16
+ */
17
+ export async function downloadFile(drive, opts) {
18
+ let ret;
19
+ try {
20
+ const { fileId, destFileName, destMimeType } = opts;
21
+ const dest = fs.createWriteStream(destFileName);
22
+ try {
23
+ if (destMimeType) {
24
+ const params = {
25
+ fileId,
26
+ mimeType: destMimeType
27
+ };
28
+ const res = await drive.files.export(params, { responseType: 'stream' });
29
+ for await (const c of res.data) {
30
+ dest.write(c);
31
+ }
32
+ }
33
+ else {
34
+ const params = {
35
+ fileId,
36
+ alt: 'media'
37
+ };
38
+ const res = await drive.files.get(params, { responseType: 'stream' });
39
+ for await (const c of res.data) {
40
+ dest.write(c);
41
+ }
42
+ }
43
+ }
44
+ catch (err) {
45
+ if (err.errors) {
46
+ throw new DownloadFileError(JSON.stringify(err.errors));
47
+ }
48
+ if (err.response?.status) {
49
+ throw new DownloadFileError(`status:${err.response.status}\nstatusText:${err.response.statusText}`);
50
+ }
51
+ throw new DownloadFileError(err);
52
+ }
53
+ finally {
54
+ // return promisify(dest.close.bind(dest))() ここで return すると常に undfeind になる
55
+ ret = promisify(dest.close.bind(dest))();
56
+ }
57
+ }
58
+ catch (err) {
59
+ throw err;
60
+ }
61
+ return ret;
62
+ }
63
+ /**
64
+ * Receive the file from Google Drive to the locale file
65
+ * @param drive - drive instance.
66
+ * @param opts - options.
67
+ * @returns id of file in Google Drive
68
+ */
69
+ export async function recvFile(drive, opts) {
70
+ const { fileId: inFileId, parentId, srcFileName, destFileName, destMimeType } = opts;
71
+ let fileId = inFileId !== '' ? inFileId : await getFileId(drive, parentId, srcFileName);
72
+ if (fileId === '') {
73
+ throw new GetFileIdError(
74
+ // `The srouce file not found in paretnt id : ${srcFileName}, ${parentId}`
75
+ `The srouce file not found`);
76
+ }
77
+ await downloadFile(drive, { fileId, destFileName, destMimeType });
78
+ return fileId;
79
+ }
package/dist/tsend.d.ts CHANGED
@@ -1,7 +1,4 @@
1
1
  import { drive_v3 } from '@googleapis/drive';
2
- export declare class GetFileIdError extends Error {
3
- constructor(message: string);
4
- }
5
2
  export declare class UploadFileError extends Error {
6
3
  constructor(message: string);
7
4
  }
@@ -38,14 +35,6 @@ export declare type SendFileOpts = {
38
35
  */
39
36
  srcMimeType: string;
40
37
  };
41
- /**
42
- * Get file id in spesiced parent.
43
- * @param drive - drive instance.
44
- * @param parentId - id of folder in Google Deive.
45
- * @param fileName - file name.
46
- * @returns id of file or blank(when file is not found)
47
- */
48
- export declare function getFileId(drive: drive_v3.Drive, parentId: string, fileName: string): Promise<string>;
49
38
  /**
50
39
  * Create file using by source file into Google Drive.
51
40
  * @param drive - drive instance.
package/dist/tsend.js CHANGED
@@ -1,13 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
- import { validateQueryValue } from './tdrive.js';
4
- export class GetFileIdError extends Error {
5
- constructor(message) {
6
- //https://stackoverflow.com/questions/41102060/typescript-extending-error-class
7
- super(message);
8
- Object.setPrototypeOf(this, GetFileIdError.prototype);
9
- }
10
- }
3
+ import { promisify } from 'util';
4
+ import { getFileId } from './tdrive.js';
11
5
  export class UploadFileError extends Error {
12
6
  constructor(message) {
13
7
  //https://stackoverflow.com/questions/41102060/typescript-extending-error-class
@@ -22,38 +16,6 @@ export class UpdateFileError extends Error {
22
16
  Object.setPrototypeOf(this, UpdateFileError.prototype);
23
17
  }
24
18
  }
25
- /**
26
- * Get file id in spesiced parent.
27
- * @param drive - drive instance.
28
- * @param parentId - id of folder in Google Deive.
29
- * @param fileName - file name.
30
- * @returns id of file or blank(when file is not found)
31
- */
32
- export async function getFileId(drive, parentId, fileName) {
33
- try {
34
- if (validateQueryValue(parentId) === false) {
35
- throw new GetFileIdError(`Invalid paretnt id : ${parentId}`);
36
- }
37
- if (validateQueryValue(fileName) === false) {
38
- throw new GetFileIdError(`Invalid file name : ${fileName}`);
39
- }
40
- const list = await drive.files.list({
41
- pageSize: 10,
42
- q: `'${parentId}' in parents and name = '${fileName}'`,
43
- fields: 'files(id, name)'
44
- });
45
- if (list.data.files && list.data.files.length > 0) {
46
- return list.data.files[0].id || '';
47
- }
48
- return '';
49
- }
50
- catch (err) {
51
- if (err.errors) {
52
- throw new GetFileIdError(JSON.stringify(err.errors));
53
- }
54
- throw err;
55
- }
56
- }
57
19
  /**
58
20
  * Create file using by source file into Google Drive.
59
21
  * @param drive - drive instance.
@@ -61,30 +23,41 @@ export async function getFileId(drive, parentId, fileName) {
61
23
  * @returns Print the id of the file that is sended into remote
62
24
  */
63
25
  export async function uploadFile(drive, opts) {
26
+ let ret = '';
64
27
  try {
65
28
  const { parentId, destFileName, srcFileName, destMimeType, srcMimeType } = opts;
66
- const params = {
67
- requestBody: {
68
- name: path.basename(destFileName),
69
- parents: [parentId]
70
- },
71
- media: {
72
- body: fs.createReadStream(srcFileName)
73
- },
74
- fields: 'id'
75
- };
76
- if (destMimeType) {
77
- params.requestBody.mimeType = destMimeType;
29
+ const srcStream = fs.createReadStream(srcFileName);
30
+ try {
31
+ const params = {
32
+ requestBody: {
33
+ name: path.basename(destFileName),
34
+ parents: [parentId]
35
+ },
36
+ media: {
37
+ body: srcStream
38
+ },
39
+ fields: 'id'
40
+ };
41
+ if (destMimeType) {
42
+ params.requestBody.mimeType = destMimeType;
43
+ }
44
+ if (srcMimeType) {
45
+ params.media.mimeType = srcMimeType;
46
+ }
47
+ const res = await drive.files.create(params);
48
+ ret = res.data.id || '';
49
+ }
50
+ catch (err) {
51
+ throw new UploadFileError(JSON.stringify(err.errors));
78
52
  }
79
- if (srcMimeType) {
80
- params.media.mimeType = srcMimeType;
53
+ finally {
54
+ await promisify(srcStream.close.bind(srcStream))();
81
55
  }
82
- const res = await drive.files.create(params);
83
- return res.data.id || '';
84
56
  }
85
57
  catch (err) {
86
- throw new UploadFileError(JSON.stringify(err.errors));
58
+ throw err;
87
59
  }
60
+ return ret;
88
61
  }
89
62
  /**
90
63
  * Update file using by source file into Google Drive.
@@ -93,28 +66,39 @@ export async function uploadFile(drive, opts) {
93
66
  * @returns id of file in Google Drive
94
67
  */
95
68
  export async function updateFile(drive, opts) {
69
+ let ret = '';
96
70
  try {
97
71
  const { fileId, srcFileName, destMimeType, srcMimeType } = opts;
98
- const params = {
99
- fileId,
100
- requestBody: {},
101
- media: {
102
- body: fs.createReadStream(srcFileName)
103
- },
104
- fields: 'id'
105
- };
106
- if (destMimeType) {
107
- params.requestBody.mimeType = destMimeType;
72
+ const srcStream = fs.createReadStream(srcFileName);
73
+ try {
74
+ const params = {
75
+ fileId,
76
+ requestBody: {},
77
+ media: {
78
+ body: srcStream
79
+ },
80
+ fields: 'id'
81
+ };
82
+ if (destMimeType) {
83
+ params.requestBody.mimeType = destMimeType;
84
+ }
85
+ if (srcMimeType) {
86
+ params.media.mimeType = srcMimeType;
87
+ }
88
+ const res = await drive.files.update(params);
89
+ ret = res.data.id || '';
108
90
  }
109
- if (srcMimeType) {
110
- params.media.mimeType = srcMimeType;
91
+ catch (err) {
92
+ throw new UpdateFileError(JSON.stringify(err.errors));
93
+ }
94
+ finally {
95
+ await promisify(srcStream.close.bind(srcStream))();
111
96
  }
112
- const res = await drive.files.update(params);
113
- return res.data.id || '';
114
97
  }
115
98
  catch (err) {
116
- throw new UpdateFileError(JSON.stringify(err.errors));
99
+ throw err;
117
100
  }
101
+ return ret;
118
102
  }
119
103
  /**
120
104
  * Send file using by source file into Google Drive.
package/dist/tshare.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getFileId } from './tsend.js';
1
+ import { getFileId } from './tdrive.js';
2
2
  export class CreatePermissonError extends Error {
3
3
  constructor(message) {
4
4
  //https://stackoverflow.com/questions/41102060/typescript-extending-error-class
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guratan",
3
- "version": "0.4.0",
3
+ "version": "0.5.2",
4
4
  "description": "Tiny send tool for Google Drive",
5
5
  "author": "hankei6km <hankei6km@gmail.com> (https://github.com/hankei6km)",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/jest": "^27.4.1",
42
- "@types/node": "^17.0.21",
42
+ "@types/node": "^16.11.26",
43
43
  "@types/yargs": "^17.0.9",
44
44
  "jest": "^27.5.1",
45
45
  "rimraf": "^3.0.2",