API reference

This doc reflects only CloudWall API. To make apps work you also need jQuery.my API and, possibly, full system manifest list to reuse system components. To search this doc just press Ctrl-F or ⌘-F.

Quick start

To create your own application or even doc editor without long reading:

1. Add new local DB for experiments
2. Click on DB name and then on App editor
3. Open in new tabs: API reference, jQuery.my readme, and any demo app from System DB. 

If you going to create an editor — open ‹ToDo Editor› in system DB, if just an app — open ‹Hello world demo› in Demo & Docs. Ok, thats all.

General principles

Everything async is a promise 

Nearly any method or construct in CloudWall that is async by it’s nature, is promise. DB methods return promises, modals are promises (resolved or rejected on close), apps are promises (resolved on start succeeds), their components are also promises (if they need to be async) and so on.

jQuery Deferred object promise model used by default. Like other models it’s than-able, but has nice extensions like progress notifier. 

Async methods, that return promise are marked with ⚑ if promise is rich $.Deferred(), or with ⚐ if promise inherits PouchDB promise format (only than-able, no candies). Infinity mark ∞ added if promise returned is forever pending and used for notifications.

You have enough RAM

Really, every phone now has 1Gb or even more. RAM is fast, 1-2 magnitudes faster than DB. RAM queries are sync. So it’s a good practice to cache all docs you use and can potentially use during session, into RAM.

JSON is more than json

Most lib functions, that parse or return json, understand json extension for functions, regexps and dates. Both calls return valid result.

Compliment methods reconstruct functions, regexps and dates.

Inline it

No attached file or resource has an URL unless you generate it — it can be costly and you must explicitly deallocate memory when app closes. It’s weird practice for JS community — we all live in a world of automatic garbage collectors.

Sometimes it’s a good idea to inline relatively large portions of binary data in JSON — and then in HTML while render. Userpics for example — which are usually less than 10kb — are inlined. All pics in this API are inlined. It’s easy and works enough fast in most cases.

this.app runtime obj

Object is available from inside of any app during its runtime. All init, bind, check, css, manifest and style functions can find runtime methods at this.app.

Property app is created in the manifest when you author it in Manifest Editor. When manifest is not yet initialized as ready-to-run application, app contains no methods — only application related properties — name, title, icon and so on.  They are marked with ❆ sign.

When manifest is prepared to be run as application, app object is extended with several methods, related to the particular app instance.

this.app properties

app.author ❄

App author name and id.

app.born

App start moment timestamp.

app.domid

HTML DOM unique id of app’s <div> container.

app.ico ❄

App icon as string containing dataURL of an image.

app.initurl

Start URL of an app instance.

app.maskstate ❄

Object or array, which is mask for reflecting app state to URL string. Application data field is masked using cw.lib.mask method with this mask. Result is encoded with cw.lib.tourl64 and reflected to URL hash.

It’s important to keep total length of state object less then 1500 bytes (browser limits the length of URL) — so do not reflect strings of uncontrolled length to appstate.

app.name ❄

Application name as reflected in URL hash.

app.nodetitle ❄

String mask for reflecting app state to browser tab’s title. References the property of app’s data, which must be observed time to time by system and put into tab title app app list right column.

app.nodecmd ❄

This property is set only if app is an editor. String mask that references the property of app’s data, which is filled with command, that editor must exec on document.

Possible list of commands that editor can exec over this or that doc types is set when you author an app with Manifest Editor.

Again: it is not the command by itself, it’s the dot-reference of property, where app can find command it was called with, during runtime.

app.nodedoc ❄

This property is set only if app is an editor. String mask that references the branch of app’s data, which is filled with document, that editor must process.

Before editor starts, system loads document that editor must process. It must be mounted somewhere on the app internal data tree. this.app.nodedoc references the node, where this particular app assumes to find doc to edit.

app.state

Current encoded app state as you see in the browser URL string after last slash.

app.timeout ❄

App max timeframe to start, in milliseconds. If app’s promise didn’t resolved during timeframe, app start is aborted and app is killed.

app.title ❄

Application title as it is shown in doc lists and start menu.

app.updated

Timestamp system last checked if app state was updated.

app.url

Current full app url.

app.width ❄

Array of suitable widths of an app container. System choose one when starts or layouts application to fit app and side panes into screen area.

// End of this.app properties

app.busy( bool )

Makes app busy or ready for interaction. ‘Busy’ is not more then semi-transparent overlay in front of app’s <div>. It prevents app from interaction with user, but have no other impact on app runtime.

app.close( next, force ) ⚑

Closes app. Param next is url to open next. force boolean commands to make no check if doc being edited is unsaved.

Returns promise. Resolved with app data when app successfully closed, or rejected with reason if app termination failed.

app.isActive(), app.isEditor()

Return if app is active and if app is an editor.

app.layout()

Forces system to rearrange panels and app layout.

app.local( key, val )

Puts or gets key/value in localStorage. val can be object, string or whatever that can be converted to json (no functions and regexps). 

If val is undefined last saved value is returned. If val is null key is removed from storage and its last value returned.

Storages for each app manifest are independent, but all instances of one app manifest running from any DB see one bundle of keys. Feature is useful for storing trigger-like app states like is app started first time or did user accepted terms.

app.modal( arg, width ) ⚑

Popups modal dialog. If no arg or true passed, closes opened modal and rejects its promise. To open modal argument must be a string, an object or jQuery object with image.

String passed. String is assumed to valid HTML and is rendered in modal. Second arg, passed sets default width of a container, HTML rendered in.

jQuery image passed. Opens modal with image, good for viewing full versions of previews. Width restricts modal width, default is 820.

Object passed. In this case modal is initialized with jQuery.my form. If form fails to init, modal promise is rejected immediately. Modal with form inside is called in this way:

Manifest can be an object with $.my manifest or string pointer to named manifest. Next example will open standard confirm dialog with ‘Proceed’ text on Ok button.

To close modal, the manifest running inside must trigger commit event to resolve modal’s promise with form data, or trigger cancel event to reject promise. Event can be triggered on any DOM element inside the form — it bubbles.

app.run( url )

Starts other app by URL.

app.watch ⚑ ∞

Object that is longpoll promise, which is notified when app goes active, inactive or is sentenced to close.

this.db runtime obj

Object is available from inside of any app during its runtime. All init, bind, check, css, manifest and style functions can find runtime db methods at this.db.

Most of them are very similar to global cw.db() methods with slight differences, related to app runtime mode. Methods, that have no cw.db() prototype or behave different, are marked with ⁙ sign.

Proxies to cw.db()

Read more in cw.db section.

this.db.actions( type )

Returns object, that represents doctype to doc action to app mapping. Called without arguments returns all type to app mapping tree.

this.db.app( appName )

Finds application manifest by app name. Searches first in DB appcache, then in appcache of system DB, then in system cache.

this.db.del( docid ) ⚑

Deletes doc by docid.

this.db.find ( filter ) ⚑

Finds and caches docs using filter function. Promise resolved with array of docs. Very slow in Chrome and Opera.

this.db.form( manId )

Returns manifest by qualified component id like cw.Post.Editor.Cropper. This method is just proxy to cw.form().

this.db.hide( docId )

Marks doc as hidden. It means doc won’t be deleted from DB, but become nearly invisible for apps — excluded from queries results, doc lists and so on.

this.db.inram( docId )

Checks if doc was cached in RAM. Returns true if doc was loaded. See db.ram for more details.

this.db.isread( docId )

Checks if cached doc was read (opened) in current revision. See db.markread and db.hide.

this.db.markread( docId )

Marks cached document as read in current revision. 

this.db.name

String, DB id.

this.db.settings( arg ) ⚑

Promise only if arg provided, else immediately returns settings object for DB. This object contains info about DB creator and birth stamp, sync urls, apps pinned and so on.

Replication URLs are returned with passwords sealed.

this.db.query( func ) ⚐

Queries DB with CouchDB-style map function. Promise is resolved with an array of results — which is also in CouchDB style. Results are not cached in RAM by system. Quite slow in Chrome and Opera.

this.db.sync( arg )

If no arg provided, returns current status of replication (true or false). If boolean provided as arg, starts or stops DB replication.

this.db.users()

Returns DB users list in format {"user-userid":"userPicBase64dataURL",...}.

this.db.uuid()

Returns stamp-based new doc uuid.

this.db.att( docid ) ⁙

Return Att object if doc was already cached. Att object has 5 members:

Function name is dataimageurl or  blob. Result is _attachment object, augmented with data in appropriate format, and data itself.

Format of data returned depends on function name.
 .data returns base64 data ⚑,
 .image — base64 with prefix data:mime/type;base64,... attached ⚑,
 .url — dataURL, temporary session string reference to resource ⚑.
 .blob returns native DB format — binary Blob object ⚑.

⚒ Unlike global prototype contains counter and frees resource when all apps using resource are closed.

this.db.load( args ) ⚑ ⁙

Loads doc or docs and caches them. All necessary events are raised and watchers notified. There are several possible combinations of arguments and their types:

Promise is rejected on error with (errorMessage as String, errorObj as Object).

⚒ Unlike global cw.db().load() method, app runtime load marks app-caller as busy, if operation takes more than 200ms.

this.db.save( doc ) ⚑ ⁙

Saves (creates) doc. To create doc just save it without _rev, and, possibly, _id properties. If conflict occurs during save, modal for user intervention is shown. 

Promise is resolved with new doc, which is immediately reloaded after save and cached. 

If doc to save has no name or type fields, or is pre-encrypted (has CRYPTO  property) promise is rejected. 

⚒ Unlike global cw.db().save() method, app runtime decrypts saved docs, if they were encrypted. If doc to save has field crypto with valid keyId, doc is encrypted with the key before save. In this case promise is resolved with decrypted doc, but cache and DB store encrypted one.

⚒ App runtime marks app as busy while save takes place, if operation takes more than 200ms.

⚒ If doc we save is one opened in editor (not just doc, but active doc you edit), system generates new snapshot footprint to track if doc changes later. 

this.db.ram( arg )

Queries RAM cache. Argument can be _id, array of _ids or filter function. Method is not a promise and returns array of results immediately.

this.db.watch() ⚑ ∞ ⁙

Returns promise which is forever-pending. Promise receive notifications when some document(s) with type docType changed in DB or in cache. If no docType provided, watcher called on any doc changed.

On hook installed handler function gets the last portion of updated docs immediately, and then receives updates in more or less big chunks after update took place.

Watchers are raised only after all bulk updates finished — to ensure no excessive calls of handlers. If you consequently save 3 docs, watchers are called once — with array of all three docs.

⚒ Unlike global cw.db().watch(), app-dependent one sleeps if app is inactive. App receives all updates only when gets active.  

this.files object

Manifest may have attached resources — which are just file attachments to DB doc. These resources are loaded in RAM when app starts first time and persist in RAM until last app instance close.

App instance can access these resources using this.files object, which resembles a lot standard CouchDB _attachments doc property.

Standard attachments object are extended with two properties — url and blob

url contains string with session URL of resource. It looks a little weird, like blob:http%3A//cloudwall.me/e8b3806a-92fa38218fbc, but can be put to src attribute of <img> for example — and image is shown. URLs of this type are suitable for ajax requests as ‘classic’ URLs. Main difference — requests to files in memory are blazing fast.

Read more about URL Object on MDN. 

blob contains Blob object with byte array of a resource file. It can be read in any suitable format.

cw global obj

Not implemented: Members of window.cw are different for debug and standard modes. Methods, marked with ✩ symbol, are available for all apps and console only in debug mode. In standard mode they are available only for system apps (loaded from cw DB).

Large cw.db and cw.lib bundles are expanded in the end of section. 

cw.con() ✩

If in debug mode, prints argument to console.

cw.crypto object

Contains all protected info in the system in decrypted state. The only system component in standard mode (not registration or profile update), that is able to write settings doc into system DB.

crypto.dblist()

Returns an array of DB ids, CloudWall is connected with.

crypto.dec( doc )

Decrypts doc with key, which id is pointed  by doc.crypto property. If no key exist source doc returned as result.

Keys are managed and generated on a profile update page and are stored encrypted with PIN in settings doc.

crypto.enc( doc )

Encrypts doc with key, which id is pointed by doc.crypto property. If no key exist source doc returned as result.

crypto.has( keyId )

Return true if cryptolib knows key with keyId.

crypto.keys()

Return array of key object. Each is like {id:"vgje9cyd"", name:"Key name"}.

crypto.me()

Return userinfo object.

cw.dbs()

Returns list of db names and titles, which is array of objects like
{"cw":"System DB", "manual":"Manual", ...}.

cw.debug

Property, debug state. True if debug mode is on. Read-only.

cw.event( arg ) ⚑ ∞

Global events feed. If argument is a string , all global listeners receive this string. If argument is a function, it becomes a listener of global events feed. 

If any other type of arg provided (or no arg), returns global events promise, which .progress( listenerFunction ) method binds listener with feed.

There are several system emitted events. They generally just notifies subscribers, that system state changed, without pointing reason or event source — it’s an agreement for broadcasted events.

Events, broadcasted by system, are:

  • slot open Some app just started
  • slot close Some app just closed
  • db replication started Tried to start replication
  • db replication failed Replication just closed or couldn’t start
  • settings update Received doc with profile settings update
  • app manifest update System received and mounted app manifest update

cw.form( formId, dbid )

Returns form (named manifest) with all sub-manifests mounted, or null. If dbid provided and system appcache lookup failed, form is searched in appcache of dbid DB.

How appcache works

All manifests from all DBs are cached in RAM. All apps and components — their source manifests unfolded — are loaded into RAM on system start and kept up to date. System just read docs by keyrange cw- to cw. on start-up and caches these docs every time they are updated in DB.

Screenshot of App Editor’s right pane. Yellow marks are app name and manifest id generated from app ...

Screenshot of App Editor’s right pane. Yellow marks are app name and manifest id generated from app name.

Manifest hiearchy

When you create an app or component manifest, you give it a name. Names are like Appname or Namespace.Appname.ComponentName or whatever, but Capitalized and in Dot.Notation.

App may consist of many components, and each of them is mounted on app manifest to position, that is component name.

So you can create manifest of name Demo.ToDo.Wow — and ToDo app will see it at runtime as object this.Wow from any init, bind or other function of the app.

Capitals are used to guarantee no interferention with manifest properties, occupied by system. They all are not Capitalized — like ui or init or style, which are taken from source manifest, and _db or _id, that are mounted by system.

System and per-DB caches

Each DB has own cache — so you can have different versions of an app in sibling DBs. 

System DB appcache is special — it is merged over every other DB’s appcache. It ensures that all system apps are visible in all DBs. Also it ensures that all DB-local apps can use system components.

Also it means you can not overlay system apps with your own in one particular DB. 

System appcache consists not only of components loaded from DB. It also holds several dozens of system apps and components, loaded from cloudwall.me during system start. Each system manifest is of namespace cw.Sys

cw.layout( arg )

Layout UI, recalcs width and so on. Arg is slot id. If no arg provided, active slot gets re-layout. Slot receives layout notification. 

cw.lock( bool ) ✩ ⚑ ∞

Locks/unlocks system. If no arg provided, returns longpoll promise. Lock state pauses all queues and disables slot switch.

Method is available only in debug mode. 

cw.locked()

Returns system lock state.

cw.log( arg1, ... argN )

Writes serialized arguments to system log. If no arguments provided, returns array of several last log records. If only one argument passed and it‘s a number — returns an array with arg1 last log records. Each log record is normally a string of JSON format.

Log persists in localStorage and survives on any DB or profile removal.

cw.me( prop )

Not equal to cw.crypto.me(). If no prop passed, returns user name. If prop is a string, returns property of user’s profile.

cw.note (msg, style)

Popups non-blocking note in the right top corner of a screen. style can be string okerrorwarning or none.

cw.ram( dbid, docid ) ✩

Returns reference to the doc in cache or null. This method is available in debug mode only (restriction not yet implemented).

cw.reg (manifest, db) ✩

Registers manifest (app or component) into DB appcache. 

cw.state object

Slot manager object. Members are:

state.get()

Returns active slot object.

state.set( url )

Decodes URL hash and execs app with init params passed through URL.

state.slots()

Returns list of all running slots.

state.url()

Returns current state URL.

cw.db object

Returns DB object. DB must be mounted in system settings file — system connects to each DB on start. Members of DB object:

db.actions( type )

Returns object, that represents doctype to doc action to app mapping. Called without arguments returns all type to app mapping tree.

db.app( appName )

Finds application manifest by app name. Searches first in DB appcache, then in appcache of system DB, then in system cache.

db.att( docid )

Return Att object if doc was already cached. Att object has 5 members:

The action function name is 'data''image', 'url' or  'blob'. Result is _attachment object, augmented with data in appropriate format, and data itself.

Filename can be array of names, name as string or null — then all attaches are read in format requested.

Format of object returned depends on function name. In general, object returned is very same to doc’s _attachments doc branch, but every file object has additional property.
 .data returns base64 data ⚑,
 .image — base64 with prefix data:mime/type;base64,... attached ⚑,
 .url — dataURL, temporary session string reference to resource ⚑.
 .blob returns native DB format — binary Blob object ⚑.

db.del( docid ) ⚑

Deletes doc by docid.

db.find ( filter ) ⚑

Iterates filter function over each doc in DB. If filter returns , doc is pushed to resulting collection. All docs found are immediately cached. Promise is resolved with array of docs, sorted by _id.

Example code fetches all ToDo-s that were saved more than 5 times.

Method is very slow in Chrome and Opera, 50-100 times slower than in FF or Safari.

db.form( manId )

Returns manifest by qualified component id like cw.Post.Editor.Cropper. This method is just proxy to cw.form().

db.hide( docId )

Marks doc as hidden. It means doc won’t be deleted from DB, but become nearly invisible for apps — excluded from queries results, doc lists and so on.

db.load( args ) ⚑

Loads doc or docs and caches them. All necessery events are raised and watchers notified. There are several possible combinations of arguments and their types:

Promise is rejected on error with (errorMessage as String, errorObj as Object).

Docs loaded has several extensions over standard CouchDB doc format.

db.markread( docId )

Marks cached document as read in current revision. State if doc was read and in what revision is stored in system DB of each user. When doc is loaded, this state mounted as _read property of doc. 

It’s useful for indication that doc, that received new revision, was not read. System doc list shows such updates with blue highlight.

Attributing doc as read raises doc update events despite of no DB op takes place.

db.isread( docId )

Checks if cached doc was read (opened) in current revision. See db.markread and db.hide.

db.name

String, DB id.

db.ram( arg )

Queries RAM cache, not a promise. Argument can be _id, array of _ids or filter function. Method is not a promise and returns array of results immediately.

db.inram( docId )

Checks if doc is cached in RAM. Returns true if doc was loaded. 

db.save( doc, silent ) ⚑

Saves (creates) doc. If silent is true, no info message is shown on finish. To create doc just save it without _rev, and, possibly, _id properties.

If conflict occurs during save and silent is false, modal for user intervention is shown. If conflict occured and silent is true, promise is rejected with error.

Promise is resolved with new doc, which is immediately reloaded after save and cached. 

If doc to save has no name or type fields, or is pre-encrypted (has CRYPTO  property) promise is rejected. 

If doc to save has field crypto with valid keyId, doc is encrypted with the key before save. Promise is resolved with encrypted doc this case — unlike this.app.save(), which decrypts doc saved.

System settings doc can not be saved using db.save method.

db.settings( arg ) ⚑

Promise only if arg provided, else immediately returns settings object for DB. This object contains info about DB creator and birth stamp, sync urls, apps pinned and so on.

Replication URLs are returned with passwords sealed.

db.sync( arg )

If no arg provided, returns current status of replication (true or false). If boolean provided as arg, starts or stops DB replication.

db.users()

Returns DB users list in format {"user-userid":"userPicBase64dataURL",...}.

db.uuid()

Returns stamp-based new doc uuid.

db.watch( docType ) ⚑ ∞

Returns promise which is forever-pending. Promise receive notifications when some document(s) with type docType changed in DB or in cache. If no docType provided, watcher called on any doc changed.

On hook installed handler function gets the last portion of updated docs immediately, and then receives updates in more or less big chunks after update took place.

Watchers are raised only after all bulk updates finished — to ensure no excessive calls of handlers. If you consequently save 3 docs, watchers are called once — with array of all three docs.

PouchDB proxied methods

db.compact() ⚐

Compacts DB.

db.get () and db.getAttachment () ⚐ 

PouchDB methods, raw DB read. Results are never placed in cache, no events raised and no app watchers notified. Not recommended in most cases.

db.info() ⚐

Returns DB info in CouchDB style.

db.post(), db.put(), db.putAttachment() ⚐

PouchDB methods, raw DB write. Not recommended in most cases, but can be useful while resolving update conflicts.

db.query( func ) ⚐

PouchDB internal method of querying DB. 

cw.lib — converters

There are a lot of lib functions, specific for CloudWall architecture. Most of them are object manipulators, converters and formatters. This section is converters.

lib.base64( arg, decode )

If decode is false or none, converts anything into base64 string. If you pass an object, ensure it has no circular references.

If decode is true, first argument must be valid base64 string — and it will be decoded into source, with all functions, regexps and dates intact.

lib.blob2base64 (Blob, done, blnNoMime)

Async, but does not return promise. Converts Blob to base64, if blnNoMome is set, result has no data:mime/type prefix.

lib.base642blob (base64, done, mimeString)

Async, but does not return promise. Converts base64 into Blob with mime type, taken from mimeString.

lib.dec( base64, key )

Decodes base64 string of an OpenSSL packet into source extended JSON object, string or whatever. Only AES256 salted packets are accepted. Complimentary method is cw.lib.enc().

lib.decDoc ( base64, key )

Decodes base64 string of an OpenSSL packet into source standard json object. Twice faster than .dec cause operates on standard json, not extended. No functions or regexps are unfolded, they returned as source strings.

Only AES256 salted packets are accepted. Complimentary method is cw.lib.encDoc().

lib.enc ( arg, key )

Encodes arg (object, array, string, function or whatever) into OpenSSL AES256 salted packet. ‘Salted’ means you can encode same data twice with same key — result strings will differ.

Returns base64 string of a packet.

lib.encDoc ( arg, key )

Same as cw.lib.enc(), but encodes only valid json-nable objects — so a little faster. Functions, regexps and so on are dropped.

lib.footprint( docObj )

Returns hash of docObj, which is assumed to be valid DB doc. Hash is calculated using very fast sdbmCode algorithm from Berkeley Db codebase. It’s not a cryptographic hash, so it’s 20-50 times faster than MD5. On i7 its capacity is 50+Mb/s.

lib.fromurl64( urlHash )

CloudWall reflects current app and its state to browser’s URL bar. App state is reflected to hash side of URL. It has 3 or 4 slash-separated parts.

#cwManual/Post/!WyJlZGl0IiwiMTM5NzM3MTYzODM0dThlYnM3MTMiXQ--

Last part is encoded app state. To decode it use cw.lib.fromurl64:

lib.tourl64( arg )

Converts argument to URL params string. 

lib.image ( arg )

Image library. Allows to resize, sharpen or blur image. Applies brightness and contrast (or any other map function). Steps can be chained.

Argument is Image object or jQuery object, pointing to an image. Image must be loaded (load event fired).

CWImage object that is passed through, has several other members:

.width() is current stage image width
.height() is height
.ctx() is canvas context of current state
.convolute ( array ) convolves image with array
.destroy() kills CWImage object

Normally .jpeg(quality) or .png() calls destroy an object. To avoid destroying use .jpeg(quality, true) or .png(true). It’s helpful for generating multistep previews.

lib.js2txt ( jsObj, tab )

Renders javascript object as source text. It’s not a JSON or json — but result string is eval()-compatible.

lib.json( any )

Converts argument to JSON. Functions, regexps and dates are preserved. Compliment function is cw.lib.unjson().

lib.unjson( object )

Converts object after JSON.stringify into full-featured object with functions, regexps and so on. Applied to unfold manifests.

cw.lib — utils

Different utility functions and hashes.

lib.a2o( Array )

Converts array of strings into object with keys are unique array values, and each key’s value is counter.

Useful for search in arrays. Array.indexOf method is rather slow for iterators, it has O(n) complexity. Once converted to object it takes O(1) cause javascript objects are hash tables. So when you go through long list, each elt of which must be checked wether it is in other list, it’s good idea to convert ‘other list’ into object.

lib.date( arg, fmt )

Formats date from arg (can be number, string or date) into human-comfort string, closer dates has better precision. fmt is string tinyshort or long. Default is short

Format is tiny:

Format is short:

Format is full:

lib.dehtml ( string, trim )

Removes all HTML markup from string except <a> tags. Trims string to trim chars with ellipsis. 

lib.dry ( obj, extraDry )

Returns shallow copy of an object with all first-level properties, started with _ char removed. If extraDry is false, _id_rev and _attachments properties are preserved.

lib.fuse( args )

Chain object merge, first argument is extended by subsequent ones in deep. It’s not like Object.merge(o1, o2, true) or $.extend(true, o1, o2, o3). Main difference is that arrays are cloned, but not merged.

lib.getref( obj, ref )

Returns object branch by string dot-notated reference. Unlike standard dot notation does not throw error when path does not exist.

lib.hash8( any )

Returns 8-chars 40-bit hash of an argument. Hash is derived from MD5, so it is quite slow. Use cw.lib.sdbm() instead if you need no cryptographic-class hash distribution.

lib.hash4( any )

Returns 4-chars 20-bit hash of an argument.

lib.mask( obj, mask )

Mask source object with mask. Compliment is cw.lib.unmask()

lib.md5( any )

Returns MD5 hash of an argument.

lib.sdbm( any )

Very fast hash, return 8-9 chars. As it use standart JSON.stringify, all non-jsonnable properties of arg (if it’s an object) are dropped.

cw.lib.unmask( any, mask )

Unmasks masked object into source. Quite tricky, but understandable using examples. Utilized heavily in manifest and appcache engine.

When both args are objects, behaves same as cw.lib.mask().

cw.lib.uuid()

Returns 20-digit doc _id. 12 first digits are stamp with 10ms granularity, second — random 8-char string.

Doc special properties

Result of fetching system properties doc. It is stored encrypted.

Result of fetching system properties doc. It is stored encrypted.

Every doc in system has several special properties. Some of them are DB-related, some — cache related, some contain doc history and so on.

Most special properties are of runtime nature — doc has these properties only when it is in cache. Some other properties are persistent and are stored to DB with doc, other exist only when doc is in cache.

Normally underscored properties are system, PouchDB provides only _attachments, _id, _rev and _conflicts. All other underscored properties are generated by CloudWall and are trimmed off onbefore putting to storage.

doc._attachments

Object, contains list of attachments in CouchDB style. Does not in general contain attachments by themselves.

doc._conflicts

Array, contain list of conflicting docs. Since Pouch employs MVCC, there can exist many versions of one doc simultaneously. One version is main, others are conflicts. There is special section in Debug about conflict resolution.

doc._db

Document parent DB name. Since we may have same-id copies in system it’s good to know DB doc was loaded from.

doc._full

Exist and set to true if doc was read with attachments. Normally means that every node in _attachments has field data with base64-encoded attachment inside.

doc._id

Document per-DB unique id. For simple doc system-generated _id’s first 12 chars are nums. It is timestamp of the doc birth, in 10ms granularity. This kind of uids allows fetching DB by date range.

doc._nokey

If set, shows that system wouldn’t be able to decrypt doc since has no cryptokey doc was encrypted with.

doc._read 

If string, represents revision, in which document was last read by user. When you open doc in an editor, system marks doc as read in current revision. Read docs are gray in doclist, unread marked blue.

doc._rev

Document revision. Has two parts — revision number and random hash. In nearly all cases revision number shows exactly how many times doc was saved.

doc._tags

Reserved for future use.

doc.creator

String or none. In some docs can contain info about user, created a doc.

doc.crypto

If set, is an id of cryptokey this doc is encrypted with. When opened/saved by editor docs are decrypted by system transparently. 

For any app it’s enough to set this property into valid cryptokey id — and doc is encrypted when saved.

doc.CRYPTO

String, contains base64 OpenSSL packet of an encrypted doc. Normally, apps must not manipulate this property — it can easily make doc unreadable.

doc.log

Optional array. If present, contains history of doc editions — who, when and did what with the doc. Much more informative, then revision because has timestamp and username.

If doc sent to save has this property and it’s an array — new log entry is prepended before putting to DB.

doc.name

String. Mandatory doc property — docs without this property can not be saved or cached.

doc.pic

Optional string, can contain dataURL of doc’s pic. If doc has one, system doc lists shows it as doc icon.

doc.stamp

Timestamp doc was last saved. This property is updated automatically only if doc is saved using this.db.save() method. cw.db().save() does not affect stamp.

doc.type

String. Mandatory property, points doc type. ‘Type’ is not something concrete or even solid. There can be several editors bound with the particular doc type.

Comparing editor’s default doc structure and current doc it’s possible to determine if one editor can edit this particular doc or not. 

Events

To be written

Debugging

To enter Debug mode just press Tab key after PIN on start. Console now is full of messages.

$app commands

Main consideration that might be used during debug is that all apps has DOM shortcut. You can see any app state using simple console commands.  

var $app = $(".cw-app-active") gets DOM node of current active slot. This node has several data nodes and methods attached.

$app.data("app")

Returns ‘live’ slot object. It has several properties, most important are app and db — application runtimes.

$app.data("my")

Returns jQuery.my runtime. Runtime has several useful fields, for example $app.data("my").initial returns copy of data as they were when application started.

$app.my("data", obj)

If second argument is null, returns ‘live’ data object of active app. If second argument is object, it is superimposed over app data and app is redrawn.

Note: not the same as $app.data("my")!

$app.my("errors")

Returns snapshot of current app error state. If everything is ok, returns {} object, otherwise returns hierarchy of invalid controls’ DOM selectors. 

$app.my("valid") 

Returns boolean if app is in valid state.

$app.my("manifest")

Returns ‘live’ manifest object of active app.

$app.my("redraw")

Forces manifest to redraw. 

$app.my("ui", obj)

If second argument is null, returns ‘live’ unfolded and extended runtime ui object of active app manifest. If second argument is object, it is superimposed over manifest and app is redrawn.

Augmenting app during runtime is quiet tricky operation, it can damage or kill app, it’s like neurosurgery.

jQuery promise tricks

Most of operations inside CloudWall are promises, however, for historical reasons, they are not fully A+.

$.Deferred, which is main promise lib in system, has several issues and strangeties.

Fail, not catch

$.Deferred object has provides no .catch handler, use .fail instead.

Silent errors

Deferreds are silent. If something goes wrong, they die without any message. There are two ways to catch in-promise errors.

First, try-catch blocks in your thens. Second — global event handler window.onerror.

Reversed exec order

There is another ‘feature’ – $.Deferred’s promises can change execution order.

Variable x now has value 30 — promise, that should be async by definition, was executed  in sync. To ensure $.Deferred is async, just break event loop.

If you copy above to console you see '30' output. Then type x and press enter — x is 20, as we expect if promise was not resolved prior to .then chaining.

Progress notifiers

This feature allows to build notifiers using deferreds. You can create $.Deferred that is forever pending, and use .notify(message) to notify listeners. 

There is one point to know — when you attach new listener, it receives one last notification, if they were. So sometimes your listeners can receive messages from deep past. 

Hot patching and beta mode

Saving an app or component has immediate effect — all future app instances will use new code. Running if they use code as external component, also utilize new code.

There is one exception. If you mark your component as beta, all users except you can not exec it — it is not mounted on their appcache.

Command work

This feature allows distributed app authoring. ‘Main app’ can contain several dummies, that take place in namespace, but do nothing.

Some engineer authors some component marked as beta, that overlays dummy-occupied branch of main app manifest. The only user gets affected by this patch is author. All others see dummy even if component get replicated to them — unless author or someone else make component stub.

 

 

© 2017 ermouth. CloudWall is MIT-licensed.