Zero Data Wrap
Unified JavaScript API for Fission + remoteStorage.
Yes, it's long and verbose and how I do things generally, but ideally your final code looks like this:
// write `{"id":"batmobile","clean":true,"washed":"…"}` to /bravo/cars/batmobile.jsonawaitapi.alfa.cars.wash({id: 'batmobile',});constapi=awaitzerodatawrap.ZDRWrap({// include then pass directlyZDRParamLibrary: RemoteStorage,// or webnative// read/write permissionsZDRParamScopes: [{// code-level identifierZDRScopeKey: 'alfa',// top-level storage directoryZDRScopeDirectory: 'bravo',}],});// write `{"foo":"bar"}` to /bravo/charlie.jsonawaitapi.alfa.ZDRStorageWriteObject('charlie.json',{foo: 'bar',});| param | type | notes |
|---|---|---|
| ZDRParamLibrary Required | pass RemoteStorage or webnative or an object conforming to ZDRClient | |
| ZDRParamScopes Required | array of ZDRScope objects | |
| ZDRParamDispatchError | function | called on network or sync errors |
| ZDRParamDispatchConnected | function | called if linked to a cloud account |
| ZDRParamDispatchOnline | function | called when network is online |
| ZDRParamDispatchOffline | function | called when network is offline |
| param | type | notes |
|---|---|---|
| ZDRScopeKey Required | string, non-empty, trimmed | convenience accessor for code only |
| ZDRScopeDirectory Required | string, non-empty, trimmed, no slashes | top-level directory for claiming read/write access |
| ZDRScopeCreatorDirectory | string, non-empty, trimmed | if Fission, sets permissions.app instead of permissions.fs |
| ZDRScopeSchemas | array of ZDRSchema objects | defines model helpers |
| ZDRScopeIsPublic | boolean | use public directory on read/write |
Call JSON.stringify; write to storage.
Returns input object.
mimetype used by remoteStorage.
Write to storage.
Returns input.
Read from storage; call JSON.parse.
Returns object.
Read from storage.
Returns data.
Read from storage in path directory (non-recursive); group by path.
Returns key/value object.
Fetch paths (non-recursive).
Returns array of paths.
Fetch paths recursively.
Returns flat array of paths.
Delete from storage.
Returns null.
Delete folder and subcontents recursively from storage.
Returns input.
Start authorization process corresponding to ZDRParamLibrary.
Returns undefined.
Retry authorization process in case of expiry or denied access.
Returns undefined.
Log out.
Returns undefined.
constapi=zerodatawrap.ZDRWrap({// …ZDRParamScopes: [{// …// map schemas to pathsZDRScopeSchemas: [{// code-level identifierZDRSchemaKey: 'cars',// path for a given objectZDRSchemaPath(object){return`cars/${object.id}.json`;},// object information for a given pathZDRSchemaStub(path){return{id: path.split('/').pop().split('.json').shift(),};},}],// …}],// …});// write `{"id":"batmobile"}` to /bravo/cars/batmobile.jsonawaitapi.alfa.cars.ZDRModelWriteObject({id: 'batmobile',});| param | type | notes |
|---|---|---|
| ZDRSchemaKey Required | string, non-empty, trimmed | convenience accessor for code only |
| ZDRSchemaPath Required | function | constructs the path for a given object |
| ZDRSchemaStub Required | function | constructs object information for a given path, used for filtering paths in recursion and routing sync events |
| ZDRSchemaMethods | object | defines methods to be accessed from the api interface (bound to this) |
| ZDRSchemaDispatchValidate | function | called before ZDRModelWriteObject |
| ZDRSchemaDispatchSyncCreate | function | called on remote create remoteStorage only |
| ZDRSchemaDispatchSyncUpdate | function | called on remote update remoteStorage only |
| ZDRSchemaDispatchSyncDelete | function | called on remote delete remoteStorage only |
| ZDRSchemaDispatchSyncConflict | function | called on remote conflict remoteStorage only Note: this passes the remoteStorage change event directly |
constapi=zerodatawrap.ZDRWrap({// …ZDRParamScopes: [{// …ZDRScopeSchemas: [{// …// truthy values cause a promise rejectionZDRSchemaDispatchValidate(object){if(typeofobject.id!=='string'){return{not: 'so fast',};}},// …}],// …}],// …});// rejectstry{awaitapi.alfa.cars.ZDRModelWriteObject({id: 123,});}catch(truthy){console.log(truthy.not);// so fast}constapi=zerodatawrap.ZDRWrap({// …ZDRParamScopes: [{// …ZDRScopeSchemas: [{// …// logic to be done on saveZDRSchemaMethods: {clean(car){returnthis.alfa.cars.ZDRModelWriteObject(Object.assign(car,{clean: true,washed: newDate(),}));},},// …}],// …}],// …});// write `{"id":"batmobile","clean":true,"washed":"…"}` to /bravo/cars/batmobile.jsonawaitapi.alfa.cars.clean({id: 'batmobile',});constapi=zerodatawrap.ZDRWrap({// …ZDRParamScopes: [{// …ZDRScopeSchemas: [{// …// update the interface for remote changesZDRSchemaDispatchSyncCreate(object){console.log('create',object);},ZDRSchemaDispatchSyncUpdate(object){console.log('update',object);},ZDRSchemaDispatchSyncDelete(object){console.log('delete',object);},// handle conflictZDRSchemaDispatchSyncConflict(event){console.log('conflict',event);},// …}],// …}],// …});Returns object path via ZDRSchemaPath.
Validate with ZDRSchemaDispatchValidate, reject if truthy; write object to path from ZDRModelPath.
Returns input.
Read all objects recursively (where paths conform to logic in ZDRSchema).
Returns array of objects.
Delete object from storage.
Returns input.
When supporting multiple protocols, the library can help track which one was selected.
constapi=awaitzerodatawrap.ZDRWrap({ZDRParamLibrary: (function(){// get the selected protocol, default to `ZDRProtocolCustom`constselected=zerodatawrap.ZDRPreferenceProtocol(zerodatawrap.ZDRProtocolCustom());if(selected===zerodatawrap.ZDRProtocolRemoteStorage()){returnRemoteStorage;}return{ZDRClientWriteFile(path,data){console.log('custom protocol write',[...arguments]);},ZDRClientReadFile(path){console.log('custom protocol read',[...arguments]);},ZDRClientListObjects(path){console.log('custom protocol list objects',[...arguments]);},ZDRClientDelete(path){console.log('custom protocol delete',[...arguments]);},};})(),// …});Move from one protocol to another by generating APIs from preferences:
if(zerodatawrap.ZDRPreferenceProtocolMigrate()){// generate apis from protocolconstwrap=function(protocol){returnzerodatawrap.ZDRWrap({// …});};constsource=awaitwrap(zerodatawrap.ZDRPreferenceProtocolMigrate());constdestination=awaitwrap(zerodatawrap.ZDRPreferenceProtocol());// get all objects (this is simplified, should be recursive)awaitPromise.all(Object.entries(awaitsource.App.ZDRStorageListingObjects('')).map(asyncfunction([key,value]){// write to destinationawaitdestination.App.ZDRStorageWriteObject(key,value);// delete from sourceawaitsource.App.ZDRStorageDeleteFile(key);}));// clear migrate preference to avoid repeatingzerodatawrap.ZDRPreferenceProtocolMigrateClear();// call disconnect to do any other cleanupsource.ZDRCloudDisconnect();};| function | notes |
|---|---|
| ZDRClientWriteFile Required | called by ZDRStorageWriteFile |
| ZDRClientReadFile Required | called by ZDRStorageReadFile |
| ZDRClientListObjects Required | called by ZDRStorageListingObjects |
| ZDRClientDelete Required | called by ZDRStorageDeleteFile |
| ZDRClientPrepare | called before returning wrapper |
| ZDRClientConnect | called by ZDRCloudConnect |
| ZDRClientReconnect | called by ZDRCloudReconnect |
| ZDRClientDisconnect | called by ZDRCloudDisconnect |
Returns string.
Returns string.
Returns string.
Stores input as the protocol preference if none is set.
Returns the protocol preference.
Clears the protocol preference.
Returns null.
Sets the protocol preference as 'to be migrated' if connecting to a different protocol.
Returns input.
Returns the 'to be migrated' protocol if set.
Clears the 'to be migrated' protocol.
Returns input object.
Help me keep creating projects that are public, accessible for free, and open-source.
The code is released under a Hippocratic License, modified to exclude its use for surveillance capitalism and also to require large for-profit entities to purchase a paid license.