Skip to content

Commit

Permalink
feature: rework type generation [breaking]
Browse files Browse the repository at this point in the history
- make apis provided by the generated schema as stable as possible (introduce namespaces for types, don't return only the first operation output message part, fallback to GraphQLJSON on generation errors and incompatible xsd to preserve a working (but partly untyped) schema).
- Set a more versatile foundation for additional xsd features which can be implemented later without breaking changes.
- Fix errors around the type resolution in different namespaces.
- Remove the usage of node-soap's service descriptions because they are incomplete. Unfortunately node-soap seems to rely on them too which leads to some bugs.
- Remove specs which don't work anymore because of removed WSDL sources

Fixes #16 and partially #17 and #18
  • Loading branch information
henkesn committed Jun 28, 2023
1 parent 1f3ff4d commit 4d3499f
Show file tree
Hide file tree
Showing 9 changed files with 527 additions and 664 deletions.
241 changes: 20 additions & 221 deletions spec/node-soap-graphql.spec.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,14 @@
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import { expect } from 'chai';
import { after, afterEach, before, beforeEach, describe, fail, it, xit } from 'mocha';
import * as chaiAsPromised from 'chai-as-promised';
import { describe, it, xit } from 'mocha';
import { GraphQLSchema } from 'graphql/type/schema';
import { getIntrospectionQuery } from 'graphql';
import {
graphql,
printSchema,
GraphQLInputType,
GraphQLEnumType,
GraphQLEnumValueConfigMap,
} from 'graphql';
import { inspect } from 'util';
import { GraphQLBoolean } from 'graphql/type/scalars';
import {
soapGraphqlSchema,
SoapCallInput,
CustomTypeResolver,
DefaultTypeResolver,
SoapGraphqlOptions,
NodeSoapClient,
SoapCaller,
NodeSoapCaller,
createSoapClient,
createLogger,
} from '../index';
import { getIntrospectionQuery, graphql } from 'graphql';
import { SoapGraphqlOptions, soapGraphqlSchema } from '../index';

chai.use(chaiAsPromised);

describe('call soap endpoints', () => {
xit('http://www.webservicex.net/geoipservice.asmx?WSDL', async () => {
await queryEndpoint(
{ createClient: { url: 'http://www.webservicex.net/geoipservice.asmx?WSDL' } },
`
mutation {
GetGeoIP(IPAddress: "74.125.224.72") {
IP
ReturnCode
}
}
`,
(data) => {
expect(data.GetGeoIP.IP).to.exist;
expect(data.GetGeoIP.IP).to.equal('74.125.224.72');
expect(data.GetGeoIP.ReturnCode).to.exist;
expect(data.GetGeoIP.ReturnCode).to.equal(1);
},
);
}).timeout(5000);

it('http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl', async () => {
await queryEndpoint(
{ createClient: { url: 'http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl' } },
`
mutation {
ResolveIP(ipAddress: "74.125.224.72", licenseKey: "") {
Latitude
Longitude
AreaCode
}
}
`,
(data) => {
expect(data.ResolveIP).to.exist;
expect(data.ResolveIP.Latitude).to.exist;
expect(data.ResolveIP.Longitude).to.exist;
expect(data.ResolveIP.AreaCode).to.exist;
},
);
}).timeout(5000);

xit('http://www.webservicex.net/globalweather.asmx?WSDL', async () => {
await queryEndpoint(
{ createClient: { url: 'http://www.webservicex.net/globalweather.asmx?WSDL' } },
`
mutation {
GetCitiesByCountry(CountryName: "Germany")
}
`,
(data) => {
expect(data.GetCitiesByCountry).to.exist;
expect(data.GetCitiesByCountry).to.include('<City>Wunstorf</City>');
},
);
}).timeout(5000);

xit('http://www.webservicex.net/periodictable.asmx?WSDL', async () => {
await queryEndpoint(
{ createClient: { url: 'http://www.webservicex.net/periodictable.asmx?WSDL' } },
`
mutation {
atoms: GetAtoms
atoms2: GetAtoms
}
`,
(data) => {
expect(data.atoms).to.exist;
expect(data.atoms2).to.exist;
expect(data.atoms).to.include('<ElementName>Aluminium</ElementName>');
expect(data.atoms2).to.include('<ElementName>Aluminium</ElementName>');
},
);
}).timeout(5000);

it('http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL', async () => {
await queryEndpoint(
{
Expand All @@ -111,7 +17,7 @@ describe('call soap endpoints', () => {
},
},
`
fragment CountryInfo on TCountryInfo {
fragment CountryInfo on OorsprongOrgWebsamplesCountryinfo_TCountryInfo {
sName
sCurrencyISOCode
Languages {
Expand All @@ -124,17 +30,19 @@ describe('call soap endpoints', () => {
mutation {
FullCountryInfo(sCountryISOCode: "PL") {
...CountryInfo
FullCountryInfoResult {
...CountryInfo
}
}
}
`,
(data) => {
expect(data.FullCountryInfo).to.exist;
expect(data.FullCountryInfo.sName).to.equal('Poland');
expect(data.FullCountryInfo.sCurrencyISOCode).to.equal('PLN');
expect(data.FullCountryInfo.Languages).to.exist;
expect(data.FullCountryInfo.Languages.tLanguage).to.exist;
expect(data.FullCountryInfo.Languages.tLanguage[0]).to.exist;
expect(data.FullCountryInfo.FullCountryInfoResult).to.exist;
expect(data.FullCountryInfo.FullCountryInfoResult.sName).to.equal('Poland');
expect(data.FullCountryInfo.FullCountryInfoResult.sCurrencyISOCode).to.equal('PLN');
expect(data.FullCountryInfo.FullCountryInfoResult.Languages).to.exist;
expect(data.FullCountryInfo.FullCountryInfoResult.Languages.tLanguage).to.exist;
expect(data.FullCountryInfo.FullCountryInfoResult.Languages.tLanguage[0]).to.exist;
},
);
}).timeout(5000);
Expand All @@ -148,125 +56,16 @@ describe('call soap endpoints', () => {
},
`
mutation {
NumberToWords(ubiNum: 1234)
}
`,
(data) => {
expect(data.NumberToWords).to.exist;
expect(data.NumberToWords).to.equal('one thousand two hundred and thirty four');
},
);
}).timeout(5000);

xit('http://www.webservicex.net/Astronomical.asmx?WSDL', async () => {
class AstronomicalResolver extends DefaultTypeResolver {
inputType(typeName: string): GraphQLInputType {
if (
typeName === 'string|meters,kilometers,miles,AstronmicalunitAU,lightyear,parsec'
) {
return new GraphQLEnumType({
name: 'AstronomicalUnit',
values: {
meters: {},
kilometers: {},
miles: {},
AstronmicalunitAU: {},
lightyear: {},
parsec: {},
},
});
}
return super.inputType(typeName);
}
}

await queryEndpoint(
{
createClient: { url: 'http://www.webservicex.net/Astronomical.asmx?WSDL' },
schemaOptions: { customResolver: new AstronomicalResolver() },
},
`
mutation {
ChangeAstronomicalUnit(AstronomicalValue: 1.24, fromAstronomicalUnit: lightyear, toAstronomicalUnit: parsec)
}
`,
(data) => {
expect(data.ChangeAstronomicalUnit).to.exist;
expect(data.ChangeAstronomicalUnit).to.equal(0.3801865856585023);
},
);
}).timeout(5000);

xit('http://www.webservicex.net/CurrencyConvertor.asmx?WSDL', async () => {
class CurrencyResolver extends DefaultTypeResolver {
inputType(typeName: string): GraphQLInputType {
if (
!!typeName &&
typeName.startsWith('string|AFA,ALL,DZD,ARS,AWG,AUD,BSD,BHD,BDT,BBD')
) {
const values: GraphQLEnumValueConfigMap = {};
typeName
.substring(7)
.split(',')
.forEach((currencyCode: string) => {
values[currencyCode] = {};
});

return new GraphQLEnumType({
name: 'Currency',
values: values,
});
NumberToWords(ubiNum: 1234) {
NumberToWordsResult
}
return super.inputType(typeName);
}
}

await queryEndpoint(
{
createClient: { url: 'http://www.webservicex.net/CurrencyConvertor.asmx?WSDL' },
schemaOptions: { customResolver: new CurrencyResolver() },
},
`
mutation {
ConversionRate(FromCurrency: AFA, ToCurrency: ALL)
}
`,
);
}).timeout(5000);

xit('http://soatest.parasoft.com/calculator.wsdl', async () => {
class CalculatorCaller extends NodeSoapCaller {
async createGraphqlResult(input: SoapCallInput, result: any): Promise<any> {
return result['Result']['$value'];
}
}

const soapClient: NodeSoapClient = await createSoapClient(
'http://soatest.parasoft.com/calculator.wsdl',
);
const caller: SoapCaller = new CalculatorCaller(soapClient, createLogger(false, false));
const options: SoapGraphqlOptions = {
soapClient: soapClient,
soapCaller: caller,
debug: false,
};

await queryEndpoint(
options,
`
mutation {
sum1: add(x: 1, y: 2)
sum2: add(x: 2.3, y: 3.45)
divide(numerator: 2, denominator: 4)
}
`,
(data) => {
expect(data.sum1).to.exist;
expect(data.sum1).to.equal(3);
expect(data.sum2).to.exist;
expect(data.sum2).to.equal(5.75);
expect(data.divide).to.exist;
expect(data.divide).to.equal(0.5);
expect(data.NumberToWords).to.exist;
expect(data.NumberToWords.NumberToWordsResult).to.equal(
'one thousand two hundred and thirty four',
);
},
);
}).timeout(5000);
Expand Down
8 changes: 1 addition & 7 deletions src/node-soap/node-soap-caller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,7 @@ export class NodeSoapCaller implements SoapCaller {
this.debug(
() => `operation '${input.operation.name()}' returned '${inspect(result, false, 5)}'`,
);

if (!input.operation.resultField()) {
// void operation
return !result ? null : JSON.stringify(result);
} else {
return !result ? null : result[input.operation.resultField()];
}
return result;
}

protected debug(message: LateResolvedMessage): void {
Expand Down
Loading

0 comments on commit 4d3499f

Please sign in to comment.