Post on 15-Jan-2015
description
javaScript/jQuery API for ScriptDBGoogle Apps ScriptDB from a webapp
what is this API for?● Allow maintenance and query Google Apps
Script ScriptDB directly from a client webapp● Share data in real time between Google
Docs, webapps and Excel (using VBA API for Excel)
● a free noSQL database for javascript webapps and Excel
COMPONENTS
scriptdb API
Your code Your GAS
webapp Handler (s)
Your code
Your client code
Your ScriptDB dispatcher
GAS Library API
Your codeYour
codeMultiple ScriptDB
cookie
rest
scripdb api credentials
simple noSql
the same handlers are used by the VBA API
access controlUser and Access
type credentials
cookie
● Can be used to control access operations by endpoint
● Only needs to be stored one time new cScriptDbCom().setScriptCredentials( { endPoint : gasHandlerEndPoints.scriptdbrequesthandler, restAPIKey : 'xliberationApp', scopeEntry : 'rest', credentialsEntry: 'dbTest', clientKey:'xliberation', library: 'dbTest', needDebug: false, needOauth: false } );
your entry/ your scope
comparison with parse.com and VBA scriptDB API
cParseCom VBA API
cScriptDBCom VBA API
cParseCom GAS API
parse.com cloud based noSQL database
VBA and GAS Main Apps are virtually the same code irrespective of the whether parse
or scriptdb is used
GAS scriptDB cloud based noSQL database
GAS scriptDB webApp and API libraryparse.com restAPI handler
cScriptDBCom javascript API
VBA and javascript clients have similar code and share the same GAS handlers and
databases
note on examplesAll the examples that follow put their results in a page element using this function/* display contents of some object at given element
* @param {object} control some object
* @param {string} id the id of the element
* @return {null}
*/
function renderScriptDb(control,id) {
$(id).text(JSON.stringify(control));
}
optimization and batching● The gas library api will batch all requests it can.● Batching is done automatically by the API ● Operations are asynchronous and orchestrated by
promises
getScriptDb("VBAParseCustomers","dbTest").getCount() .done (function (data,cob) { renderScriptDb(data.count,'#countcopycustomers'); }) .fail(function (data,cob) { renderScriptDb(JSON.stringify(data),'#countcopycustomers'); });
example - create object (s)Data is stored in silos within one or more ScriptDb
one objectdbTarget.createObject(data) .done ( function(data) { .. do something good .. }) .fail ( function (error) { .. do something bad.. });
multiple objectsdb.createObjects([some objects...]) .done( function (data) {...it worked..}) .fail( function (error) {...it failed..});
example - do a queryQueries are by example, and can include limit/skip
var dbCustomer = getScriptDb("VBAParseCustomers","dbTest"); dbCustomer.getObjectsByQuery({country:"United States"}) .done (function (data,cob) { renderScriptDb(data.results,'#countryquery'); })
example - update objectsAll matching objects are updated to the given value. New fields are created, existing fields are replaced
getScriptDb("testClass","dbTest").updateObjects({town:’chicago’},null,{state:'IL’'}) .done(function(data){ renderScriptDb(data,'#bitupdate'); }) .fail(function(error){ renderScriptDb(error,'#bitupdate'); });
example - count matching objectsCount operations can have optional queries
getScriptDb("VBAParseCustomers",entry).getCount({country:"United States"})
.done (function (data,cob) {
renderScriptDb(data.count,'#countquery');
})
.fail(function (error,cob) {
renderScriptDb(fSON.stringify(error),'#countquery');
});
example - get object by idEach object is assigned a unique Id returned by queries
getScriptDb("VBAParseCustomers",entry).getObjectById(objId)
.done (function (data,cob) {
renderScriptDb(data.results,'#id');
})
.fail(function (error,cob) {
renderScriptDb(JSON.stringify(error),'#id');
});
example - delete objectsAll objects matching the query are deleted
dbTarget.deleteObjects({customerid:1}) .done (function (data,cob) {
renderScriptDb(data.results,'#delete');
})
.fail(function (error,cob) {
renderScriptDb(JSON.stringify(error),'#delete');
});
limits and skippingQueries are subject to limits, so you can work multiple passes for big queries using skip/limit. A recursive convenience method is provided to use, and show you how to do it (eg. db.getAllMatchingQueries({state:’IL’}) will take care of this automatically as below - but watch out for memory usage) self.getAllMatchingQueries = function (queryJob, queryParameters,list, defer) { list = list || []; defer = defer || $.Deferred(); var jobSkip = {skip:list.length}; self.getObjectsByQuery (queryJob, self.mergeParameters(queryParameters, jobSkip)) .done (function (data,defers) { if (!data.results.length) { defer.resolve(list); } else { for (var i = 0 ; i < data.results.length; i++) { list.push(data.results[i]); } self.getAllMatchingQueries(queryJob,queryParameters,list,defer); } }) .fail (function (error,defers){ defer.reject (error); }); return defer.promise(); };
this is automatically handled for update and delete
notes on finalFlush()Because POST operations are batched, you need to call finalFlush() at some point for each scriptdbcom instance. This clears any batch queues and resolves any outstanding promises. It can be called as often and whenever you like, but should be called at least once if there have been any POST type operations (CREATE,UPDATE,DELETE), following the last one. Note that POST operations are not resolved until they have been successfully flushed from the Batch Queue.
finalFlush() also returns a promise for when all its work is complete.
dbTarget.finalFlush().then( function (data) { … do something , its all over… } );
dates and timesThese are handled the same way as parse.com "date":{ "__type":"Date", "iso":"2013-08-22T00:00:00.000Z" }
silos and parse classes● A Silo is like a parse Class. For 2D data it can be
considered like a table.● Multiple classes can be held in the same scriptDB.● scriptDB siloing is handled automatically● A seperate cScriptDbCom instance should be
instantiated for each class being worked on
multiple scriptDB● The scriptDB dispatcher handled which actual scriptDB
to write to.● Multiple DBs can be used by referencing multiple
libraries in the scriptDB dispatcher.● Library names will be signalled to the dispatcher if they
are in the setup for this entry
restricting operationsYou may want to allow a different kind of access to certain users.
● provide a different URL or use the app keys to signal some restricted access , and include something like this in the doGet() and doPost() functions
var whatsAllowed = ['query','count','getbyid'];● setting that configuration up under a different entry
new cScriptDbCom().setScriptCredentials( { endPoint : gasHandlerEndPoints.scriptdbrequesthandler, restAPIKey : 'xliberationApp', scopeEntry : 'rest', credentialsEntry: 'dbTest', clientKey:'xliberation', library: 'dbTest', needDebug: false, needOauth: false } );
accessing from other apps● The scriptDB GAS handler API can be
accessed using any rest query mechanism. ● The VBA API and javaScript just manages
the conversation with the scriptDB GAS handler
● Examples of other languages will be on Excel Liberation at a later date.
public facing scriptdbOAuth2 support is not yet released for the JavaScript version (it is with the VBA one). This is because Google Apps Script doesn’t yet support CORS (cross origin resource sharing) for javaScript clients.
A temporary workaround for access control is described here.
further detailAll this code is downloadable or copyable from Google Apps Script Libraries.For more information see Excel Liberation