Closed kokujin closed 8 years ago
If you set the DEBUG=feathers*
environment variable you should get a little more info. My guess is that the errors is in https://github.com/feathersjs/feathers-waterline/blob/master/src/index.js#L23 which means that data.collections.thing
is potentially undefined.
I set the mode to debug, no further information, here is the traceback
error: Route: /things - Cannot read property 'count' of undefined
info: TypeError: Cannot read property 'count' of undefined
at Object._find (/home/kokujin/development/research/fw_test/node_modules/feathers-waterline/lib/index.js:66:31)
at Object.find (/home/kokujin/development/research/fw_test/node_modules/feathers-waterline/lib/index.js:102:25)
at /home/kokujin/development/research/fw_test/node_modules/feathers-hooks/lib/hooks.js:74:31
at new Promise (/home/kokujin/development/research/fw_test/node_modules/core-js/modules/es6.promise.js:191:7)
at /home/kokujin/development/research/fw_test/node_modules/feathers-hooks/lib/hooks.js:58:16
at run (/home/kokujin/development/research/fw_test/node_modules/core-js/modules/es6.promise.js:87:22)
at /home/kokujin/development/research/fw_test/node_modules/core-js/modules/es6.promise.js:100:28
at flush (/home/kokujin/development/research/fw_test/node_modules/core-js/modules/_microtask.js:18:9)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
I logged out the Model to see if it was being created, it is.. Could it be that feathers service is having a problem wiith a waterline variant?
Are you sure that the model you are passing (data.collections.thing
) isn't undefined? To me that's the only explanation for this issue.
So it looks like you are registering the things
service twice. Once with the most likely wrong configuration in
ORM.loadCollection(Thing);
app.use('/things', service(config));
And then later with the correct settings as
app.use('/things', service({
Model: data.collections.thing,
paginate: {
default: 2,
max: 4
}
}));
It is probably trying to use the first one.
Thanks @daffl for your patience.
This is the error that gets traced using only one config, the second call using service
/home/kokujin/development/research/fw_test/src/services/things/index.js:76
thingsService.before(hooks.before);
^
TypeError: Cannot read property 'before' of undefined
at EventEmitter.module.exports (/home/kokujin/development/research/fw_test/src/services/things/index.js:76:16)
at EventEmitter.configure (/home/kokujin/development/research/fw_test/node_modules/feathers/lib/application.js:138:8)
at EventEmitter.module.exports (/home/kokujin/development/research/fw_test/src/services/index.js:13:7)
at EventEmitter.configure (/home/kokujin/development/research/fw_test/node_modules/feathers/lib/application.js:138:8)
at Object.<anonymous> (/home/kokujin/development/research/fw_test/src/app.js:30:4)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/home/kokujin/development/research/fw_test/src/index.js:3:13)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
It's because you are now retrieving the service before it is registered. Your code has to look like this:
'use strict';
const Waterline = require('waterline');
const diskAdapter = require('sails-disk');
const service = require('feathers-waterline');
const hooks = require('./hooks');
const ORM = new Waterline();
// CONFIGURATION
// ------------------------------------------------------------------------------
const config = {
adapters: {
'default': diskAdapter,
disk: diskAdapter
},
connections: {
myLocalDisk: {
adapter: 'disk'
}
},
defaults: {
migrate: 'alter'
}
};
// Model
// ------------------------------------------------------------------------------
const Thing = Waterline.Collection.extend({
identity: 'thing',
schema: true,
connection: 'myLocalDisk',
attributes: {
text: {
type: 'string',
required: true
},
complete: {
type: 'boolean'
}
}
});
// ------------------------------------------------------------------------------
module.exports = function() {
const app = this;
ORM.loadCollection(Thing);
ORM.initialize(config, function(error, data) {
//console.log(data.collections.thing);
if (error) {
console.error(error);
}
// Create a Waterline Feathers service with a default page size of 2 items
// and a maximum size of 4
app.use('/things', service({
Model: data.collections.thing,
paginate: {
default: 2,
max: 4
}
}));
// Get our initialize service to that we can bind hooks
const thingsService = app.service('/things');
//console.log('thingsService: ', thingsService);
// Set up our before hooks
thingsService.before(hooks.before);
// Set up our after hooks
thingsService.after(hooks.after);
});
};
I had tried that out too, but reverted because it causes an error
Feathers application started on localhost:3030
info: (404) Route: /things - Page not found
It's probably because you registered a notFound the asynchronous service initialization. Just like any other Express middleware the order matters so you have to make sure that any middleware that should run at the end is registered after everything else.
That cant be the case @daffl , I have 2 services scaffolded with the feathers CLI so that I can compare. Services that use NeDB and Mongoose work.
I suspect a bug, I'll have to step through the code with a debugger perhaps. You could try out the code too to verify what I am seeing.
I am using a freshly scaffolded feathers app for testing. Nothing has been modified.
NeDB and Mongoose are not initialized asynchronously so all services are registered before the not found handler. For Waterline you need to configure middleware after the asynchronous database initialization:
module.exports = function() {
const app = this;
ORM.loadCollection(Thing);
ORM.initialize(config, function(error, data) {
//console.log(data.collections.thing);
if (error) {
console.error(error);
}
// Create a Waterline Feathers service with a default page size of 2 items
// and a maximum size of 4
app.use('/things', service({
Model: data.collections.thing,
paginate: {
default: 2,
max: 4
}
}));
// Get our initialize service to that we can bind hooks
const thingsService = app.service('/things');
//console.log('thingsService: ', thingsService);
// Set up our before hooks
thingsService.before(hooks.before);
// Set up our after hooks
thingsService.after(hooks.after);
// Configure middleware here
app.configure(middleware());
// Or middleware individually
app.use(notFound);
});
};
That clunky initialization is the reason why feathers-waterline and feathers-mongodb can't be selected in the app generator at the moment.
You are right, Waterline is initialized differently, and it isindeed clunky. Thanks for your help.
The new generator creates an app that supports this initialization mode so hopefully it'll be easier to deal with then. For now you'll probably have to somehow save the state of the asynchronous initialization somewhere and then run app.configure(middleware());
(and other things that need to go last) when it completes.
That would be great, when would the new generator hit the repository?
Thanks.
I need some help using feathers-waterline with other services. I have scaffolded an app with a few services that use NeDB. I would like a particular service to use Waterline. From the docs, I came up with this:
This errors out with this trace
Can someone tell me what I am doing wrong? Thanks