Generated feathers app from the cli
This commit is contained in:
parent
b37f217984
commit
e078f9dbe6
|
@ -0,0 +1,13 @@
|
||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 3030,
|
||||||
|
"public": "../public/",
|
||||||
|
"paginate": {
|
||||||
|
"default": 10,
|
||||||
|
"max": 50
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"host": "uplink-app.feathersjs.com",
|
||||||
|
"port": "PORT"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@
|
||||||
"description": "Uplink receives bursts of Jenkins telemetry",
|
"description": "Uplink receives bursts of Jenkins telemetry",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
"lib": "src",
|
||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -27,17 +28,24 @@
|
||||||
"@types/jest": "^23.3.2",
|
"@types/jest": "^23.3.2",
|
||||||
"@types/winston": "^2.4.4",
|
"@types/winston": "^2.4.4",
|
||||||
"jest": "^23.5.0",
|
"jest": "^23.5.0",
|
||||||
|
"nodemon": "^1.18.4",
|
||||||
|
"request": "^2.88.0",
|
||||||
|
"request-promise": "^4.2.2",
|
||||||
"sequelize-cli": "^4.1.1",
|
"sequelize-cli": "^4.1.1",
|
||||||
"ts-jest": "^23.1.4",
|
"ts-jest": "^23.1.4",
|
||||||
"typescript": "^3.0.3"
|
"typescript": "^3.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@feathersjs/configuration": "^2.0.2",
|
"@feathersjs/configuration": "^2.0.2",
|
||||||
|
"@feathersjs/errors": "^3.3.2",
|
||||||
"@feathersjs/express": "^1.2.5",
|
"@feathersjs/express": "^1.2.5",
|
||||||
"@feathersjs/feathers": "^3.2.1",
|
"@feathersjs/feathers": "^3.2.1",
|
||||||
|
"@feathersjs/socketio": "^3.2.4",
|
||||||
|
"compression": "^1.7.3",
|
||||||
"cors": "^2.8.4",
|
"cors": "^2.8.4",
|
||||||
"feathers-sequelize": "^3.1.2",
|
"feathers-sequelize": "^3.1.2",
|
||||||
"helmet": "^3.13.0",
|
"helmet": "^3.13.0",
|
||||||
|
"serve-favicon": "^2.5.0",
|
||||||
"tslib": "^1.9.3",
|
"tslib": "^1.9.3",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"winston": "^3.1.0"
|
"winston": "^3.1.0"
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,34 @@
|
||||||
|
// Application hooks that run for every service
|
||||||
|
const log = require('./hooks/log');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
before: {
|
||||||
|
all: [ log() ],
|
||||||
|
find: [],
|
||||||
|
get: [],
|
||||||
|
create: [],
|
||||||
|
update: [],
|
||||||
|
patch: [],
|
||||||
|
remove: []
|
||||||
|
},
|
||||||
|
|
||||||
|
after: {
|
||||||
|
all: [ log() ],
|
||||||
|
find: [],
|
||||||
|
get: [],
|
||||||
|
create: [],
|
||||||
|
update: [],
|
||||||
|
patch: [],
|
||||||
|
remove: []
|
||||||
|
},
|
||||||
|
|
||||||
|
error: {
|
||||||
|
all: [ log() ],
|
||||||
|
find: [],
|
||||||
|
get: [],
|
||||||
|
create: [],
|
||||||
|
update: [],
|
||||||
|
patch: [],
|
||||||
|
remove: []
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,50 @@
|
||||||
|
const path = require('path');
|
||||||
|
const favicon = require('serve-favicon');
|
||||||
|
const compress = require('compression');
|
||||||
|
const helmet = require('helmet');
|
||||||
|
const cors = require('cors');
|
||||||
|
const logger = require('./logger');
|
||||||
|
|
||||||
|
const feathers = require('@feathersjs/feathers');
|
||||||
|
const configuration = require('@feathersjs/configuration');
|
||||||
|
const express = require('@feathersjs/express');
|
||||||
|
const socketio = require('@feathersjs/socketio');
|
||||||
|
|
||||||
|
|
||||||
|
const middleware = require('./middleware');
|
||||||
|
const services = require('./services');
|
||||||
|
const appHooks = require('./app.hooks');
|
||||||
|
const channels = require('./channels');
|
||||||
|
|
||||||
|
const app = express(feathers());
|
||||||
|
|
||||||
|
// Load app configuration
|
||||||
|
app.configure(configuration());
|
||||||
|
// Enable security, CORS, compression, favicon and body parsing
|
||||||
|
app.use(helmet());
|
||||||
|
app.use(cors());
|
||||||
|
app.use(compress());
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
app.use(favicon(path.join(app.get('public'), 'favicon.ico')));
|
||||||
|
// Host the public folder
|
||||||
|
app.use('/', express.static(app.get('public')));
|
||||||
|
|
||||||
|
// Set up Plugins and providers
|
||||||
|
app.configure(express.rest());
|
||||||
|
app.configure(socketio());
|
||||||
|
|
||||||
|
// Configure other middleware (see `middleware/index.js`)
|
||||||
|
app.configure(middleware);
|
||||||
|
// Set up our services (see `services/index.js`)
|
||||||
|
app.configure(services);
|
||||||
|
// Set up event channels (see channels.js)
|
||||||
|
app.configure(channels);
|
||||||
|
|
||||||
|
// Configure a middleware for 404s and the error handler
|
||||||
|
app.use(express.notFound());
|
||||||
|
app.use(express.errorHandler({ logger }));
|
||||||
|
|
||||||
|
app.hooks(appHooks);
|
||||||
|
|
||||||
|
module.exports = app;
|
|
@ -0,0 +1,61 @@
|
||||||
|
module.exports = function(app) {
|
||||||
|
if(typeof app.channel !== 'function') {
|
||||||
|
// If no real-time functionality has been configured just return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.on('connection', connection => {
|
||||||
|
// On a new real-time connection, add it to the anonymous channel
|
||||||
|
app.channel('anonymous').join(connection);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('login', (authResult, { connection }) => {
|
||||||
|
// connection can be undefined if there is no
|
||||||
|
// real-time connection, e.g. when logging in via REST
|
||||||
|
if(connection) {
|
||||||
|
// Obtain the logged in user from the connection
|
||||||
|
// const user = connection.user;
|
||||||
|
|
||||||
|
// The connection is no longer anonymous, remove it
|
||||||
|
app.channel('anonymous').leave(connection);
|
||||||
|
|
||||||
|
// Add it to the authenticated user channel
|
||||||
|
app.channel('authenticated').join(connection);
|
||||||
|
|
||||||
|
// Channels can be named anything and joined on any condition
|
||||||
|
|
||||||
|
// E.g. to send real-time events only to admins use
|
||||||
|
// if(user.isAdmin) { app.channel('admins').join(connection); }
|
||||||
|
|
||||||
|
// If the user has joined e.g. chat rooms
|
||||||
|
// if(Array.isArray(user.rooms)) user.rooms.forEach(room => app.channel(`rooms/${room.id}`).join(channel));
|
||||||
|
|
||||||
|
// Easily organize users by email and userid for things like messaging
|
||||||
|
// app.channel(`emails/${user.email}`).join(channel);
|
||||||
|
// app.channel(`userIds/$(user.id}`).join(channel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
app.publish((data, hook) => {
|
||||||
|
// Here you can add event publishers to channels set up in `channels.js`
|
||||||
|
// To publish only for a specific event use `app.publish(eventname, () => {})`
|
||||||
|
|
||||||
|
console.log('Publishing all events to all authenticated users. See `channels.js` and https://docs.feathersjs.com/api/channels.html for more information.'); // eslint-disable-line
|
||||||
|
|
||||||
|
// e.g. to publish all service events to all authenticated users use
|
||||||
|
return app.channel('authenticated');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Here you can also add service specific event publishers
|
||||||
|
// e.g. the publish the `users` service `created` event to the `admins` channel
|
||||||
|
// app.service('users').publish('created', () => app.channel('admins'));
|
||||||
|
|
||||||
|
// With the userid and email organization from above you can easily select involved users
|
||||||
|
// app.service('messages').publish(() => {
|
||||||
|
// return [
|
||||||
|
// app.channel(`userIds/${data.createdBy}`),
|
||||||
|
// app.channel(`emails/${data.recipientEmail}`)
|
||||||
|
// ];
|
||||||
|
// });
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
// A hook that logs service method before, after and error
|
||||||
|
// See https://github.com/winstonjs/winston for documentation
|
||||||
|
// about the logger.
|
||||||
|
const logger = require('../logger');
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
// To see more detailed messages, uncomment the following line:
|
||||||
|
// logger.level = 'debug';
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
return context => {
|
||||||
|
// This debugs the service call and a stringified version of the hook context
|
||||||
|
// You can customize the message (and logger) to your needs
|
||||||
|
logger.debug(`${context.type} app.service('${context.path}').${context.method}()`);
|
||||||
|
|
||||||
|
if(typeof context.toJSON === 'function' && logger.level === 'debug') {
|
||||||
|
logger.debug('Hook Context', util.inspect(context, {colors: false}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(context.error) {
|
||||||
|
logger.error(context.error.stack);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
const logger = require('./logger');
|
||||||
|
const app = require('./app');
|
||||||
|
const port = app.get('port');
|
||||||
|
const server = app.listen(port);
|
||||||
|
|
||||||
|
process.on('unhandledRejection', (reason, p) =>
|
||||||
|
logger.error('Unhandled Rejection at: Promise ', p, reason)
|
||||||
|
);
|
||||||
|
|
||||||
|
server.on('listening', () =>
|
||||||
|
logger.info('Feathers application started on http://%s:%d', app.get('host'), port)
|
||||||
|
);
|
|
@ -0,0 +1,16 @@
|
||||||
|
const { createLogger, format, transports } = require('winston');
|
||||||
|
|
||||||
|
// Configure the Winston logger. For the complete documentation see https://github.com/winstonjs/winston
|
||||||
|
const logger = createLogger({
|
||||||
|
// To see more detailed errors, change this to 'debug'
|
||||||
|
level: 'info',
|
||||||
|
format: format.combine(
|
||||||
|
format.splat(),
|
||||||
|
format.simple()
|
||||||
|
),
|
||||||
|
transports: [
|
||||||
|
new transports.Console()
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = logger;
|
|
@ -0,0 +1,5 @@
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
module.exports = function (app) {
|
||||||
|
// Add your custom middleware here. Remember that
|
||||||
|
// in Express, the order matters.
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
module.exports = function (app) {
|
||||||
|
};
|
|
@ -0,0 +1,55 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
const rp = require('request-promise');
|
||||||
|
const url = require('url');
|
||||||
|
const app = require('../src/app');
|
||||||
|
|
||||||
|
const port = app.get('port') || 3030;
|
||||||
|
const getUrl = pathname => url.format({
|
||||||
|
hostname: app.get('host') || 'localhost',
|
||||||
|
protocol: 'http',
|
||||||
|
port,
|
||||||
|
pathname
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Feathers application tests', () => {
|
||||||
|
before(function(done) {
|
||||||
|
this.server = app.listen(port);
|
||||||
|
this.server.once('listening', () => done());
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
|
this.server.close(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('starts and shows the index page', () => {
|
||||||
|
return rp(getUrl()).then(body =>
|
||||||
|
assert.ok(body.indexOf('<html>') !== -1)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('404', function() {
|
||||||
|
it('shows a 404 HTML page', () => {
|
||||||
|
return rp({
|
||||||
|
url: getUrl('path/to/nowhere'),
|
||||||
|
headers: {
|
||||||
|
'Accept': 'text/html'
|
||||||
|
}
|
||||||
|
}).catch(res => {
|
||||||
|
assert.equal(res.statusCode, 404);
|
||||||
|
assert.ok(res.error.indexOf('<html>') !== -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows a 404 JSON error without stack trace', () => {
|
||||||
|
return rp({
|
||||||
|
url: getUrl('path/to/nowhere'),
|
||||||
|
json: true
|
||||||
|
}).catch(res => {
|
||||||
|
assert.equal(res.statusCode, 404);
|
||||||
|
assert.equal(res.error.code, 404);
|
||||||
|
assert.equal(res.error.message, 'Page not found');
|
||||||
|
assert.equal(res.error.name, 'NotFound');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue