1 | const debug = require('debug')('feathers:application');
|
2 | const { stripSlashes } = require('@feathersjs/commons');
|
3 |
|
4 | const Uberproto = require('uberproto');
|
5 | const events = require('./events');
|
6 | const hooks = require('./hooks');
|
7 | const version = require('./version');
|
8 |
|
9 | const Proto = Uberproto.extend({
|
10 | create: null
|
11 | });
|
12 |
|
13 | const application = {
|
14 | init () {
|
15 | Object.assign(this, {
|
16 | version,
|
17 | methods: [
|
18 | 'find', 'get', 'create', 'update', 'patch', 'remove'
|
19 | ],
|
20 | mixins: [],
|
21 | services: {},
|
22 | providers: [],
|
23 | _setup: false,
|
24 | settings: {}
|
25 | });
|
26 |
|
27 | this.configure(hooks());
|
28 | this.configure(events());
|
29 | },
|
30 |
|
31 | get (name) {
|
32 | return this.settings[name];
|
33 | },
|
34 |
|
35 | set (name, value) {
|
36 | this.settings[name] = value;
|
37 | return this;
|
38 | },
|
39 |
|
40 | disable (name) {
|
41 | this.settings[name] = false;
|
42 | return this;
|
43 | },
|
44 |
|
45 | disabled (name) {
|
46 | return !this.settings[name];
|
47 | },
|
48 |
|
49 | enable (name) {
|
50 | this.settings[name] = true;
|
51 | return this;
|
52 | },
|
53 |
|
54 | enabled (name) {
|
55 | return !!this.settings[name];
|
56 | },
|
57 |
|
58 | configure (fn) {
|
59 | fn.call(this, this);
|
60 |
|
61 | return this;
|
62 | },
|
63 |
|
64 | service (path, service) {
|
65 | if (typeof service !== 'undefined') {
|
66 | throw new Error('Registering a new service with `app.service(path, service)` is no longer supported. Use `app.use(path, service)` instead.');
|
67 | }
|
68 |
|
69 | const location = stripSlashes(path) || '/';
|
70 | const current = this.services[location];
|
71 |
|
72 | if (typeof current === 'undefined' && typeof this.defaultService === 'function') {
|
73 | return this.use(location, this.defaultService(location))
|
74 | .service(location);
|
75 | }
|
76 |
|
77 | return current;
|
78 | },
|
79 |
|
80 | use (path, service, options = {}) {
|
81 | if (typeof path !== 'string') {
|
82 | throw new Error(`'${path}' is not a valid service path.`);
|
83 | }
|
84 |
|
85 | const location = stripSlashes(path) || '/';
|
86 | const isSubApp = typeof service.service === 'function' && service.services;
|
87 | const isService = this.methods.concat('setup').some(name => typeof service[name] === 'function');
|
88 |
|
89 | if (isSubApp) {
|
90 | const subApp = service;
|
91 |
|
92 | Object.keys(subApp.services).forEach(subPath =>
|
93 | this.use(`${location}/${subPath}`, subApp.service(subPath))
|
94 | );
|
95 |
|
96 | return this;
|
97 | }
|
98 |
|
99 | if (!isService) {
|
100 | throw new Error(`Invalid service object passed for path \`${location}\``);
|
101 | }
|
102 |
|
103 |
|
104 | const protoService = Proto.isPrototypeOf(service) ? service : Proto.extend(service);
|
105 |
|
106 | debug(`Registering new service at \`${location}\``);
|
107 |
|
108 |
|
109 | this.mixins.forEach(fn => fn.call(this, protoService, location, options));
|
110 |
|
111 | if (typeof protoService._setup === 'function') {
|
112 | protoService._setup(this, location);
|
113 | }
|
114 |
|
115 |
|
116 | this.providers.forEach(provider =>
|
117 | provider.call(this, protoService, location, options)
|
118 | );
|
119 |
|
120 |
|
121 | if (this._isSetup && typeof protoService.setup === 'function') {
|
122 | debug(`Setting up service for \`${location}\``);
|
123 | protoService.setup(this, location);
|
124 | }
|
125 |
|
126 | this.services[location] = protoService;
|
127 |
|
128 | return this;
|
129 | },
|
130 |
|
131 | setup () {
|
132 |
|
133 | Object.keys(this.services).forEach(path => {
|
134 | const service = this.services[path];
|
135 |
|
136 | debug(`Setting up service for \`${path}\``);
|
137 |
|
138 | if (typeof service.setup === 'function') {
|
139 | service.setup(this, path);
|
140 | }
|
141 | });
|
142 |
|
143 | this._isSetup = true;
|
144 |
|
145 | return this;
|
146 | }
|
147 | };
|
148 |
|
149 | module.exports = application;
|