search-string-for-google-drive
Version:
helper function to create query string for drive.files.list when using Google Drive API v3
143 lines (125 loc) • 4.15 kB
JavaScript
/*
* search-string-for-google-drive -- creates search string for Drive API v3 drive.files.list "q" parameter
* This is a helper function for creating the "q" query string described in https://developers.google.com/drive/v3/web/search-parameters
*
* Copyright 2017-2018 Paul Brewer, Economic and Financial Technology Consulting LLC <drpaulbrewer@eaftc.com>
* This file is open source software. License: The MIT License
*
*/
;
const folderMimeType = 'application/vnd.google-apps.folder';
function escape(s) {
return "'" + String(s).replace(/'/g, "\\'") + "'";
}
// used capital Q here to avoid confusion with search string q defined later
const Q = {
"string": function(op, combiner) {
return function(k, v) {
if (Array.isArray(v)) {
return '( ' +
v.map(function(eachv) {
return (k + ' ' + op + ' ' + escape(eachv));
}).join(' ' + combiner + ' ') +
' )';
}
return k + ' ' + op + ' ' + escape(v);
};
},
"boolean": function() {
return function(k, v) {
if ((typeof(v) === 'string') && (v.charAt(0) === "F" || v.charAt(0) === "f" || v === "0"))
v = false;
return k + ' = ' + (!!v);
};
},
"collection": function(combiner) {
return function(k, v) {
if (Array.isArray(v)) {
return '( ' +
v.map(function(eachv) {
return escape(eachv) + ' in ' + k;
}).join(' ' + combiner + ' ') +
' )';
}
return escape(v) + ' in ' + k;
};
},
"hash": function() {
return function(k, v) {
return Object.keys(v).map(
function(hk) {
return k + ' has { key=' + escape(hk) + ' and value=' + escape(v[hk]) + ' }';
}).join(' and ');
};
},
"isFolder": function() {
return function(k, v) {
if ((typeof(v) === 'string') && (v.charAt(0) === "F" || v.charAt(0) === "f" || v === "0"))
v = false;
const sep = (v) ? ' = ' : ' != ';
return 'mimeType' + sep + escape(folderMimeType);
};
}
};
const handlers = {
name: Q.string('=', 'or'),
fullText: Q.string('contains', 'and'),
mimeType: Q.string('=', 'or'),
trashed: Q.boolean(),
starred: Q.boolean(),
parents: Q.collection('or'),
owners: Q.collection('or'),
writers: Q.collection('or'),
readers: Q.collection('or'),
sharedWithMe: Q.boolean(),
properties: Q.hash('and'),
appProperties: Q.hash('and'),
visibility: Q.string('=', 'or'),
isFolder: Q.isFolder()
};
function ssgd(spec, matchAll) {
const queries = (
Object.keys(spec)
.filter(function(k) {
return (spec[k] !== undefined) && (spec[k] !== null);
})
.map(function(k) {
if (typeof(handlers[k]) === 'function')
return (handlers[k])(k, spec[k]);
// fix singular<-->plural
const lastChar = k.charAt(k.length - 1);
const kPlural = (lastChar !== 's') ? k + 's' : false;
const kSingular = (lastChar === 's') ? k.substr(0, k.length - 1) : false;
if (kPlural && (typeof(handlers[kPlural]) === 'function'))
return (handlers[kPlural])(kPlural, spec[k]);
if (kSingular && (typeof(handlers[kSingular]) === 'function'))
return (handlers[kSingular])(kSingular, spec[k]);
throw new Error("search key " + escape(k) + " unsupported");
})
);
const q = queries.join(' and ');
if ((q.length === 0) && (matchAll))
return q;
if (q.length > 0)
return q;
throw new Error("blank, match-all, query prohibited by configuration at search-string-for-google-drive");
}
ssgd.supported = function() {
return Object.keys(handlers);
};
// someobj.hasOwnProperty(prop) is replaced with
// Object.prototype.hasOwnProperty.call(someobj,prop)
// see https://eslint.org/docs/rules/no-prototype-builtins
ssgd.isSupported = function(k) {
return (k in handlers) && (Object.prototype.hasOwnProperty.call(handlers,k));
};
ssgd.extract = function(slop) {
const spec = {};
Object.keys(handlers).forEach(function(k) {
if ((k in slop) && (Object.prototype.hasOwnProperty.call(slop,k))) {
spec[k] = slop[k];
}
});
return spec;
};
module.exports = ssgd;