@adobe/helix-google-support 1.1.0 → 1.2.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/CHANGELOG.md +21 -0
- package/package.json +1 -1
- package/src/GoogleClient.d.ts +140 -0
- package/src/GoogleClient.js +80 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [1.2.2](https://github.com/adobe/helix-google-support/compare/v1.2.1...v1.2.2) (2022-04-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* include mimeType ([#11](https://github.com/adobe/helix-google-support/issues/11)) ([67ab999](https://github.com/adobe/helix-google-support/commit/67ab999a7fee111978a15c4393761e4b614ee2fc))
|
|
7
|
+
|
|
8
|
+
## [1.2.1](https://github.com/adobe/helix-google-support/compare/v1.2.0...v1.2.1) (2022-04-28)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* include mimeType ([#10](https://github.com/adobe/helix-google-support/issues/10)) ([993e24a](https://github.com/adobe/helix-google-support/commit/993e24acdd723402a6d85a8bf74e3b93df8c5d0e))
|
|
14
|
+
|
|
15
|
+
# [1.2.0](https://github.com/adobe/helix-google-support/compare/v1.1.0...v1.2.0) (2022-04-28)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add get file|doc from path ([#9](https://github.com/adobe/helix-google-support/issues/9)) ([4a2e927](https://github.com/adobe/helix-google-support/commit/4a2e9272f4328e936e65b7144d04e516ac602625))
|
|
21
|
+
|
|
1
22
|
# [1.1.0](https://github.com/adobe/helix-google-support/compare/v1.0.1...v1.1.0) (2022-04-28)
|
|
2
23
|
|
|
3
24
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
declare interface ICachePlugin {}
|
|
13
|
+
|
|
14
|
+
declare interface DriveItemInfo {}
|
|
15
|
+
|
|
16
|
+
declare interface GoogleClientOptions {
|
|
17
|
+
log:Console;
|
|
18
|
+
clientId:string;
|
|
19
|
+
clientSecret:string;
|
|
20
|
+
redirectUri:string;
|
|
21
|
+
cachePlugin?:ICachePlugin;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Google client
|
|
26
|
+
*/
|
|
27
|
+
declare class GoogleClient {
|
|
28
|
+
/**
|
|
29
|
+
* Sets the global item cache options. It internally creates a new LRU
|
|
30
|
+
* with the given options
|
|
31
|
+
*
|
|
32
|
+
* @param opts
|
|
33
|
+
*/
|
|
34
|
+
static setItemCacheOptions(opts:object);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns a url for a google drive id.
|
|
38
|
+
* @param {string} id
|
|
39
|
+
* @returns {string}
|
|
40
|
+
*/
|
|
41
|
+
static id2Url(id:string):string;
|
|
42
|
+
|
|
43
|
+
constructor(opts:GoogleClientOptions);
|
|
44
|
+
|
|
45
|
+
init():Promise<GoogleClient>;
|
|
46
|
+
|
|
47
|
+
generateAuthUrl(...args):Promise<string>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Sets the credentials
|
|
51
|
+
* @param tokens
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
setCredentials(tokens:object):Promise<void>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Returns the token for the given code
|
|
58
|
+
* @param {string} code
|
|
59
|
+
* @returns {Promise<*>}
|
|
60
|
+
*/
|
|
61
|
+
getToken(code:string):Promise<object>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {string} parentId
|
|
65
|
+
* @param {string[]} pathSegments
|
|
66
|
+
* @param {string} parentPath
|
|
67
|
+
* @returns {Promise<DriveItemInfo[]>|null}
|
|
68
|
+
*/
|
|
69
|
+
getUncachedItemsFromSegments(parentId:string, pathSegments:string[], parentPath:string):Promise<DriveItemInfo[]>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {string} parentId
|
|
73
|
+
* @param {string} pathSegments
|
|
74
|
+
* @param {string} parentPath
|
|
75
|
+
* @returns {Promise<DriveItemInfo[]>|null}
|
|
76
|
+
*/
|
|
77
|
+
getDriveItemsFromSegments(parentId:string, pathSegments:string[], parentPath:string):Promise<DriveItemInfo[]>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* returns the items hierarchy for the given path and root id, starting with the given path.
|
|
81
|
+
* @param {string} parentId
|
|
82
|
+
* @param {string} path
|
|
83
|
+
* @return {DriveItemInfo[]}
|
|
84
|
+
*/
|
|
85
|
+
getDriveItemsFromSegments(parentId:string, path:string):Promise<DriveItemInfo[]>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* returns the items hierarchy for the given item, starting with the given id
|
|
89
|
+
* @param {string} fileId
|
|
90
|
+
* @param {object} roots
|
|
91
|
+
* @returns {Promise<DriveItemInfo[]>}
|
|
92
|
+
*/
|
|
93
|
+
getItemsFromId(fileId:string, roots:object):Promise<DriveItemInfo[]>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns the (cached) item for the given path or {@code null} if the item cannot be found.
|
|
97
|
+
* The item will contains a `invalidate()` method which can be used to remove it from the cache.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} parentId
|
|
100
|
+
* @param {string} path
|
|
101
|
+
* @returns {Promise<DriveItemInfo>}
|
|
102
|
+
*/
|
|
103
|
+
getItemFromPath(parentId:string, path:string):Promise<DriveItemInfo>;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Returns an (uncached) file directly via the google api
|
|
107
|
+
* @param {string} fileId
|
|
108
|
+
* @returns {string} file data
|
|
109
|
+
*/
|
|
110
|
+
getFile(fileId:string):Promise<string>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Fetches the file data from the give path. If the file with the internal id could not be
|
|
114
|
+
* fetched, the item cache is invalidated and the operation is retried. this is to support
|
|
115
|
+
* moved items.
|
|
116
|
+
* @param {string} parentId
|
|
117
|
+
* @param {string} path
|
|
118
|
+
* @param {boolean} noRetry {@code true} to avoid retry
|
|
119
|
+
* @returns {Promise<string>|null} The data of the file or {@code null} if the file does not exist
|
|
120
|
+
*/
|
|
121
|
+
getFileFromPath(parentId:string, path:string, noRetry:boolean):Promise<string>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Returns an (uncached) document directly via the google api
|
|
125
|
+
* @param {string} documentId
|
|
126
|
+
* @returns {object} document
|
|
127
|
+
*/
|
|
128
|
+
getDocument(documentId:string):Promise<object>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Fetches the document from the give path. If the document with the internal id could not be
|
|
132
|
+
* fetched, the item cache is invalidated and the operation is retried. this is to support
|
|
133
|
+
* moved items.
|
|
134
|
+
* @param {string} parentId
|
|
135
|
+
* @param {string} path
|
|
136
|
+
* @param {boolean} noRetry {@code true} to avoid retry
|
|
137
|
+
* @returns {Promise<object>|null} The document or {@code null} if the document does not exist
|
|
138
|
+
*/
|
|
139
|
+
getDocumentFromPath(parentId:string, path:string, noRetry:boolean):Promise<object>;
|
|
140
|
+
}
|
package/src/GoogleClient.js
CHANGED
|
@@ -150,12 +150,12 @@ export class GoogleClient {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
|
-
* @param {string[]} pathSegments
|
|
154
153
|
* @param {string} parentId
|
|
154
|
+
* @param {string[]} pathSegments
|
|
155
155
|
* @param {string} parentPath
|
|
156
156
|
* @returns {Promise<DriveItemInfo[]>|null}
|
|
157
157
|
*/
|
|
158
|
-
async getUncachedItemsFromSegments(
|
|
158
|
+
async getUncachedItemsFromSegments(parentId, pathSegments, parentPath) {
|
|
159
159
|
const { log, drive } = this;
|
|
160
160
|
const name = pathSegments.shift();
|
|
161
161
|
const [baseName, ext] = splitByExtension(name);
|
|
@@ -169,7 +169,7 @@ export class GoogleClient {
|
|
|
169
169
|
// folder if path continues, sheet otherwise
|
|
170
170
|
`and mimeType ${pathSegments.length ? '=' : '!='} 'application/vnd.google-apps.folder'`,
|
|
171
171
|
].join(' '),
|
|
172
|
-
fields: 'nextPageToken, files(id, name, modifiedTime)',
|
|
172
|
+
fields: 'nextPageToken, files(id, name, mimeType, modifiedTime)',
|
|
173
173
|
includeItemsFromAllDrives: true,
|
|
174
174
|
supportsAllDrives: true,
|
|
175
175
|
pageSize: 1000,
|
|
@@ -226,7 +226,7 @@ export class GoogleClient {
|
|
|
226
226
|
const itemPath = `${parentPath}/${sanitizedName}`;
|
|
227
227
|
const children = pathSegments.length
|
|
228
228
|
// eslint-disable-next-line no-use-before-define
|
|
229
|
-
? await this.getDriveItemsFromSegments(
|
|
229
|
+
? await this.getDriveItemsFromSegments(item.id, pathSegments, itemPath)
|
|
230
230
|
: [];
|
|
231
231
|
|
|
232
232
|
if (!children) {
|
|
@@ -236,6 +236,7 @@ export class GoogleClient {
|
|
|
236
236
|
name,
|
|
237
237
|
path: itemPath,
|
|
238
238
|
id: item.id,
|
|
239
|
+
mimeType: item.mimeType,
|
|
239
240
|
}, item);
|
|
240
241
|
|
|
241
242
|
if (children.length) {
|
|
@@ -250,18 +251,18 @@ export class GoogleClient {
|
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
/**
|
|
253
|
-
* @param {string} pathSegments
|
|
254
254
|
* @param {string} parentId
|
|
255
|
+
* @param {string} pathSegments
|
|
255
256
|
* @param {string} parentPath
|
|
256
257
|
* @returns {Promise<DriveItemInfo[]>|null}
|
|
257
258
|
*/
|
|
258
|
-
async getDriveItemsFromSegments(
|
|
259
|
+
async getDriveItemsFromSegments(parentId, pathSegments, parentPath) {
|
|
259
260
|
const key = getCacheKey(parentId, pathSegments);
|
|
260
261
|
let items = lru.get(key);
|
|
261
262
|
if (items) {
|
|
262
263
|
return items;
|
|
263
264
|
}
|
|
264
|
-
items = await this.getUncachedItemsFromSegments(
|
|
265
|
+
items = await this.getUncachedItemsFromSegments(parentId, pathSegments, parentPath);
|
|
265
266
|
if (items) {
|
|
266
267
|
lru.set(key, items);
|
|
267
268
|
// add invalidation function as not-enumerable to keep compatible objects
|
|
@@ -278,20 +279,21 @@ export class GoogleClient {
|
|
|
278
279
|
|
|
279
280
|
/**
|
|
280
281
|
* returns the items hierarchy for the given path and root id, starting with the given path.
|
|
281
|
-
* @param
|
|
282
|
-
* @param
|
|
282
|
+
* @param {string} parentId
|
|
283
|
+
* @param {string} path
|
|
283
284
|
* @return {DriveItemInfo[]}
|
|
284
285
|
*/
|
|
285
|
-
async getItemsFromPath(
|
|
286
|
+
async getItemsFromPath(parentId, path) {
|
|
286
287
|
const segs = createPathSegments(path);
|
|
287
|
-
const result = await this.getDriveItemsFromSegments(
|
|
288
|
+
const result = await this.getDriveItemsFromSegments(parentId, segs, '');
|
|
288
289
|
if (!result) {
|
|
289
290
|
return [];
|
|
290
291
|
}
|
|
291
292
|
return [...result, {
|
|
292
293
|
name: '',
|
|
293
294
|
path: '/',
|
|
294
|
-
id:
|
|
295
|
+
id: parentId,
|
|
296
|
+
mimeType: 'application/vnd.google-apps.folder',
|
|
295
297
|
}];
|
|
296
298
|
}
|
|
297
299
|
|
|
@@ -299,6 +301,7 @@ export class GoogleClient {
|
|
|
299
301
|
* returns the items hierarchy for the given item, starting with the given id
|
|
300
302
|
* @param {string} fileId
|
|
301
303
|
* @param {object} roots
|
|
304
|
+
* @private
|
|
302
305
|
* @returns {Promise<DriveItemInfo[]>}
|
|
303
306
|
*/
|
|
304
307
|
async getItems(fileId, roots) {
|
|
@@ -366,13 +369,13 @@ export class GoogleClient {
|
|
|
366
369
|
* Returns the (cached) item for the given path or {@code null} if the item cannot be found.
|
|
367
370
|
* The item will contains a `invalidate()` method which can be used to remove it from the cache.
|
|
368
371
|
*
|
|
369
|
-
* @param {string}
|
|
372
|
+
* @param {string} parentId
|
|
370
373
|
* @param {string} path
|
|
371
374
|
* @returns {Promise<DriveItemInfo>}
|
|
372
375
|
*/
|
|
373
|
-
async getItemFromPath(
|
|
376
|
+
async getItemFromPath(parentId, path) {
|
|
374
377
|
const segs = createPathSegments(path);
|
|
375
|
-
const items = await this.getDriveItemsFromSegments(
|
|
378
|
+
const items = await this.getDriveItemsFromSegments(parentId, segs, '');
|
|
376
379
|
const item = items?.[0];
|
|
377
380
|
if (!item) {
|
|
378
381
|
return null;
|
|
@@ -400,6 +403,37 @@ export class GoogleClient {
|
|
|
400
403
|
}
|
|
401
404
|
}
|
|
402
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Fetches the file data from the give path. If the file with the internal id could not be
|
|
408
|
+
* fetched, the item cache is invalidated and the operation is retried. this is to support
|
|
409
|
+
* moved items.
|
|
410
|
+
* @param {string} parentId
|
|
411
|
+
* @param {string} path
|
|
412
|
+
* @param {boolean} noRetry {@code true} to avoid retry
|
|
413
|
+
* @returns {Promise<string>|null} The data of the file or {@code null} if the file does not exist
|
|
414
|
+
*/
|
|
415
|
+
async getFileFromPath(parentId, path, noRetry) {
|
|
416
|
+
const item = await this.getItemFromPath(parentId, path);
|
|
417
|
+
if (!item) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
try {
|
|
421
|
+
// noinspection ES6RedundantAwait (need to catch exception)
|
|
422
|
+
return await this.getFile(item.id);
|
|
423
|
+
} catch (e) {
|
|
424
|
+
if (e.statusCode === 404) {
|
|
425
|
+
if (noRetry) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
this.log.info(`file ${item.id} does not exist - invalidating cache and retry`);
|
|
429
|
+
item.invalidate();
|
|
430
|
+
return this.getFileFromPath(parentId, path, true);
|
|
431
|
+
} else {
|
|
432
|
+
throw e;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
403
437
|
/**
|
|
404
438
|
* Returns an (uncached) document directly via the google api
|
|
405
439
|
* @param {string} documentId
|
|
@@ -420,4 +454,35 @@ export class GoogleClient {
|
|
|
420
454
|
throw e;
|
|
421
455
|
}
|
|
422
456
|
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Fetches the document from the give path. If the document with the internal id could not be
|
|
460
|
+
* fetched, the item cache is invalidated and the operation is retried. this is to support
|
|
461
|
+
* moved items.
|
|
462
|
+
* @param {string} parentId
|
|
463
|
+
* @param {string} path
|
|
464
|
+
* @param {boolean} noRetry {@code true} to avoid retry
|
|
465
|
+
* @returns {Promise<object>|null} The document or {@code null} if the document does not exist
|
|
466
|
+
*/
|
|
467
|
+
async getDocumentFromPath(parentId, path, noRetry) {
|
|
468
|
+
const item = await this.getItemFromPath(parentId, path);
|
|
469
|
+
if (!item) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
try {
|
|
473
|
+
// noinspection ES6RedundantAwait (need to catch exception)
|
|
474
|
+
return await this.getDocument(item.id);
|
|
475
|
+
} catch (e) {
|
|
476
|
+
if (e.statusCode === 404) {
|
|
477
|
+
if (noRetry) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
this.log.info(`document ${item.id} does not exist - invalidating cache and retry`);
|
|
481
|
+
item.invalidate();
|
|
482
|
+
return this.getDocumentFromPath(parentId, path, true);
|
|
483
|
+
} else {
|
|
484
|
+
throw e;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
423
488
|
}
|