ok, these are good points. let's try to break it down.
first of all, we need to have clear what the library does, and what it
exposes, then per point we can see what should be configurable and
what not:
- widget:
- displayWidget - we probably want to offer two choices: just
indicate which div should display the widget, or get direct access to
the session so you can design your own 'connect your remote storage'
widget
- module management:
- defineModule and loadModule - these are quite basic; maybe we want
to compile versions of the library that have modules loaded in by
default (right now 'tasks-0.1' and 'documents-0.1' are both included
by default). but that's an option of the build script, not of the
library at runtime.
- webfinger+hardcoded discovery:
- i don't think it's desirable that different apps respond
differently to certain user addresses, so i don't think there should
be any configurable parts here. Maybe the xhr timeout should be
controlled in response to the device, but that's not app-specific, so
if that's necessary, the library should do that itself. one exception
i can think of is during testing, you might want to 'spike' the
discovery with a test account, but then you might as well just spike
the session so that you're already logged in with that test account
(and don't need to do the discovery)
- wireClient:
- the wireClient takes care of abstracting all the difference
between webdav, couchdb and getputdelete. This is i think the part we
agree most on should be in the library and hidden from view. of the
modules and the apps.
- what to sync explicitly:
- the module can tell the baseClient which directories or items
should be kept in sync proactively. The baseClient will start fetching
data into the cache (localStorage) so that it's ready for synchronous
access. we can make this control as detailed as we want, since we are
only exposing it to modules, not to apps.
- what to cache implicitly:
- whenever the module gets or sets some data, by default it is added
to the cache implicitly. we can of course make this optional with an
extra parameter.
- what to expunge from cache:
- i was thinking by default we want to expunge implicitly cached
data on a LeastRecentlyUsed basis (maybe influenced by item size), and
fire an error event if the cache (localStorage) is full with
explicitly cached data.
- when to pull:
- i was thinking by default once a minute while the window has
focus, and once every 10 minutes when not. but we can of course make
this as configurable as we want, per key, and separately for in-focus
and off-focus.
- when to push:
- there are 3 caching levels: window (in js globally scoped memory),
device (localStorage), cloud (remoteStorage if connected). Pushing
from memory to device is instant (actually, even synchronous) right
now. I was thinking we probably want to do this once a second by
default, but we can allow the module to set this per path if we want.
pushing from device cache to server i was thinking of once every 10
seconds by default whenever there is something to push, but again, we
can make this configurable per path
- read/write access to the user's and other users' storage while
totally bypassing all caching layers:
- the way i had it in my head right now, you can do this for read by
using the asynchronous get function and specifying the dont-cache
option. For writing it's a bit more complicated, since all writes are
queued. but we can allow a module to specify 'expungeAfterWrite', that
actually sounds useful. but as you say, it would be super easy to also
expose an asynchronous non-cached write.
- json-ld and mimetypes:
- this is still under construction, but i want the baseClient to
automatically add @context fields into data objects, pointing to
per-module data format specs that are automatically published using a
sort of docgen/docco-like system. i think it's important that modules
document how they store data, and i think we don't want to have any
modules with undocumented data formats. That's why right now the
baseClient exposes storeObject and storeObject and storeMedia. But of
course if you don't want to use these things, just stringify your
objects in the module, and then use storeMedia with mime-type
application/json or even application/octet-stream whenever you want
raw access to the wire data.
- directory listings:
- it's quite tricky how directory listings work on webdav, couchdb
and getputdelete, and i haven't even started properly coding all of
that. right now, what the baseClient exposes is only the cached data
(which includes directory listings with modified-times), and it will
tell you if there are pending outgoing changes on a certain path, and
how long ago the last check for incoming changes took place on a
certain path (this is not implemented yet). What i don't think we want
to expose to the module is access to tinkering with modified times and
directory listings. i think those should "just work", or if someone
has a use case for tinkering with them (hidden files? unsynchronized
files?) then we should maybe look at how we can add that functionality
generically.
- other couchdb and webdav functionality:
- afaik we're exposing most of webdav's functionality, but couchdb
has some specific things that the other api's don't have, like
server-side map-reduce and bulk updates. i think where and when these
are useful, the baseClient should for an abstraction layer for those
with fallbacks so that each functionality always works either for
everybody or for nobody. i can think of no case where exposing this to
the modules would make sense.
- exposing direct access to the wire data:
this is basically covered in the 'json-ld and mimetypes' and
'directory listings' points above.
i think what you're mainly after is asynchronous read and asynchronous
write without caching, right? I'll make sure i'll add both of those to
the baseClient. about the caching strategy for things you do cache,
i'll also make that overridable. and then maybe the ability to
override the widget design would be the third important thing? let me
know if you need anything else, and i'll simply add it.
again, this is talking about functionality exposed from the baseClient
to the modules, each module makes its own decisions about what it
exposes to apps. But my idea is that when you implement for instance
SharedStuff from scratch, 50% of your code would be writing the
reusable 'stuff' module, and 50% would be the actual app, which would
by then be only a presentation layer on top of the reusable module.
does that make sense?
cheers,
Michiel