From fea7737301391507b8e5533093532030bccaa9bc Mon Sep 17 00:00:00 2001 From: nodkz Date: Mon, 21 Aug 2017 14:07:48 +0600 Subject: [PATCH] fix(mappingConverter): Replace invalid GraphQL characters on underscore. Related #9 --- src/__tests__/mappingConverter-test.js | 63 +++++++++++++++++++++++++- src/mappingConverter.js | 33 ++++++++------ 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/__tests__/mappingConverter-test.js b/src/__tests__/mappingConverter-test.js index bc6750f..c5d1e43 100644 --- a/src/__tests__/mappingConverter-test.js +++ b/src/__tests__/mappingConverter-test.js @@ -1,6 +1,6 @@ /* @flow */ -import { TypeComposer, GraphQLJSON, graphql } from 'graphql-compose'; +import { TypeComposer, GraphQLJSON, graphql, GQC } from 'graphql-compose'; import { convertToSourceTC, propertyToSourceGraphQLType, @@ -225,4 +225,65 @@ describe('PropertiesConverter', () => { expect(getSubFields('range')).toEqual([]); }); }); + + describe('issue #9', () => { + const mapping9 = { + properties: { + $id: { + type: 'long', + }, + lastName: { + type: 'string', + }, + email: { + type: 'string', + analyzer: 'email_analyzer', + }, + $passwordHash: { + type: 'string', + index: 'not_analyzed', + }, + }, + }; + const tc9 = convertToSourceTC(mapping9, 'Type9'); + + it('should replace unacceptable characters in GraphQL fieldnames', () => { + expect(tc9).toBeInstanceOf(TypeComposer); + expect(tc9.getFieldNames()).toEqual( + expect.arrayContaining(['_id', 'lastName', 'email', '_passwordHash']) + ); + }); + + it('should work with graphql schema without errors', () => { + GQC.rootQuery().addFields({ userES: tc9 }); + expect(() => GQC.buildSchema()).not.toThrowError(); + }); + + it('should use Elastic field names from source', async () => { + GQC.rootQuery().addFields({ userES: tc9 }); + const result = await graphql.graphql( + GQC.buildSchema(), + `query { userES { _id, lastName, email, _passwordHash } }`, + { + // simulate elastic responce + userES: { + $id: 123, + lastName: 'Tyler', + email: 'tyler@example.com', + $passwordHash: 'abc1234def', + }, + } + ); + expect(result).toEqual({ + data: { + userES: { + _id: 123, + lastName: 'Tyler', + email: 'tyler@example.com', + _passwordHash: 'abc1234def', + }, + }, + }); + }); + }); }); diff --git a/src/mappingConverter.js b/src/mappingConverter.js index b952e5a..aed8798 100644 --- a/src/mappingConverter.js +++ b/src/mappingConverter.js @@ -107,30 +107,35 @@ export function convertToSourceTC( const fields = {}; const pluralFields = opts.pluralFields || []; - Object.keys(properties).forEach(name => { - const gqType = propertyToSourceGraphQLType(properties[name], `${typeName}${upperFirst(name)}`, { - ...opts, - pluralFields: getSubFields(name, pluralFields), - }); + Object.keys(properties).forEach(sourceName => { + const fieldName = sourceName.replace(/[^_a-zA-Z0-9]/g, '_'); + const gqType = propertyToSourceGraphQLType( + properties[sourceName], + `${typeName}${upperFirst(fieldName)}`, + { + ...opts, + pluralFields: getSubFields(sourceName, pluralFields), + } + ); if (gqType) { - if (pluralFields.indexOf(name) >= 0) { - fields[name] = { + if (pluralFields.indexOf(sourceName) >= 0) { + fields[fieldName] = { type: new GraphQLList(gqType), resolve: source => { - if (Array.isArray(source[name])) { - return source[name]; + if (Array.isArray(source[sourceName])) { + return source[sourceName]; } - return [source[name]]; + return [source[sourceName]]; }, }; } else { - fields[name] = { + fields[fieldName] = { type: gqType, resolve: source => { - if (Array.isArray(source[name])) { - return source[name][0]; + if (Array.isArray(source[sourceName])) { + return source[sourceName][0]; } - return source[name]; + return source[sourceName]; }, }; }