8 Commits

Author SHA1 Message Date
fd9f7f2c0d Use knex instead of js-data 2016-11-08 22:48:32 +02:00
7c106cd843 v0.2.1 2016-11-06 19:44:57 +02:00
3163b037fc Merge pull request #24 from zalmoxisus/pass-express-app
Refactor the module
2016-11-06 19:41:52 +02:00
60d81ae52b Use the same route for any url 2016-11-06 19:40:23 +02:00
d354edac1a Refactor the module 2016-11-06 12:20:41 +02:00
25419b6bf5 Add info about the docker image and making a custom adapter 2016-11-01 20:21:43 +02:00
5e281d1b94 v0.2.0 2016-09-11 18:56:53 +03:00
f3c050ac8e Merge pull request #20 from zalmoxisus/reports
Receive reports from users and get them replicated right in the extension
2016-09-11 18:55:39 +03:00
12 changed files with 141 additions and 71 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ node_modules
.DS_Store
coverage
.idea
remotedev-db.sqlite3

View File

@ -9,6 +9,8 @@ Bridge for communicating with an application remotely via [Redux DevTools extens
npm install --save-dev remotedev-server
```
Also [there's a docker image](https://github.com/jhen0409/docker-remotedev-server) you can use.
### Usage
##### Add in your app's `package.json`:
@ -98,6 +100,8 @@ Remotedev server is database agnostic. By default everything is stored in the me
| RethinkDB | rethinkdb | `{ host: '123.456.68.987', db: 'my_db' }` | `npm install --save rethinkdbdash js-data-rethinkdb` |
| SQLite3 | sql | `{ client: 'sqlite3', connection: { host: '123.45.67.890', user: 'ubuntu', password: 'welcome1234', database: 'db1' }` | `npm install --save js-data-sql` |
Implement a [custom adapter for JSData](http://www.js-data.io/docs/working-with-adapters#custom-adapters).
### License
MIT

View File

@ -70,4 +70,4 @@ if (argv.injectserver) {
process.exit(pass ? 0 : 1);
}
require('./server')(argv);
require('../index')(argv);

6
defaultDbOptions.json Normal file
View File

@ -0,0 +1,6 @@
{
"connection": { "filename": "./remotedev-db.sqlite3" },
"client": "sqlite3",
"debug": false,
"migrate": true
}

View File

@ -1,7 +1,7 @@
var assign = require('object-assign');
var repeat = require('repeat-string');
var getOptions = require('./../lib/options');
var getPort = require('getport');
var getOptions = require('./lib/options');
var LOG_LEVEL_NONE = 0;
var LOG_LEVEL_ERROR = 1;
@ -11,7 +11,7 @@ var LOG_LEVEL_INFO = 3;
module.exports = function(argv) {
var SocketCluster = require('socketcluster').SocketCluster;
var options = assign(getOptions(argv), {
workerController: __dirname + '/../lib/worker.js',
workerController: __dirname + '/lib/worker.js',
allowClientPublish: false
});
var port = options.port;

27
lib/db/connector.js Normal file
View File

@ -0,0 +1,27 @@
var path = require('path');
var knexModule = require('knex');
module.exports = function connector(options) {
var dbOptions = options.dbOptions;
dbOptions.useNullAsDefault = true;
if (!dbOptions.migrate) {
return knexModule(dbOptions);
}
dbOptions.migrations = { directory: path.resolve(__dirname, 'migrations') };
dbOptions.seeds = { directory: path.resolve(__dirname, 'seeds') };
var knex = knexModule(dbOptions);
knex.migrate.latest()
.then(function() {
return knex.seed.run();
})
.then(function() {
console.log('Migrations are finished.');
})
.catch(function(error) {
console.error(error);
});
return knexModule(dbOptions);
};

View File

@ -0,0 +1,39 @@
exports.up = function(knex, Promise) {
return Promise.all([
knex.schema.createTable('remotedev_reports', function(table) {
table.uuid('id').primary();
table.string('type');
table.string('title');
table.string('description');
table.string('action');
table.text('payload');
table.text('preloadedState');
table.text('screenshot');
table.string('userAgent');
table.string('version');
table.string('user');
table.string('userId');
table.string('meta');
table.string('exception');
table.timestamp('added');
table.uuid('appId')
.references('id')
.inTable('remotedev_apps');
}),
knex.schema.createTable('remotedev_apps', function(table){
table.uuid('id').primary();
table.string('title');
table.string('description');
table.string('url');
table.timestamps();
})
])
};
exports.down = function(knex, Promise) {
return Promise.all([
knex.schema.dropTable('remotedev_reports'),
knex.schema.dropTable('remotedev_apps')
])
};

12
lib/db/seeds/apps.js Normal file
View File

@ -0,0 +1,12 @@
exports.seed = function(knex, Promise) {
return Promise.all([
knex('remotedev_apps').del()
]).then(function() {
return Promise.all([
knex('remotedev_apps').insert({
id: '78626c31-e16b-4528-b8e5-f81301b627f4',
title: 'Default'
})
]);
});
};

View File

@ -1,4 +1,13 @@
var path = require('path');
module.exports = function getOptions(argv) {
var dbOptions = argv.dbOptions;
if (typeof dbOptions === 'string') {
dbOptions = require(path.resolve(process.cwd(), argv.dbOptions));
} else if (typeof dbOptions === 'undefined') {
dbOptions = require('../defaultDbOptions.json');
}
return {
host: argv.hostname || process.env.npm_package_remotedev_hostname || null,
port: Number(argv.port || process.env.npm_package_remotedev_port) || 8000,
@ -8,8 +17,7 @@ module.exports = function getOptions(argv) {
cert: argv.cert || process.env.npm_package_remotedev_cert || null,
passphrase: argv.passphrase || process.env.npm_package_remotedev_passphrase || null
},
adapter: argv.adapter || process.env.npm_package_remotedev_adapter,
dbOptions: argv.dbOptions || process.env.npm_package_remotedev_db,
dbOptions: dbOptions,
logLevel: argv.logLevel || 3
};
}

View File

@ -1,11 +1,9 @@
var uuid = require('node-uuid');
var pick = require('lodash/pick');
var JSData = require('js-data');
var getAdapter = require('./adapter');
var connector = require('./db/connector');
var store;
var adapter;
var Report;
var reports = 'remotedev_reports';
var knex;
var baseFields = ['id', 'title', 'added'];
@ -15,41 +13,17 @@ function error(msg) {
});
}
function map(data, fields) {
if (!fields) return data;
return data.map(function(r) {
return pick(r, fields);
});
}
function listEvery(query) {
if (!adapter) {
return new Promise(function(resolve) {
var report = Report.filter(query);
return resolve(report);
});
}
return Report.findAll(query);
}
function list(query, fields) {
return new Promise(function(resolve) {
listEvery(query).then(function(data) {
return resolve(map(data, fields || baseFields));
});
});
knex.select().from('remotedev_apps').then(function(r){ console.log(r) });
var r = knex.select(fields || baseFields).from(reports);
if (query) return r.where(query);
return r;
}
function get(id) {
if (!id) return error('No id specified.');
if (!adapter) {
return new Promise(function(resolve) {
var report = Report.get(id);
return resolve(report);
});
}
return Report.find(id);
return knex(reports).where('id', id);
}
function add(data) {
@ -75,17 +49,11 @@ function add(data) {
user: data.user,
userId: typeof data.user === 'object' ? data.user.id : data.user,
meta: data.meta,
exception: data.exception,
added: Date.now()
exception: data.exception
};
if (!adapter) {
return new Promise(function(resolve) {
var report = Report.inject(obj);
return resolve(report);
});
}
return Report.create(obj);
return knex.insert(obj).into(reports)
.then(function (){ return byBaseFields(obj); })
}
function byBaseFields(data) {
@ -93,24 +61,12 @@ function byBaseFields(data) {
}
function createStore(options) {
var adapterName = options.adapter;
store = new JSData.DS();
if (adapterName) {
var DSAdapter = getAdapter(adapterName);
adapter = new DSAdapter(options.dbOptions);
store.registerAdapter(adapterName, adapter, { default: true });
}
Report = store.defineResource('report');
knex = connector(options);
return {
list: list,
get: get,
add: add,
selectors: {
byBaseFields: byBaseFields
}
add: add
};
}

View File

@ -14,7 +14,7 @@ module.exports.run = function(worker) {
app.set('view engine', 'ejs');
app.set('views', path.resolve(__dirname, '..', 'views'));
app.get('/', function(req, res) {
app.get('*', function(req, res) {
res.render('index', { port: worker.options.port });
});
@ -26,20 +26,29 @@ module.exports.run = function(worker) {
switch(req.body.op) {
case 'get':
store.get(req.body.id).then(function(r) {
res.send(r || {});
res.send(r[0] || {});
}).catch(function(error) {
console.error(error);
res.sendStatus(500)
});
break;
case 'list':
store.list(req.body.query, req.body.fields).then(function(r) {
res.send(r);
}).catch(function(error) {
console.error(error);
res.sendStatus(500)
});
break;
default:
store.add(req.body).then(function(r) {
res.send({ id: r.id, error: r.error });
scServer.exchange.publish('report', {
type: 'add', data: store.selectors.byBaseFields(r)
type: 'add', data: r
});
}).catch(function(error) {
console.error(error);
res.status(500).send({})
});
}
});
@ -60,6 +69,8 @@ module.exports.run = function(worker) {
if (req.channel === 'report') {
store.list().then(function(data) {
req.socket.emit(req.channel, { type: 'list', data: data });
}).catch(function(error) {
console.error(error);
});
}
});
@ -79,7 +90,9 @@ module.exports.run = function(worker) {
});
socket.on('getReport', function (id, respond) {
store.get(id).then(function(data) {
respond(null, data);
respond(null, data[0]);
}).catch(function(error) {
console.error(error);
});
});
socket.on('disconnect', function() {

View File

@ -1,15 +1,17 @@
{
"name": "remotedev-server",
"version": "0.1.7",
"version": "0.2.1",
"description": "Run the RemoteDev monitor on your local server.",
"main": "bin/server.js",
"main": "index.js",
"bin": {
"remotedev": "bin/remotedev.js"
},
"files": [
"bin",
"lib",
"views"
"views",
"index.js",
"defaultDbOptions.json"
],
"repository": {
"type": "git",
@ -33,12 +35,14 @@
"express": "^4.13.3",
"getport": "^0.1.0",
"js-data": "^2.9.0",
"knex": "^0.12.6",
"lodash": "^4.15.0",
"minimist": "^1.2.0",
"node-uuid": "^1.4.0",
"object-assign": "^4.0.0",
"repeat-string": "^1.5.4",
"semver": "^5.3.0",
"socketcluster": "^5.0.4"
"socketcluster": "^5.0.4",
"sqlite3": "^3.1.8"
}
}