diff --git a/lib/codegen/fromcto/graphql/graphqlvisitor.js b/lib/codegen/fromcto/graphql/graphqlvisitor.js index bb0f2323..a8100b3c 100644 --- a/lib/codegen/fromcto/graphql/graphqlvisitor.js +++ b/lib/codegen/fromcto/graphql/graphqlvisitor.js @@ -15,6 +15,7 @@ 'use strict'; const util = require('util'); +const { ModelUtil } = require('@accordproject/concerto-core'); /** * Convert the contents of a ModelManager to GraphQL types, based on @@ -52,7 +53,7 @@ class GraphQLVisitor { } else if (thing.isField?.()) { return this.visitField(thing, parameters); } else if (thing.isMapDeclaration?.()) { - return; + return this.visitMapDeclaration(thing, parameters); } else if (thing.isRelationship?.()) { return this.visitRelationship(thing, parameters); } else if (thing.isEnumValue?.()) { @@ -171,6 +172,28 @@ class GraphQLVisitor { return null; } + /** + * Visitor design pattern + * @param {MapDeclaration} mapDeclaration - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitMapDeclaration(mapDeclaration, parameters) { + const keyType = mapDeclaration.getKey().getType(); + const valueType = mapDeclaration.getValue().getType(); + + let key = ModelUtil.isPrimitiveType(keyType) ? this.toGraphQLType(keyType) : keyType; + let value = ModelUtil.isPrimitiveType(valueType) ? this.toGraphQLType(valueType) : valueType; + + parameters.fileWriter.writeLine(0, `type ${mapDeclaration.getName()} {`); + parameters.fileWriter.writeLine(1, `key: ${key}`); + parameters.fileWriter.writeLine(1, `value: ${value}`); + parameters.fileWriter.writeLine(0, '}'); + + return null; + } + /** * Visitor design pattern * @param {Relationship} relationship - the object being visited diff --git a/test/codegen/__snapshots__/codegen.js.snap b/test/codegen/__snapshots__/codegen.js.snap index b031ca12..08e15db8 100644 --- a/test/codegen/__snapshots__/codegen.js.snap +++ b/test/codegen/__snapshots__/codegen.js.snap @@ -632,6 +632,30 @@ type Address { dictionary5: Map5! dictionary6: Map6! } +type Map1 { + key: String + value: String +} +type Map2 { + key: String + value: DateTime +} +type Map3 { + key: String + value: SSN +} +type Map4 { + key: String + value: Concept +} +type Map5 { + key: SSN + value: String +} +type Map6 { + key: SSN + value: Employee +} type Company { name: String! headquarters: Address! @@ -5758,6 +5782,30 @@ type Address { dictionary5: Map5! dictionary6: Map6! } +type Map1 { + key: String + value: String +} +type Map2 { + key: String + value: DateTime +} +type Map3 { + key: String + value: SSN +} +type Map4 { + key: String + value: Concept +} +type Map5 { + key: SSN + value: String +} +type Map6 { + key: SSN + value: Employee +} type Company { name: String! headquarters: Address! diff --git a/test/codegen/fromcto/graphql/graphqlvisitor.js b/test/codegen/fromcto/graphql/graphqlvisitor.js index 1bf7db3a..a944000a 100644 --- a/test/codegen/fromcto/graphql/graphqlvisitor.js +++ b/test/codegen/fromcto/graphql/graphqlvisitor.js @@ -23,10 +23,14 @@ const GraphQLVisitor = require('../../../../lib/codegen/fromcto/graphql/graphqlv const ModelFile = require('@accordproject/concerto-core').ModelFile; const ModelManager = require('@accordproject/concerto-core').ModelManager; const ClassDeclaration = require('@accordproject/concerto-core').ClassDeclaration; +const MapDeclaration = require('@accordproject/concerto-core').MapDeclaration; const EnumValueDeclaration = require('@accordproject/concerto-core').EnumValueDeclaration; const Field = require('@accordproject/concerto-core').Field; const RelationshipDeclaration = require('@accordproject/concerto-core').RelationshipDeclaration; const FileWriter = require('@accordproject/concerto-util').FileWriter; +const { ModelUtil } = require('@accordproject/concerto-core'); + +let sandbox = sinon.createSandbox(); const MODEL_WITH_DECORATORS = ` namespace test @@ -339,6 +343,37 @@ describe('GraphQLVisitor', function () { }); }); + describe('visitMapDeclaration', () => { + it('should write a type for a Map', () => { + let param = { + fileWriter: mockFileWriter + }; + + sandbox.stub(ModelUtil, 'isPrimitiveType').callsFake(() => { + return true; + }); + + const mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getKeyType.returns('String'); + getValueType.returns('String'); + mockMapDeclaration.getName.returns('map1'); + mockMapDeclaration.getKey.returns({ getType: getKeyType }); + mockMapDeclaration.getValue.returns({ getType: getValueType }); + + graphQLVisitor.visitMapDeclaration(mockMapDeclaration, param); + + param.fileWriter.writeLine.withArgs(0, 'type map1 {').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, 'key: String').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, 'value: String').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(0, '}').calledOnce.should.be.ok; + + sandbox.restore(); + }); + }); + describe('visitRelationship', () => { it('should write a line for a relationship', () => { let param = {