insomnia/app/database/index.js

295 lines
6.6 KiB
JavaScript
Raw Normal View History

2016-04-27 23:33:38 +00:00
import * as fsPath from 'path'
import electron from 'electron'
2016-04-29 08:15:37 +00:00
import Loki from 'lokijs'
2016-04-27 23:33:38 +00:00
2016-04-28 07:41:31 +00:00
import * as methods from '../lib/constants'
import {generateId} from './util'
2016-04-29 04:57:03 +00:00
import {CONTENT_TYPE_TEXT} from '../lib/contentTypes'
import {PREVIEW_MODE_FRIENDLY} from '../lib/previewModes'
2016-04-18 04:39:15 +00:00
export const TYPE_WORKSPACE = 'Workspace';
export const TYPE_REQUEST_GROUP = 'RequestGroup';
export const TYPE_REQUEST = 'Request';
export const TYPE_RESPONSE = 'Response';
const TYPES = [
TYPE_WORKSPACE,
TYPE_REQUEST_GROUP,
TYPE_REQUEST,
TYPE_RESPONSE
];
let db = null;
2016-04-16 23:24:57 +00:00
2016-04-28 00:04:29 +00:00
function getDBFilePath () {
2016-04-28 07:30:26 +00:00
const basePath = electron.remote.app.getPath('userData');
return fsPath.join(basePath, 'insomnia.db.json');
2016-04-28 00:04:29 +00:00
}
/**
* Initialize the database. This should be called once on app start.
* @returns {Promise}
*/
let initialized = false;
export function initDB () {
// Only init once
if (initialized) {
return new Promise(resolve => resolve());
}
return new Promise(resolve => {
2016-04-28 00:04:29 +00:00
const dbPath = getDBFilePath();
db = new Loki(dbPath, {
autoload: true,
autosave: true,
2016-04-29 08:15:37 +00:00
autosaveInterval: 300, // TODO: do a final save on close
persistenceMethod: 'fs',
autoloadCallback () {
TYPES.map(type => {
let collection = db.getCollection(type);
if (!collection) {
collection = db.addCollection(type, {
2016-04-29 08:15:37 +00:00
indices: ['_id'],
asyncListeners: false,
2016-04-29 08:15:37 +00:00
disableChangesApi: true, // Don't need this yet
clone: true, // Clone objects on save
transactional: true
});
collection.ensureUniqueIndex('_id');
console.log(`-- Initialize DB Collection ${type} --`)
}
collection.on('update', doc => {
Object.keys(changeListeners).map(k => changeListeners[k]('update', doc));
});
collection.on('insert', doc => {
Object.keys(changeListeners).map(k => changeListeners[k]('insert', doc));
});
collection.on('delete', doc => {
Object.keys(changeListeners).map(k => changeListeners[k]('delete', doc));
});
});
resolve();
initialized = true;
2016-04-29 08:15:37 +00:00
console.log(`-- Initialize DB at ${dbPath} --`);
}
});
2016-04-29 08:15:37 +00:00
global.db = db;
})
}
2016-04-16 23:24:57 +00:00
let changeListeners = {};
export function onChange (id, callback) {
console.log(`-- Added DB Listener ${id} -- `);
changeListeners[id] = callback;
}
export function offChange (id) {
console.log(`-- Removed DB Listener ${id} -- `);
delete changeListeners[id];
}
export function get (type, id) {
const doc = db.getCollection(type).by('_id', id);
return new Promise(resolve => resolve(doc));
}
function find (type, query) {
const docs = db.getCollection(type).find(query);
return new Promise(resolve => resolve(docs));
2016-04-16 23:24:57 +00:00
}
function insert (doc) {
const newDoc = db.getCollection(doc.type).insert(doc);
return new Promise(resolve => resolve(newDoc));
}
function update (doc) {
2016-04-29 08:15:37 +00:00
// NOTE: LokiJS only holds references to objects in its DB. This means we need to fetch the
// old reference and update it because that's the only way.
return get(doc.type, doc._id).then(oldDoc => {
Object.assign(oldDoc, doc);
db.getCollection(doc.type).update(oldDoc);
return new Promise(resolve => resolve(oldDoc));
});
}
function remove (doc) {
2016-04-29 03:37:49 +00:00
db.getCollection(doc.type).remove(doc);
// Also remove children
TYPES.map(type => db.getCollection(type).removeWhere({parentId: doc._id}));
new Promise(resolve => resolve());
2016-04-16 23:24:57 +00:00
}
// ~~~~~~~~~~~~~~~~~~~ //
// DEFAULT MODEL STUFF //
// ~~~~~~~~~~~~~~~~~~~ //
2016-04-16 23:24:57 +00:00
function docUpdate (originalDoc, patch = {}) {
const doc = Object.assign(
{},
originalDoc,
patch,
{modified: Date.now()}
);
// Fake a promise
const finalDoc = update(doc);
return new Promise(resolve => resolve(finalDoc));
}
function docCreate (type, idPrefix, defaults, patch = {}) {
const baseDefaults = {
parentId: null
};
const doc = Object.assign(
baseDefaults,
defaults,
2016-04-16 23:24:57 +00:00
patch,
2016-04-18 04:39:15 +00:00
2016-04-16 23:24:57 +00:00
// Required Generated Fields
{
_id: generateId(idPrefix),
$loki: undefined,
meta: undefined,
2016-04-18 04:39:15 +00:00
type: type,
2016-04-16 23:24:57 +00:00
created: Date.now(),
modified: Date.now()
}
);
2016-04-18 04:39:15 +00:00
// Fake a promise
return insert(doc);
}
// ~~~~~~~ //
// REQUEST //
// ~~~~~~~ //
export function requestCreate (patch = {}) {
return docCreate(TYPE_REQUEST, 'req', {
url: '',
name: 'New Request',
method: methods.METHOD_GET,
activated: Date.now(),
2016-04-29 04:57:03 +00:00
previewMode: PREVIEW_MODE_FRIENDLY,
body: '',
params: [],
2016-04-29 04:57:03 +00:00
contentType: CONTENT_TYPE_TEXT,
headers: [],
authentication: {}
}, patch);
2016-04-16 23:24:57 +00:00
}
2016-04-29 08:15:37 +00:00
export function requestById (id) {
return get(TYPE_REQUEST, id);
}
export function requestUpdate (request, patch) {
return docUpdate(request, patch);
}
export function requestCopy (request) {
const name = `${request.name} (Copy)`;
return requestCreate(Object.assign({}, request, {name}));
2016-04-16 23:24:57 +00:00
}
export function requestRemove (request) {
return remove(request);
}
export function requestAll () {
return find(TYPE_REQUEST, {});
}
2016-04-16 23:24:57 +00:00
// ~~~~~~~~~~~~~ //
// REQUEST GROUP //
// ~~~~~~~~~~~~~ //
export function requestGroupCreate (patch = {}) {
return docCreate(TYPE_REQUEST_GROUP, 'grp', {
collapsed: false,
name: 'New Request Group',
environment: {}
}, patch);
}
2016-04-16 23:24:57 +00:00
export function requestGroupUpdate (requestGroup, patch) {
return docUpdate(requestGroup, patch);
}
export function requestGroupById (id) {
return get(TYPE_REQUEST_GROUP, id);
}
export function requestGroupRemove (requestGroup) {
return remove(requestGroup);
}
export function requestGroupAll () {
return find(TYPE_REQUEST_GROUP, {});
}
2016-04-23 06:08:52 +00:00
// ~~~~~~~~ //
// RESPONSE //
2016-04-23 06:08:52 +00:00
// ~~~~~~~~ //
2016-04-16 23:24:57 +00:00
export function responseCreate (patch = {}) {
return docCreate(TYPE_RESPONSE, 'res', {
2016-04-18 04:39:15 +00:00
statusCode: 0,
statusMessage: '',
contentType: 'text/plain',
bytes: 0,
millis: 0,
headers: [],
2016-04-18 04:39:15 +00:00
body: ''
}, patch);
}
2016-04-18 04:39:15 +00:00
export function responseAll () {
return find(TYPE_RESPONSE, {});
}
2016-04-23 06:08:52 +00:00
// ~~~~~~~~~ //
// WORKSPACE //
// ~~~~~~~~~ //
export function workspaceCreate (patch = {}) {
return docCreate(TYPE_WORKSPACE, 'wrk', {
name: 'New Workspace',
activeRequestId: null,
2016-04-23 06:08:52 +00:00
environments: []
}, patch);
}
export function workspaceAll () {
return find(TYPE_WORKSPACE, {}).then(workspaces => {
if (workspaces.length === 0) {
workspaceCreate({name: 'Insomnia'});
return workspaceAll();
} else {
return new Promise(resolve => resolve(workspaces))
}
});
}
export function workspaceUpdate (workspace, patch) {
return docUpdate(workspace, patch);
}
export function workspaceRemove (workspace) {
return remove(workspace);
}