Skip to content

Commit

Permalink
add support for options.recent to drive.x.searcher;
Browse files Browse the repository at this point in the history
use recent instead of unique in driveStepRight and path resolution
  • Loading branch information
DrPaulBrewer committed Feb 20, 2020
1 parent cdafcad commit e5e4029
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 36 deletions.
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Initialize googleapi's Google Drive[tm] nodejs client, decorated with some useful 3rd party extensions.

## new in v5.4.0
* path traversal now uses search option 'recent' and will find the most recent file
* it is better behaved in the case of multiple files with the same name
* issues can arise if a user creates a file with the same name as an existing app folder

## new in v5.3.0
* tested against googleapis@47.0.0

Expand Down Expand Up @@ -149,7 +154,7 @@ To replace an existing file, set `clobber:true`, otherwise it may throw a `Boom.
Post-upload checksums reported by Google Drive API are used to guarantee fidelity for **binary** file uploads. A binary file
is any non-text file. The md5 checksum computed from the file stream is reported as `ourMD5` in the `newFileMetaData`
and the md5 checksum computed by Google is reported as `md5Checksum` in the `newFileMetaData`. When there is a mismatch
on a binary file the code will throw `Boom.badImplementation`, which you can catch, and any recovery should assume that Google
on a binary file the code will throw `Boom.badImplementation`, which you can catch, and any recovery should check if Google
Drive retains the corrupted upload.


Expand Down Expand Up @@ -231,16 +236,14 @@ where `{...}` is your code that needs `fileMetaData`. The resolved data looks l
size: 21398 // size in Drive, may not equal number of bytes in file
}

Additionally, `findPath` can fail with a rejected Promise. `npm:boom` is used for errors our code throws. You can also
get errors thrown by the googleapis code.
Additionally, `findPath` can fail with a rejected Promise.
`npm:boom` is used for errors our code throws.
You can also get errors thrown by the googleapis code.

To catch file not found:

.catch( (e)=>{ if (e.isBoom && e.typeof===Boom.notFound) return your_file_not_found_handler(e); throw e; } )

To catch two or more files with same name:

.catch( (e)=>{ if (e.isBoom && e.typeof===Boom.expectationFailed) return your_duplicate_file_handler(e); throw e; })

### searching folders with drive.x.searcher

Expand Down Expand Up @@ -286,7 +289,12 @@ You can restrict mimeType or require a unique (single) file in the searcher para
.then(({ files })=>{...})
)

`unique:true` sets `limit:2` so is not in fact unique but instead returns 2 files quickly. You can enforce uniqueness, thowing Boom errors, by calling
`recent:true` sets `limit:1` and `orderby:'modifiedTime desc'` so that the most
recently created/modified file will be returned.

`unique:true` sets `limit:2` so is not in fact unique but instead returns 2 files quickly.

You can enforce uniqueness, thowing Boom errors, by calling
`drive.x.checkSearch` on the search results. Successful searches are passed to the next `then()` and searches with missing files or duplicates
throw errors. (see `drive.x.findPath` above for a descrption of these Boom errors and how to catch them).

Expand Down
12 changes: 9 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,14 @@ function extensions(drive, request, rootFolderId, spaces, salt) {
function driveSearcher(options) {
let limit = (options.limit || 1000);
let fields = options.fields || 'id,name,mimeType,modifiedTime,size,parents';
let orderBy = options.orderby || 'folder,name,modifiedTime desc';
const unique = options.unique;
if (unique) limit = 2;
const recent = options.recent;
if (recent) {
limit = 1;
orderBy = 'modifiedTime desc';
}
const allowMatchAllFiles = options.allowMatchAllFiles;
const searchTerms = ssgd.extract(options);

Expand All @@ -96,7 +102,7 @@ function extensions(drive, request, rootFolderId, spaces, salt) {
q: searchString,
pageSize: limit,
maxResults: limit,
orderBy: "folder,name,modifiedTime desc",
orderBy,
fields: `files(${fields})`
};

Expand All @@ -107,7 +113,7 @@ function extensions(drive, request, rootFolderId, spaces, salt) {
// add isFolder boolean property to files, comparing mimeType to the Google Drive folder mimeType
if (Array.isArray(resp.files))
resp.files.forEach(addIsFolder);
const result = { parent, name, searchTerms, limit, unique, isSearchResult: true, files: resp.files };
const result = { parent, name, searchTerms, limit, unique, recent, isSearchResult: true, files: resp.files };
return result;
};
}
Expand Down Expand Up @@ -167,7 +173,7 @@ function extensions(drive, request, rootFolderId, spaces, salt) {
x.getFolderId = getFolderId;

function driveStepRight() {
const search = driveSearcher({ unique: true });
const search = driveSearcher({ recent: true });
return async function (folderIdOrObject, name) {
return (getFolderId(folderIdOrObject)
.then((parentId) => (search(parentId, name)))
Expand Down
2 changes: 1 addition & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('decorated-google-drive:', function () {
});
});
});
describe(' drive.x.appDataFolder.upload2: upload a string to appDataFolder ', function () {
describe(' drive.x.appDataFolder.upload2: upload a string ...-1-2-3 to appDataFolder ', function () {
let uploadResult;
before(function () {
return drive.x.appDataFolder.upload2({
Expand Down
50 changes: 25 additions & 25 deletions testResults.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@
✓ drive should not be undefined
✓ drive.x should be an object
drive.x.aboutMe
✓ should return the test users email address (180ms)
✓ should return a storageQuota object with properties limit, usage (169ms)
✓ drive.about.get still works, as well, and the outputs match (135ms)
✓ should return the test users email address (403ms)
✓ should return a storageQuota object with properties limit, usage (161ms)
✓ drive.about.get still works, as well, and the outputs match (175ms)
drive.x.hexid
✓ should return a 64 char hex id (134ms)
✓ should consistently return the same 64 char hex when called 3 times (143ms)
drive.x.appDataFolder.upload2: upload a string to appDataFolder
✓ should return a 64 char hex id (212ms)
✓ should consistently return the same 64 char hex when called 3 times (201ms)
drive.x.appDataFolder.upload2: upload a string ...-1-2-3 to appDataFolder
✓ uploading the string to appDataFolder file myaccount should resolve with expected file metadata
✓ drive.x.appDataFolder.searcher should report there is exactly one myaccount file in the folder and it should match upload file id
✓ drive.x.appDataFolder.contents should resolve to contents Hello-World-Test-1-2-3
drive.x.upload2: upload a file README.md to Drive folder /path/to/test/Files
✓ uploading the README.md file to /path/to/test/Files/README.md should resolve with expected file metadata
✓ the parents[0] folder should have the name 'Files' (145ms)
✓ searching the parents[0] folder for README.md find a file with matching id (217ms)
✓ the parents[0] folder should have the name 'Files' (158ms)
✓ searching the parents[0] folder for README.md find a file with matching id (267ms)
after drive.x.upload2
✓ searching root for anything should yield folder 'path' with .isFolder===true (195ms)
✓ searching root for folders should yield folder 'path' with .isFolder===true (275ms)
✓ searching root for non-folders should be empty (1951ms)
✓ searching all folders for any non-trashed file should be non-empty and include file README.md in results (278ms)
✓ searching all folders or a file with appProperties: { 'role': 'documentation' } should be empty (175ms)
✓ checking existence of /path/to/test/Files/README.md with drive.x.findPath should yield expected file metadata (1085ms)
✓ checking existence of /path/to/test should yield expected folder metadata (790ms)
✓ checking existence on wrong path should throw Boom.notfound (182ms)
✓ downloading content with drive.x.download should yield contents string including 'License: MIT' (1262ms)
✓ updating README.md appProperties to {'role': 'documentation'} should succeed (1719ms)
✓ searching all folders or a file with appProperties: { 'role': 'documentation' } should find README.md (215ms)
✓ drive.x.upload2 uploading the file again with {clobber:false} will throw Boom.conflict error because file already exists (1327ms)
✓ searching root for anything should yield folder 'path' with .isFolder===true (215ms)
✓ searching root for folders should yield folder 'path' with .isFolder===true (267ms)
✓ searching root for non-folders should be empty (221ms)
✓ searching all folders for any non-trashed file should be non-empty and include file README.md in results (243ms)
✓ searching all folders or a file with appProperties: { 'role': 'documentation' } should be empty (153ms)
✓ checking existence of /path/to/test/Files/README.md with drive.x.findPath should yield expected file metadata (1074ms)
✓ checking existence of /path/to/test should yield expected folder metadata (1205ms)
✓ checking existence on wrong path should throw Boom.notfound (216ms)
✓ downloading content with drive.x.download should yield contents string including 'License: MIT' (1189ms)
✓ updating README.md appProperties to {'role': 'documentation'} should succeed (1820ms)
✓ searching all folders or a file with appProperties: { 'role': 'documentation' } should find README.md (207ms)
✓ drive.x.upload2 uploading the file again with {clobber:false} will throw Boom.conflict error because file already exists (987ms)
drive.x.upload2: upload test/test.zip to Drive folder /path/to/test/Files
✓ uploading the test.zip file to /path/to/test/Files/test.zip should resolve with expected file metadata and md5 match
create folder /path/to/test2
Expand All @@ -46,12 +46,12 @@
use folderId of /path/to/test2 to upload test.zip
✓ uploading the test.zip file to /path/to/test2/test.zip should resolve with expected file metadata and md5 match
cleanup via drive.x.janitor
✓ janitor hopefully deletes the README.md file(s) OK and resolves correctly (1518ms)
✓ drive.x.findPath will throw Boom.notFound if the file was successfully deleted (1164ms)
✓ janitor will throw an error if told to delete an invalid file (93ms)
✓ janitor hopefully deletes the README.md file(s) OK and resolves correctly (1695ms)
✓ drive.x.findPath will throw Boom.notFound if the file was successfully deleted (974ms)
✓ janitor will throw an error if told to delete an invalid file (173ms)
✓ janitor should not throw an error if given an empty filelist
✓ final cleanup: delete the path folder and check non-existence (923ms)
✓ final cleanup: delete the path folder and check non-existence (885ms)


40 passing (25s)
40 passing (30s)

0 comments on commit e5e4029

Please sign in to comment.