Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

feat: integration with feathers v3 and feathers-cli #212

Closed
wants to merge 12 commits into from
Closed
26 changes: 20 additions & 6 deletions template/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
"version": "1.0.0",
"description": "<%= description %>",
"author": "<%= author %>",
"private": true,
"private": true,<% if (server === 'feathers') { %>
"directories": {
"lib": "server",
"config": "server/config",
"test": "server/test"
}, <% } %>
"scripts": {<% if (server === 'adonis') { %>
"serve:dev": "<%= pm %> run dev",
"dev": "nodemon --watch app --watch bootstrap --watch config --watch .env -x node server.js",
Expand All @@ -15,7 +20,8 @@
"generate": "nuxt generate"<% } %><% if (eslint === 'yes') { %>,
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"precommit": "<%= pm %> run lint"<% } %><% if (test !== 'none') { %>,
"test": "<%= test %>"<% } %>
"test": "<%= test %>"<% } %><% if (server === 'feathers') { %>,
"feathers": "feathers"<% } %>
},
"dependencies": {
"cross-env": "^5.2.0"<% if (edge) { %>,
Expand All @@ -27,9 +33,16 @@
"micro": "^9.3.3",
"micro-route": "^2.5.0"<% } else if (server === 'fastify') { %>,
"fastify": "^1.13.3"<% } else if (server === 'feathers') { %>,
"@feathersjs/feathers": "^3.3.1",
"@feathersjs/express": "^1.3.1",
"@feathersjs/configuration": "^2.0.6"<% } else if (server === 'adonis') { %>,
"@feathersjs/client": "^3.7.3",
"@feathersjs/configuration": "^2.0.4",
"@feathersjs/errors": "^3.3.4",
"@feathersjs/express": "^1.2.7",
"@feathersjs/feathers": "^3.2.3",
"@feathersjs/socketio": "^3.2.6",
"compression": "^1.7.3",
"consola": "^1.4.3",
"cors": "^2.8.4",
"helmet": "^3.13.0"<% } else if (server === 'adonis') { %>,
"@adonisjs/ace": "^4.0.7",
"@adonisjs/auth": "^2.0.10",
"@adonisjs/bodyparser": "^1.0.8",
Expand All @@ -54,7 +67,8 @@
"tachyons": "^4.11.1"<% } %>
},
"devDependencies": {
"nodemon": "^1.18.9"<% if (eslint === 'yes') { %>,
"nodemon": "^1.18.9"<% if (server === 'feathers') { %>,
"@feathersjs/cli": "^3.8.5"<% } %><% if (eslint === 'yes') { %>,
"@nuxtjs/eslint-config": "^0.0.1",
"babel-eslint": "^10.0.1",
"eslint": "^5.15.1",
Expand Down
34 changes: 34 additions & 0 deletions template/frameworks/feathers/server/app.hooks.js
Original file line number Diff line number Diff line change
@@ -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: []
}
};
46 changes: 46 additions & 0 deletions template/frameworks/feathers/server/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const compress = require('compression');
const helmet = require('helmet');
const cors = require('cors');
const logger = require('./logger');

const path = require('path');
process.env['NODE_CONFIG_DIR'] = path.join(__dirname, 'config/');

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 and body parsing
app.use(helmet());
app.use(cors());
app.use(compress());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 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 error handler
app.use(express.errorHandler({ logger }));

app.hooks(appHooks);

module.exports = app;
61 changes: 61 additions & 0 deletions template/frameworks/feathers/server/channels.js
Original file line number Diff line number Diff line change
@@ -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}`)
// ];
// });
};
7 changes: 5 additions & 2 deletions template/frameworks/feathers/server/config/default.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"host": "localhost",
"port": 3000
"port": 3000,
"paginate": {
"default": 10,
"max": 50
}
}
2 changes: 0 additions & 2 deletions template/frameworks/feathers/server/config/production.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
{
"host": "with-featherjs-app.feathersjs.com",
"port": 80
}
21 changes: 21 additions & 0 deletions template/frameworks/feathers/server/hooks/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// A hook that logs service method before, after and error
const util = require('util');
const consola = require('../logger');

module.exports = function() {
return context => {
// This debugs the service call and a stringified version of the hook context
// You can customize the message to your needs
consola.debug(
`${context.type} app.service('${context.path}').${context.method}()`
);

if (typeof context.toJSON === 'function') {
consola.debug('Hook Context', util.inspect(context, { colors: false }));
}

if (context.error && !context.result) {
consola.error(context.error);
}
};
};
52 changes: 22 additions & 30 deletions template/frameworks/feathers/server/index.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,34 @@
'use strict'
const path = require('path')
const consola = require('consola')
const feathers = require('@feathersjs/feathers')
const express = require('@feathersjs/express')
const consola = require('consola');
const { Nuxt, Builder } = require('nuxt');
const app = require('./app');
const host = process.env.HOST || '127.0.0.1';
const port = process.env.PORT || 3000;

process.env.NODE_CONFIG_DIR = path.join(__dirname, 'config/')
app.set('port', port);

async function start() {
const app = express(feathers())

const { Nuxt, Builder } = require('nuxt<% if (edge) { %>-edge<% } %>')
// Import and Set Nuxt.js options
let config = require('../nuxt.config.js');
config.dev = !(process.env.NODE_ENV === 'production');

// Setup nuxt.js
const config = require('../nuxt.config.js')
config.rootDir = path.resolve(__dirname, '..')
config.dev = process.env.NODE_ENV !== 'production'
async function start() {
// Init Nuxt.js
const nuxt = new Nuxt(config);

const nuxt = new Nuxt(config)
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
} else {
await nuxt.ready()
const builder = new Builder(nuxt);
await builder.build();
}

const configuration = require('@feathersjs/configuration')
app.configure(configuration()).use(nuxt.render)

const host = app.get('host')
const port = app.get('port')

app.listen(port)
// Give nuxt middleware to express
app.use(nuxt.render);

// Listen the server
app.listen(port, host);
consola.ready({
message: `Feathers application started on ${host}:${port}`,
message: `Server listening on http://${host}:${port}`,
badge: true
})
});
}

start()

start();
9 changes: 9 additions & 0 deletions template/frameworks/feathers/server/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { Consola, FancyReporter } = require('consola');

const logger = new Consola({
level: 3, // Info level
reporters: [new FancyReporter()],
types: []
});

module.exports = logger;
5 changes: 5 additions & 0 deletions template/frameworks/feathers/server/middleware/index.js
Original file line number Diff line number Diff line change
@@ -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.
};
2 changes: 2 additions & 0 deletions template/frameworks/feathers/server/services/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-unused-vars
module.exports = function(app) {};
27 changes: 24 additions & 3 deletions test/snapshots/index.test.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,16 @@ Generated by [AVA](https://ava.li).
'pages/README.md',
'pages/index.vue',
'plugins/README.md',
'server/app.hooks.js',
'server/app.js',
'server/channels.js',
'server/config/default.json',
'server/config/production.json',
'server/hooks/log.js',
'server/index.js',
'server/logger.js',
'server/middleware/index.js',
'server/services/index.js',
'static/README.md',
'static/favicon.ico',
'store/README.md',
Expand All @@ -323,19 +330,33 @@ Generated by [AVA](https://ava.li).

{
dependencies: {
'@feathersjs/configuration': '^2.0.6',
'@feathersjs/express': '^1.3.1',
'@feathersjs/feathers': '^3.3.1',
'@feathersjs/client': '^3.7.3',
'@feathersjs/configuration': '^2.0.4',
'@feathersjs/errors': '^3.3.4',
'@feathersjs/express': '^1.2.7',
'@feathersjs/feathers': '^3.2.3',
'@feathersjs/socketio': '^3.2.6',
compression: '^1.7.3',
consola: '^1.4.3',
cors: '^2.8.4',
'cross-env': '^5.2.0',
helmet: '^3.13.0',
nuxt: '^2.4.0',
},
devDependencies: {
'@feathersjs/cli': '^3.8.5',
nodemon: '^1.18.9',
},
directories: {
config: 'server/config',
lib: 'server',
test: 'server/test',
},
private: true,
scripts: {
build: 'nuxt build',
dev: 'cross-env NODE_ENV=development nodemon server/index.js --watch server',
feathers: 'feathers',
generate: 'nuxt generate',
start: 'cross-env NODE_ENV=production node server/index.js',
},
Expand Down
Binary file modified test/snapshots/index.test.js.snap
Binary file not shown.