feathers/lib/application.js
2017-10-29 13:28:23 -07:00

148 lines
3.5 KiB
JavaScript

const debug = require('debug')('feathers:application');
const { stripSlashes } = require('@feathersjs/commons');
const Uberproto = require('uberproto');
const events = require('./events');
const hooks = require('./hooks');
const version = require('./version');
const Proto = Uberproto.extend({
create: null
});
const application = {
init () {
Object.assign(this, {
version,
methods: [
'find', 'get', 'create', 'update', 'patch', 'remove'
],
mixins: [],
services: {},
providers: [],
_setup: false,
settings: {}
});
this.configure(hooks());
this.configure(events());
},
get (name) {
return this.settings[name];
},
set (name, value) {
this.settings[name] = value;
return this;
},
disable (name) {
this.settings[name] = false;
return this;
},
disabled (name) {
return !this.settings[name];
},
enable (name) {
this.settings[name] = true;
return this;
},
enabled (name) {
return !!this.settings[name];
},
configure (fn) {
fn.call(this, this);
return this;
},
service (path, service) {
if (typeof service !== 'undefined') {
throw new Error('Registering a new service with `app.service(path, service)` is no longer supported. Use `app.use(path, service)` instead.');
}
const location = stripSlashes(path);
const current = this.services[location];
if (typeof current === 'undefined' && typeof this.defaultService === 'function') {
return this.use(`/${location}`, this.defaultService(location))
.service(location);
}
return current;
},
use (path, service, options = {}) {
const location = stripSlashes(path);
const isSubApp = typeof service.service === 'function' && service.services;
const isService = this.methods.concat('setup').some(name =>
(service && typeof service[name] === 'function')
);
if (isSubApp) {
const subApp = service;
Object.keys(subApp.services).forEach(subPath =>
this.use(`${location}/${subPath}`, subApp.service(subPath))
);
return this;
}
if (!isService) {
throw new Error(`Invalid service object passed for path \`${location}\``);
}
// If the service is already Uberproto'd use it directly
const protoService = Proto.isPrototypeOf(service) ? service : Proto.extend(service);
debug(`Registering new service at \`${location}\``);
// Add all the mixins
this.mixins.forEach(fn => fn.call(this, protoService, location, options));
if (typeof protoService._setup === 'function') {
protoService._setup(this, location);
}
// Run the provider functions to register the service
this.providers.forEach(provider =>
provider.call(this, protoService, location, options)
);
// If we ran setup already, set this service up explicitly
if (this._isSetup && typeof protoService.setup === 'function') {
debug(`Setting up service for \`${location}\``);
protoService.setup(this, location);
}
this.services[location] = protoService;
return this;
},
setup () {
// Setup each service (pass the app so that they can look up other services etc.)
Object.keys(this.services).forEach(path => {
const service = this.services[path];
debug(`Setting up service for \`${path}\``);
if (typeof service.setup === 'function') {
service.setup(this, path);
}
});
this._isSetup = true;
return this;
}
};
module.exports = application;