UNPKG

4.47 kBJavaScriptView Raw
1// Generated by CoffeeScript 2.3.1
2(function() {
3 // This is a minimalist CouchDB (HTTP) API
4 // It provides exactly what this module needs, but no more.
5 var CouchDB, EventEmitter2, EventSource, LRU, URL, agent, autoRestart, ec, fromEventSource, http, https, lru_cache, lru_dispose, most, options, sleep, static_cache;
6
7 LRU = require('lru-cache');
8
9 ({EventEmitter2} = require('eventemitter2'));
10
11 http = require('http');
12
13 https = require('https');
14
15 lru_dispose = new EventEmitter2({
16 newListener: false,
17 verboseMemoryLeak: true
18 });
19
20 options = {
21 max: 200,
22 dispose: function(key) {
23 return ev.emit(key);
24 },
25 maxAge: 20 * 60 * 1000
26 };
27
28 lru_cache = LRU(options);
29
30 static_cache = new Map();
31
32 CouchDB = class CouchDB {
33 constructor(uri, use_lru) {
34 if (uri.match(/\/$/)) {
35 this.uri = uri;
36 } else {
37 this.uri = `${uri}/`;
38 }
39 if (use_lru) {
40 this.cache = lru_cache;
41 this.limit = most.fromEvent(this.uri, lru_dispose);
42 } else {
43 this.cache = static_cache;
44 this.limit = most.never();
45 }
46 switch (false) {
47 case !uri.match(/^http:/):
48 this.agent = agent.agent(http.globalAgent);
49 break;
50 case !uri.match(/^https:/):
51 this.agent = agent.agent(https.globalAgent);
52 break;
53 default:
54 this.agent = agent;
55 }
56 return;
57 }
58
59 put(doc) {
60 var _id, uri;
61 ({_id} = doc);
62 uri = new URL(ec(_id), this.uri);
63 return this.agent.put(uri.toString()).type('json').accept('json').send(doc).then(function({body}) {
64 return body;
65 });
66 }
67
68 get(_id, {rev} = {}) {
69 var uri;
70 uri = new URL(ec(_id), this.uri);
71 if (rev != null) {
72 uri.searchParams.set('rev', rev);
73 }
74 return this.agent.get(uri.toString()).accept('json').then(function({body}) {
75 return body;
76 });
77 }
78
79 delete({_id, _rev}) {
80 var uri;
81 uri = new URL(ec(_id), this.uri);
82 if (_rev != null) {
83 uri.searchParams.set('rev', _rev);
84 }
85 return this.agent.delete(uri.toString()).accept('json').then(function({body}) {
86 return body;
87 });
88 }
89
90 changes(options = {}) {
91 var include_docs, live, s, since, stream, uri;
92 ({live, include_docs, since} = options);
93 if (live == null) {
94 live = true;
95 }
96 if (live !== true) {
97 throw new Error('Only live streaming is supported');
98 }
99 if (this.cache.has(this.uri)) {
100 return this.cache.get(this.uri);
101 }
102 if (since == null) {
103 since = 'now';
104 }
105 uri = new URL('_changes', this.uri);
106 uri.searchParams.set('feed', 'eventsource');
107 uri.searchParams.set('heartbeat', true);
108 uri.searchParams.set('include_docs', include_docs != null ? include_docs : false);
109 // The stream might end because the server disconnects or other errors.
110 // In all cases we let it finish cleanly.
111 s = function() {
112 uri.searchParams.set('since', since);
113 return fromEventSource(new EventSource(uri.toString())).continueWith(function() {
114 console.error('retry', uri.host, uri.pathname, since);
115 return most.never();
116 }).recoverWith(function(error) {
117 var ref;
118 console.error('retry', (ref = error.stack) != null ? ref : error, uri.host, uri.pathname, since);
119 return most.never();
120 });
121 };
122 stream = autoRestart(s).map(function({data}) {
123 return data;
124 }).map(JSON.parse).tap(function({seq}) {
125 if (seq != null) {
126 return since = seq;
127 }
128 }).until(this.limit).multicast();
129 this.cache.set(this.uri, stream);
130 return stream;
131 }
132
133 };
134
135 module.exports = CouchDB;
136
137 ec = encodeURIComponent;
138
139 most = require('most');
140
141 EventSource = require('eventsource');
142
143 ({fromEventSource} = require('most-w3msg'));
144
145 ({URL} = require('url'));
146
147 agent = require('superagent');
148
149 // When the stream finishes, we restart it with a small delay.
150 sleep = function(timeout) {
151 return new Promise(function(resolve) {
152 return setTimeout(resolve, timeout);
153 });
154 };
155
156 autoRestart = function(s) {
157 return most.generate(function*() {
158 return (yield 200);
159 }).startWith(0).map(async function(delay) {
160 await sleep(delay);
161 return s();
162 }).chain(most.fromPromise).switchLatest();
163 };
164
165}).call(this);