diff --git a/fixture/user.js b/fixture/user.js index 65073ff..23614bb 100644 --- a/fixture/user.js +++ b/fixture/user.js @@ -8,6 +8,14 @@ let UserSchema = new mongoose.Schema({ type: Number, index: true }, + mother: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + friends: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], weight: Number, // to test "floatish" numbers createdAt: Date, removed: Boolean, @@ -15,10 +23,6 @@ let UserSchema = new mongoose.Schema({ strings: [String], bools: [Boolean], dates: [Date], - friends: [{ - type: mongoose.Schema.Types.ObjectId, - ref: 'User' - }], sub: { foo: String, nums: [Number], diff --git a/package.json b/package.json index 1327f24..8bf223e 100644 --- a/package.json +++ b/package.json @@ -32,15 +32,15 @@ "lodash": "^3.10.0" }, "devDependencies": { - "babel": "^5.8.19", - "babel-eslint": "^3.1.26", + "babel": "^5.8.20", + "babel-eslint": "^4.0.5", "chai": "^3.2.0", "chai-subset": "^1.0.1", "co-mocha": "^1.1.2", - "eslint": "1.0.0-rc-3", + "eslint": "1.0.0", "mocha": "^2.2.5", "mongoose": "^4.0.6", - "pre-commit": "^1.0.10", + "pre-commit": "^1.1.1", "sinon": "^1.15.4", "sinon-chai": "^2.8.0" }, diff --git a/src/e2e.spec.js b/src/e2e.spec.js index 633ea80..c5954b2 100644 --- a/src/e2e.spec.js +++ b/src/e2e.spec.js @@ -32,6 +32,7 @@ describe('e2e', () => { }); describe('get schema', () => { + let motherUser; let user1; let user2; let schema; @@ -39,6 +40,13 @@ describe('e2e', () => { beforeEach(function* () { schema = getSchema([User]); + motherUser = new User({ + name: 'Mother', + age: 54 + }); + + yield motherUser.save(); + user1 = new User({ name: 'Foo', age: 28 @@ -49,6 +57,7 @@ describe('e2e', () => { user2 = new User({ name: 'Bar', age: 28, + mother: motherUser._id, friends: [user1._id] }); @@ -56,7 +65,7 @@ describe('e2e', () => { }); afterEach(function* () { - yield [user1.remove(), user2.remove()]; + yield [motherUser.remove(), user1.remove(), user2.remove()]; }); it('should generate schema from mongoose models', () => { @@ -77,6 +86,10 @@ describe('e2e', () => { _id name age + mother { + _id + name + } friends { _id name @@ -90,6 +103,10 @@ describe('e2e', () => { _id: user2._id.toString(), name: 'Bar', age: 28, + mother: { + _id: motherUser._id.toString(), + name: 'Mother' + }, friends: [{ _id: user1._id.toString(), name: 'Foo' diff --git a/src/field.js b/src/field.js index 6ad2f67..54493b2 100644 --- a/src/field.js +++ b/src/field.js @@ -1,4 +1,5 @@ import {isDate} from 'lodash'; +import ObjectID from 'bson-objectid'; import { GraphQLString, @@ -44,8 +45,28 @@ function getField(field, types, models, model) { var refModelName; + // ObjectID + if (field.instance === 'ObjectID') { + + // with reference + if (field.ref) { + graphQLfield.description += ` and reference to "${field.ref}" model`; + + graphQLfield.type = types[field.ref]; + graphQLfield.resolve = (modelInstance, params, source, fieldASTs) => { + var projections = getProjection(fieldASTs); + + return models[field.ref].model.findOne({ + _id: new ObjectID(modelInstance[field.name]) + }, projections); + }; + } else { + graphQLfield.type = GraphQLString; + } + } + // String - if (['String', 'ObjectID'].indexOf(field.instance) > -1) { + else if (field.instance === 'String') { graphQLfield.type = GraphQLString; } @@ -107,7 +128,7 @@ function getField(field, types, models, model) { // Object else if (field.instance === 'Object') { - console.log(field.instance); + // TODO: implement } return graphQLfield; diff --git a/src/model.js b/src/model.js index feacab6..c75976c 100644 --- a/src/model.js +++ b/src/model.js @@ -16,14 +16,29 @@ function getField (schemaPath) { indexed: options.index ? true : false }; + // Field options + if (schemaPath.options) { + + // ObjectID ref + if (schemaPath.options.ref) { + field.ref = schemaPath.options.ref; + } + } + + // Caster if (schemaPath.caster) { field.caster = { path: schemaPath.caster.path, instance: schemaPath.caster.instance }; - if (schemaPath.caster.options && schemaPath.caster.options.ref) { - field.caster.ref = schemaPath.caster.options.ref; + // Caster options + if (schemaPath.caster.options) { + + // ObjectID ref + if (schemaPath.caster.options.ref) { + field.caster.ref = schemaPath.caster.options.ref; + } } } diff --git a/src/schema.spec.js b/src/schema.spec.js index 5ce54d7..80cf441 100644 --- a/src/schema.spec.js +++ b/src/schema.spec.js @@ -146,7 +146,56 @@ describe('schema', () => { }); }); - it('should get data with ref fields', function* () { + it.only('should get data with ref fields', function* () { + var mother = new User({ + name: 'Mother' + }); + + var user = new User({ + name: 'User', + mother: mother + }); + + var findOneStub = this.sandbox.stub(User, 'findOne'); + + findOneStub.onFirstCall().returns(Promise.resolve(user)); + findOneStub.onSecondCall().returns(Promise.resolve(mother)); + + var result = yield graphql(schema, `{ + user(_id: "${user._id}") { + name + mother { + name + } + } + }`); + + // FIXME: "Cannot read property 'map' of undefined" + // expect(findOneStub).to.calledWith({ + // _id: new ObjectID(user._id.toString()) + // }, { + // name: 1 + // }); + // + // expect(findOneStub).to.calledWith({ + // _id: new ObjectID(mother._id.toString()) + // }, { + // name: 1 + // }); + + expect(result).to.be.eql({ + data: { + user: { + name: 'User', + mother: { + name: 'Mother' + } + } + } + }); + }); + + it('should get data with array of ref(s) fields', function* () { var user1 = new User({ name: 'Foo' }); @@ -156,7 +205,7 @@ describe('schema', () => { friends: [user1._id] }); - var findByIdStub = this.sandbox.stub(User, 'findOne').returnsWithResolve(user2); + var findOneStub = this.sandbox.stub(User, 'findOne').returnsWithResolve(user2); var findStub = this.sandbox.stub(User, 'find').returnsWithResolve([user1]); var result = yield graphql(schema, `{ @@ -168,7 +217,7 @@ describe('schema', () => { } }`); - expect(findByIdStub).to.calledWith({ + expect(findOneStub).to.calledWith({ _id: new ObjectID(user2._id.toString()) }, { name: 1,