1 | // Generated by CoffeeScript 2.3.1
|
2 | (function() {
|
3 | // CouchDB back-end
|
4 | // ----------------
|
5 |
|
6 | // ### Back-end for a regular (static) DB such as provisioning
|
7 |
|
8 | // - `db_uri` refers to a database URI.
|
9 | // - `view_for` refers to a view object or a function that returns a view object (based on a requested key). A view object contains `view.map` (the map function as a function), `view.app`,and `view.name`, which all refer to the same view. If `view_for` is `null`, the `_all_docs` "identity" "view" is used.
|
10 |
|
11 | // Changes are not computed for views where the `view_for` parameter is a function. (See below for the reason.) This could be worked-around by providing a database-to-view mapper that records the outcome of the view in a new database (and we are asked to monitor that database). (But notice that regular CouchDB databases are not suitable for this, since they can't directly handle non-string ids, and more importantly, cannot deal with duplicated keys/ids either.)
|
12 | var CouchDB, build_backend, changes_view, couchdb_backend, most, semantic_for, view_as_stream;
|
13 |
|
14 | couchdb_backend = function(db_uri, view_for, fromJS, use_lru) {
|
15 | var changes, get_key, semantic, the_db, view_changes, view_key;
|
16 | the_db = new CouchDB(db_uri, use_lru);
|
17 | semantic = semantic_for(the_db, fromJS);
|
18 | get_key = function(key) {
|
19 | return the_db.get(key).catch(function() {
|
20 | return null;
|
21 | });
|
22 | };
|
23 | // Document changes
|
24 | changes = the_db.changes({
|
25 | include_docs: true
|
26 | }).multicast();
|
27 | // Changeset for wandering-country-view/all (or other view)
|
28 | view_changes = (function() {
|
29 | switch ((view_for != null) && typeof view_for) {
|
30 | // For a static `view_for` object, we apply the `.map` function locally to each modified document,
|
31 | // therefor dynamically computing the outcome of the view. (CouchDB does the same thing on its side,
|
32 | // so if we need to reconnect we can query the CouchDB view and obtain the same results.)
|
33 | case 'object':
|
34 | return changes_view(view_for.map, changes).multicast();
|
35 | default:
|
36 | return most.empty();
|
37 | }
|
38 | })();
|
39 | // We do not provide support for view changes for `view_for` functions.
|
40 |
|
41 | // The reason this is a bad idea is that the view to use is decided based on the keys
|
42 | // (see below for `.app` and `.name`), but the keys are _generated_ by the very
|
43 | // same `map` function we're trying to select. (If this wasn't the case, the results would be
|
44 | // inconsistent between the data returned by CouchDB, and the data generated by the function.)
|
45 | // In details: to use this feature, you would have to provide a function would have to know
|
46 | // how to reliably predict which keys will be returned by which ids (in other words it would
|
47 | // be able to pre-compute the outcome of the `map` function).
|
48 |
|
49 | // Also, we do not provide support for view changes for aggregate views (`count`, `range` etc.).
|
50 |
|
51 | // On initial subscription we convert the key into a stream, using the server-side (CouchDB-stored) view.
|
52 | view_key = (function() {
|
53 | switch ((view_for != null) && typeof view_for) {
|
54 | case false:
|
55 | return function(key) {
|
56 | return view_as_stream(db_uri, null, '_all_docs', key);
|
57 | };
|
58 | case 'object': // there is only one DB, or the view is named the same in all DBs
|
59 | return function(key) {
|
60 | return view_as_stream(db_uri, view_for.app, view_for.name, key);
|
61 | };
|
62 | case 'function':
|
63 | return function(key) {
|
64 | var view;
|
65 | view = view_for(key);
|
66 | if (view == null) {
|
67 | return most.emtpy();
|
68 | }
|
69 | return view_as_stream(db_uri, view.app, view.name, key);
|
70 | };
|
71 | default:
|
72 | throw new Error('view_for must be object or function');
|
73 | }
|
74 | })();
|
75 | return build_backend({changes, view_changes, semantic, get_key, view_key, fromJS});
|
76 | };
|
77 |
|
78 | module.exports = couchdb_backend;
|
79 |
|
80 | changes_view = require('./util/changes-view');
|
81 |
|
82 | view_as_stream = require('./util/view');
|
83 |
|
84 | most = require('most');
|
85 |
|
86 | CouchDB = require('./util/db');
|
87 |
|
88 | semantic_for = require('./util/semantic-for');
|
89 |
|
90 | build_backend = require('./util/build-backend');
|
91 |
|
92 | // FIXME: figure out the pattern to push in bulk
|
93 |
|
94 | // The semantic really is 'UPDATE', not 'OVERWRITE'
|
95 | // → we could either do bulk-get / bulk-put (aka `_all_docs` and `_bulk_docs`),
|
96 | // → or use an [update function](http://docs.couchdb.org/en/2.1.1/api/ddoc/render.html#db-design-design-doc-update-update-name)
|
97 | // For now the code (above) does single GET/PUT on updates.
|
98 |
|
99 | }).call(this);
|