diff --git a/README.md b/README.md index b426de7..9ffa652 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ import { GraphQLToLowerDirective, GraphQLToUpperDirective, GraphQLTemplateDirective, - applySchemaCustomDirectives + GraphQLPhoneDirective, + applySchemaCustomDirectives, } from 'graphql-custom-directives'; const query = new GraphQLObjectType({ @@ -66,6 +67,7 @@ const schema = new GraphQLSchema({ GraphQLDefaultToDirective, GraphQLToLowerDirective, GraphQLToUpperDirective, + GraphQLPhoneDirective, GraphQLTemplateDirective ], query @@ -100,6 +102,7 @@ import { GraphQLToLowerDirective, GraphQLToUpperDirective, GraphQLTemplateDirective, + GraphQLPhoneDirective applySchemaCustomDirectives } from 'graphql-custom-directives'; @@ -117,7 +120,8 @@ let directives = [ GraphQLDefaultToDirective, GraphQLToLowerDirective, GraphQLToUpperDirective, - GraphQLTemplateDirective + GraphQLTemplateDirective, + GraphQLPhoneDirective ] let schema = makeExecutableSchema(...); @@ -291,6 +295,30 @@ Adding string directive to graphql query for formatting the result using [Lodash // => { input: "FOO BAR FOO BAR" } ``` +### Phone formatting directives + +Adding phone directive to graphql query for formatting the result using [libphonenumber-js](https://github.com/catamphetamine/libphonenumber-js). + +- Using default international format: +```javascript + query { + input(value: "+12133734253") @phone + } + // => { input: "+1 213 373 4253" } +``` +- Using specific format: +```javascript + query { + input(value: "+12133734253") @phone(as: "national") + } +// => { input: "(213) 373-4253" } + query { + input(value: "+12133734253") @phone(as: "RFC3966") + } +// => { input: "tel:+12133734253" } // URI format +``` + + ### License ``` The MIT License (MIT) diff --git a/package.json b/package.json index 46af419..a1491ac 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "dependencies": { "moment": "^2.22.2", "numeral": "^2.0.6", - "lodash": "^4.17.5" + "lodash": "^4.17.5", + "libphonenumber-js": "^1.6.4" }, "peerDependencies": { "graphql": "*" diff --git a/src/directives/phone.js b/src/directives/phone.js new file mode 100644 index 0000000..2a5930d --- /dev/null +++ b/src/directives/phone.js @@ -0,0 +1,31 @@ +import {GraphQLString} from 'graphql'; +import {DirectiveLocation} from '../directiveLocation'; +import {GraphQLCustomDirective} from '../custom'; + +import { parsePhoneNumber } from 'libphonenumber-js' + +exports.GraphQLPhoneDirective = new GraphQLCustomDirective({ + name: 'phone', + description: 'Format the phone value from resolving the field', + locations: [DirectiveLocation.FIELD], + args: { + as: { + type: GraphQLString, + description: 'A phone format (NATIONAL, INTERNATIONAL, RFC3966)', + }, + }, + resolve(resolve, source, {as}) { + return resolve().then(input => { + try { + const phoneNumber = parsePhoneNumber(input); + if (as) { + return phoneNumber.format(as.toUpperCase()); + } + return phoneNumber.formatInternational(); + } catch (e) { + // In case of wrong format return the original value + return input + } + }); + }, +}); diff --git a/src/index.js b/src/index.js index 072e224..6f8be33 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,8 @@ import { import {GraphQLNumberDirective} from './directives/number'; +import {GraphQLPhoneDirective} from './directives/phone'; + import {GraphQLCurrencyDirective} from './directives/currency'; import { @@ -43,3 +45,4 @@ exports.GraphQLToLowerDirective = GraphQLToLowerDirective; exports.GraphQLToUpperDirective = GraphQLToUpperDirective; exports.GraphQLTemplateDirective = GraphQLTemplateDirective; exports.GraphQLTimeOffsetDirective = GraphQLTimeOffsetDirective; +exports.GraphQLPhoneDirective = GraphQLPhoneDirective; diff --git a/test/directives/phone.js b/test/directives/phone.js new file mode 100644 index 0000000..b8063f5 --- /dev/null +++ b/test/directives/phone.js @@ -0,0 +1,82 @@ +import {GraphQLPhoneDirective} from '../../src/index'; +import {testEqual} from '../utils'; + +import {expect} from 'chai'; + +describe('directives/currency', () => { + it('expected to have name property', () => { + expect(GraphQLPhoneDirective.name).to.a('string'); + }); + + it('expected to have description property', () => { + expect(GraphQLPhoneDirective.description).to.a('string'); + }); + + it('expected to have args properties', () => { + expect(GraphQLPhoneDirective.args).to.a('array'); + }); + + it('expected to have locations list', () => { + expect(GraphQLPhoneDirective.locations).to.a('array'); + }); + + it('expected to have resolve function', () => { + expect(GraphQLPhoneDirective.resolve).to.be.function; + }); + + it('expected regular execution of graphql', done => { + const query = `{ value }`, + directives = [GraphQLPhoneDirective], + expected = {value: null}; + testEqual({directives, query, expected, done}); + }); + + it('expected regular execution of graphql in case of wrong format', done => { + const query = `{ value(input: "abc") @phone }`, + directives = [GraphQLPhoneDirective], + expected = {value: 'abc'}; + testEqual({directives, query, expected, done}); + }); + + + it('expected directive to alter execution of graphql and result international formatted phone as default', done => { + const query = `{ value(input: "+12133734253") @phone }`, + directives = [GraphQLPhoneDirective], + expected = {value: '+1 213 373 4253'}; + + testEqual({directives, query, expected, done}); + }); + + it('expected directive to alter execution of graphql and result international formatted phone', done => { + const query = `{ value(input: "+12133734253") @phone(as: "INTERNATIONAL") }`, + directives = [GraphQLPhoneDirective], + expected = {value: '+1 213 373 4253'}; + + testEqual({directives, query, expected, done}); + }); + + it('expected directive to alter execution of graphql and result uri formatted phone', done => { + const query = `{ value(input: "+12133734253") @phone(as: "RFC3966") }`, + directives = [GraphQLPhoneDirective], + expected = {value: 'tel:+12133734253'}; + + testEqual({directives, query, expected, done}); + }); + + it('expected directive to alter execution of graphql and result national formatted phone', done => { + const query = `{ value(input: "+12133734253") @phone(as: "NATIONAL") }`, + directives = [GraphQLPhoneDirective], + expected = {value: '(213) 373-4253'}; + + testEqual({directives, query, expected, done}); + }); + + + it('expected directive to alter execution of graphql and result the original value', done => { + const query = `{ value(input: "test") @phone }`, + directives = [GraphQLPhoneDirective], + expected = {value: 'test'}; + + testEqual({directives, query, expected, done}); + }); +});