Skip to content

Commit 917099d

Browse files
committed
Add support for fields with MIXED type via https://github.com/taion/graphql-type-json
1 parent c71fcee commit 917099d

File tree

5 files changed

+96
-20
lines changed

5 files changed

+96
-20
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"homepage": "https://github.com/nodkz/graphql-compose-mongoose",
2626
"dependencies": {
2727
"babel-runtime": "6.11.6",
28-
"object-path": "^0.11.0"
28+
"graphql-type-json": "0.1.2",
29+
"object-path": "0.11.0"
2930
},
3031
"peerDependencies": {
3132
"graphql": ">=0.5.0 || >=0.6.0",

src/__mocks__/userModel.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,17 @@ const UserSchema = new Schema(
7070
description: 'Knowledge of languages',
7171
},
7272

73-
// createdAt, created via option `timastamp: true`
74-
75-
// updatedAt, created via option `timastamp: true`
76-
7773
__secretField: {
7874
type: String,
7975
},
76+
77+
someDynamic: {
78+
type: Schema.Types.Mixed,
79+
description: 'Some mixed value, that served with @taion\'s `graphql-type-json`',
80+
},
81+
82+
// createdAt, created via option `timastamp: true` (see bottom)
83+
// updatedAt, created via option `timastamp: true` (see bottom)
8084
},
8185
{
8286
timestamps: true, // add createdAt, updatedAt fields

src/__tests__/fieldConverter-test.js

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
/* eslint-disable no-unused-expressions */
22

33
import { expect } from 'chai';
4+
import {
5+
GraphQLString,
6+
GraphQLFloat,
7+
GraphQLBoolean,
8+
GraphQLList,
9+
GraphQLEnumType,
10+
GraphQLSchema,
11+
GraphQLObjectType,
12+
graphql,
13+
} from 'graphql';
14+
import GraphQLJSON from 'graphql-type-json';
15+
import {
16+
GraphQLDate,
17+
GraphQLBuffer,
18+
GraphQLGeneric,
19+
} from 'graphql-compose';
420
import { UserModel } from '../__mocks__/userModel.js';
521
import {
622
deriveComplexType,
@@ -12,23 +28,11 @@ import {
1228
embeddedToGraphQL,
1329
enumToGraphQL,
1430
documentArrayToGraphQL,
31+
mixedToGraphQL,
1532
} from '../fieldsConverter';
16-
17-
import {
18-
GraphQLString,
19-
GraphQLFloat,
20-
GraphQLBoolean,
21-
GraphQLList,
22-
GraphQLEnumType,
23-
} from 'graphql';
33+
import { composeWithMongoose } from '../composeWithMongoose';
2434
import GraphQLMongoID from '../types/mongoid';
2535

26-
import {
27-
GraphQLDate,
28-
GraphQLBuffer,
29-
GraphQLGeneric,
30-
} from 'graphql-compose';
31-
3236
/*
3337
Object.prototype.getClassName = function getClassName() {
3438
const funcNameRegex = /function (.{1,})\(/;
@@ -101,6 +105,10 @@ describe('fieldConverter', () => {
101105
expect(deriveComplexType(fields.gender)).not.to.equal(ComplexTypes.SCALAR);
102106
expect(deriveComplexType(fields.subDoc)).not.to.equal(ComplexTypes.SCALAR);
103107
});
108+
109+
it('schould derive MIXED mongoose type', () => {
110+
expect(deriveComplexType(fields.someDynamic)).to.equal(ComplexTypes.MIXED);
111+
});
104112
});
105113

106114
describe('convertFieldToGraphQL()', () => {
@@ -191,6 +199,53 @@ describe('fieldConverter', () => {
191199
});
192200
});
193201

202+
describe('mixedToGraphQL()', () => {
203+
let user;
204+
const UserTC = composeWithMongoose(UserModel);
205+
206+
before('add test user document to mongoDB', (done) => {
207+
user = new UserModel({
208+
name: 'nodkz',
209+
someDynamic: {
210+
a: 123,
211+
b: [1, 2],
212+
c: { c: 1 },
213+
d: null,
214+
e: 'str',
215+
},
216+
});
217+
user.save(done);
218+
});
219+
220+
it('should produce GraphQLJSON', () => {
221+
const someDynamicType = mixedToGraphQL(fields.someDynamic);
222+
expect(someDynamicType).to.equal(GraphQLJSON);
223+
});
224+
225+
it('should properly return data via graphql query', async () => {
226+
const schema = new GraphQLSchema({
227+
query: new GraphQLObjectType({
228+
name: 'Query',
229+
fields: {
230+
user: UserTC.getResolver('findById').getFieldConfig(),
231+
},
232+
}),
233+
});
234+
235+
const query = `{
236+
user(_id: "${user._id}") {
237+
name
238+
someDynamic
239+
}
240+
}`;
241+
const result = await graphql(schema, query);
242+
expect(result).deep.property('data.user.name').to.equals(user.name);
243+
expect(result)
244+
.deep.property('data.user.someDynamic')
245+
.deep.equals(user.someDynamic);
246+
});
247+
});
248+
194249
describe('referenceToGraphQL()', () => {
195250
xit('', () => {
196251

src/definition.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type connectionSortMapOpts = _connectionSortMapOpts;
88
export type ObjectMap = { [optName: string]: any };
99

1010
export type ComplexTypesT =
11-
'ARRAY' | 'EMBEDDED' | 'DOCUMENT_ARRAY' | 'ENUM' | 'REFERENCE' | 'SCALAR';
11+
'ARRAY' | 'EMBEDDED' | 'DOCUMENT_ARRAY' | 'ENUM' | 'REFERENCE' | 'MIXED' | 'SCALAR';
1212

1313
export type MongooseModelSchemaT = {
1414
paths: {

src/fieldsConverter.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
GraphQLEnumType,
2020
GraphQLObjectType,
2121
} from 'graphql';
22+
import GraphQLJSON from 'graphql-type-json';
2223
import GraphQLMongoID from './types/mongoid';
2324
import typeStorage from './typeStorage';
2425

@@ -39,6 +40,7 @@ export const ComplexTypes = {
3940
ENUM: 'ENUM',
4041
REFERENCE: 'REFERENCE',
4142
SCALAR: 'SCALAR',
43+
MIXED: 'MIXED',
4244
};
4345

4446
function _getFieldName(field: MongooseFieldT): string {
@@ -191,6 +193,7 @@ export function convertFieldToGraphQL(
191193
case ComplexTypes.ENUM: return enumToGraphQL(field, prefix);
192194
case ComplexTypes.REFERENCE: return referenceToGraphQL(field, prefix);
193195
case ComplexTypes.DOCUMENT_ARRAY: return documentArrayToGraphQL(field, prefix);
196+
case ComplexTypes.MIXED: return mixedToGraphQL(field);
194197
default: return scalarToGraphQL(field);
195198
}
196199
}
@@ -212,6 +215,8 @@ export function deriveComplexType(field: MongooseFieldT): ComplexTypesT {
212215
} else if (field instanceof mongoose.Schema.Types.Array
213216
|| objectPath.has(field, 'caster.instance')) {
214217
return ComplexTypes.ARRAY;
218+
} else if (field instanceof mongoose.Schema.Types.Mixed) {
219+
return ComplexTypes.MIXED;
215220
} else if (fieldType === 'ObjectID') {
216221
return ComplexTypes.REFERENCE;
217222
}
@@ -352,3 +357,14 @@ export function referenceToGraphQL(
352357
// this is mongo id field
353358
return scalarToGraphQL(field, prefix);
354359
}
360+
361+
export function mixedToGraphQL(
362+
field: MongooseFieldT
363+
): GraphQLOutputType {
364+
if (!(field instanceof mongoose.Schema.Types.Mixed)) {
365+
throw new Error('You provide incorrect mongoose field to `mixedToGraphQL()`. '
366+
+ 'Correct field should be instance of `mongoose.Schema.Types.Mixed`');
367+
}
368+
369+
return GraphQLJSON;
370+
}

0 commit comments

Comments
 (0)