Stackedit/src/services/providers/helpers/couchdbHelper.js
2018-09-19 09:59:22 +01:00

195 lines
4.5 KiB
JavaScript

import networkSvc from '../../networkSvc';
import utils from '../../utils';
import store from '../../../store';
import userSvc from '../../userSvc';
const request = async (token, options = {}) => {
const baseUrl = `${token.dbUrl}/`;
const getLastToken = () => store.getters['data/couchdbTokensBySub'][token.sub];
const assertUnauthorized = (err) => {
if (err.status !== 401) {
throw err;
}
};
const onUnauthorized = async () => {
try {
const { name, password } = getLastToken();
await networkSvc.request({
method: 'POST',
url: utils.resolveUrl(baseUrl, '../_session'),
withCredentials: true,
body: {
name,
password,
},
});
} catch (err) {
assertUnauthorized(err);
await store.dispatch('modal/open', {
type: 'couchdbCredentials',
token: getLastToken(),
});
await onUnauthorized();
}
};
const config = {
...options,
headers: {
Accept: 'application/json',
...options.headers || {},
},
url: utils.resolveUrl(baseUrl, options.path || '.'),
withCredentials: true,
};
try {
let res;
try {
res = await networkSvc.request(config);
} catch (err) {
assertUnauthorized(err);
await onUnauthorized();
res = await networkSvc.request(config);
}
return res.body;
} catch (err) {
if (err.status === 409) {
throw new Error('TOO_LATE');
}
throw err;
}
};
export default {
/**
* http://docs.couchdb.org/en/2.1.1/api/database/common.html#db
*/
getDb(token) {
return request(token);
},
/**
* http://docs.couchdb.org/en/2.1.1/api/database/changes.html#db-changes
*/
async getChanges(token, lastSeq) {
const result = {
changes: [],
lastSeq,
};
const getPage = async () => {
const body = await request(token, {
method: 'GET',
path: '_changes',
params: {
since: result.lastSeq || 0,
include_docs: true,
limit: 1000,
},
});
result.changes = [...result.changes, ...body.results];
result.lastSeq = body.last_seq;
if (body.pending) {
return getPage();
}
return result;
};
return getPage();
},
/**
* http://docs.couchdb.org/en/2.1.1/api/database/common.html#post--db
* http://docs.couchdb.org/en/2.1.1/api/document/common.html#put--db-docid
*/
async uploadDocument({
token,
item,
data = null,
dataType = null,
documentId = null,
rev = null,
}) {
const options = {
method: 'POST',
body: { item, time: Date.now() },
};
const userId = userSvc.getCurrentUserId();
if (userId) {
options.body.sub = userId;
}
if (documentId) {
options.method = 'PUT';
options.path = documentId;
options.body._rev = rev; // eslint-disable-line no-underscore-dangle
}
if (data) {
options.body._attachments = { // eslint-disable-line no-underscore-dangle
data: {
content_type: dataType,
data: utils.encodeBase64(data),
},
};
}
return request(token, options);
},
/**
* http://docs.couchdb.org/en/2.1.1/api/document/common.html#delete--db-docid
*/
async removeDocument(token, documentId, rev) {
if (!documentId) {
// Prevent from deleting the whole database
throw new Error('Missing document ID');
}
return request(token, {
method: 'DELETE',
path: documentId,
params: { rev },
});
},
/**
* http://docs.couchdb.org/en/2.1.1/api/document/common.html#get--db-docid
*/
async retrieveDocument(token, documentId, rev) {
return request(token, {
path: documentId,
params: { rev },
});
},
/**
* http://docs.couchdb.org/en/2.1.1/api/document/common.html#get--db-docid
*/
async retrieveDocumentWithAttachments(token, documentId, rev) {
const body = await request(token, {
path: documentId,
params: { attachments: true, rev },
});
body.attachments = {};
// eslint-disable-next-line no-underscore-dangle
Object.entries(body._attachments).forEach(([name, attachment]) => {
body.attachments[name] = utils.decodeBase64(attachment.data);
});
return body;
},
/**
* http://docs.couchdb.org/en/2.1.1/api/document/common.html#get--db-docid
*/
async retrieveDocumentWithRevisions(token, documentId) {
return request(token, {
path: documentId,
params: {
revs_info: true,
},
});
},
};