@graphql-mesh/transport-soap 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/executor.js +144 -0
- package/cjs/index.js +10 -0
- package/cjs/package.json +1 -0
- package/cjs/parseXmlOptions.js +12 -0
- package/esm/executor.js +140 -0
- package/esm/index.js +5 -0
- package/esm/parseXmlOptions.js +9 -0
- package/package.json +51 -0
- package/typings/executor.d.cts +4 -0
- package/typings/executor.d.ts +4 -0
- package/typings/index.d.cts +3 -0
- package/typings/index.d.ts +3 -0
- package/typings/parseXmlOptions.d.cts +2 -0
- package/typings/parseXmlOptions.d.ts +2 -0
package/cjs/executor.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createExecutorFromSchemaAST = void 0;
|
|
4
|
+
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const cross_helpers_1 = require("@graphql-mesh/cross-helpers");
|
|
7
|
+
const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
|
|
8
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
9
|
+
const fetch_1 = require("@whatwg-node/fetch");
|
|
10
|
+
const parseXmlOptions_1 = require("./parseXmlOptions");
|
|
11
|
+
function isOriginallyListType(type) {
|
|
12
|
+
if ((0, graphql_1.isNonNullType)(type)) {
|
|
13
|
+
return isOriginallyListType(type.ofType);
|
|
14
|
+
}
|
|
15
|
+
return (0, graphql_1.isListType)(type);
|
|
16
|
+
}
|
|
17
|
+
const defaultFieldResolver = function soapDefaultResolver(root, args, context, info) {
|
|
18
|
+
const rootField = root[info.fieldName];
|
|
19
|
+
if (typeof rootField === 'function') {
|
|
20
|
+
return rootField(args, context, info);
|
|
21
|
+
}
|
|
22
|
+
const fieldValue = rootField;
|
|
23
|
+
const isArray = Array.isArray(fieldValue);
|
|
24
|
+
const isPlural = isOriginallyListType(info.returnType);
|
|
25
|
+
if (isPlural && !isArray) {
|
|
26
|
+
return [fieldValue];
|
|
27
|
+
}
|
|
28
|
+
if (!isPlural && isArray) {
|
|
29
|
+
return fieldValue[0];
|
|
30
|
+
}
|
|
31
|
+
return fieldValue;
|
|
32
|
+
};
|
|
33
|
+
function normalizeArgsForConverter(args) {
|
|
34
|
+
if (args != null) {
|
|
35
|
+
if (typeof args === 'object') {
|
|
36
|
+
for (const key in args) {
|
|
37
|
+
args[key] = normalizeArgsForConverter(args[key]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return {
|
|
42
|
+
innerText: args,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return args;
|
|
47
|
+
}
|
|
48
|
+
function normalizeResult(result) {
|
|
49
|
+
if (result != null && typeof result === 'object') {
|
|
50
|
+
for (const key in result) {
|
|
51
|
+
if (key === 'innerText') {
|
|
52
|
+
return result.innerText;
|
|
53
|
+
}
|
|
54
|
+
result[key] = normalizeResult(result[key]);
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(result) && result.length === 1) {
|
|
57
|
+
return result[0];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
function createRootValueMethod({ soapAnnotations, fetchFn, jsonToXMLConverter, xmlToJSONConverter, operationHeadersFactory, }) {
|
|
63
|
+
return async function rootValueMethod(args, context, info) {
|
|
64
|
+
const requestJson = {
|
|
65
|
+
'soap:Envelope': {
|
|
66
|
+
attributes: {
|
|
67
|
+
'xmlns:soap': 'http://www.w3.org/2003/05/soap-envelope',
|
|
68
|
+
},
|
|
69
|
+
'soap:Body': {
|
|
70
|
+
attributes: {
|
|
71
|
+
xmlns: soapAnnotations.bindingNamespace,
|
|
72
|
+
},
|
|
73
|
+
...normalizeArgsForConverter(args),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const requestXML = jsonToXMLConverter.build(requestJson);
|
|
78
|
+
const currentFetchFn = context?.fetch || fetchFn;
|
|
79
|
+
const response = await currentFetchFn(soapAnnotations.endpoint, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
body: requestXML,
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/soap+xml; charset=utf-8',
|
|
84
|
+
...operationHeadersFactory({
|
|
85
|
+
args,
|
|
86
|
+
context,
|
|
87
|
+
info,
|
|
88
|
+
env: cross_helpers_1.process.env,
|
|
89
|
+
}),
|
|
90
|
+
},
|
|
91
|
+
}, context, info);
|
|
92
|
+
const responseXML = await response.text();
|
|
93
|
+
const responseJSON = xmlToJSONConverter.parse(responseXML, parseXmlOptions_1.parseXmlOptions);
|
|
94
|
+
return normalizeResult(responseJSON.Envelope[0].Body[0][soapAnnotations.elementName]);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function createRootValue(schema, fetchFn, operationHeaders) {
|
|
98
|
+
const rootValue = {};
|
|
99
|
+
const rootTypes = (0, utils_1.getRootTypes)(schema);
|
|
100
|
+
const jsonToXMLConverter = new fast_xml_parser_1.XMLBuilder({
|
|
101
|
+
attributeNamePrefix: '',
|
|
102
|
+
attributesGroupName: 'attributes',
|
|
103
|
+
textNodeName: 'innerText',
|
|
104
|
+
});
|
|
105
|
+
const xmlToJSONConverter = new fast_xml_parser_1.XMLParser(parseXmlOptions_1.parseXmlOptions);
|
|
106
|
+
const operationHeadersFactory = (0, string_interpolation_1.getInterpolatedHeadersFactory)(operationHeaders);
|
|
107
|
+
for (const rootType of rootTypes) {
|
|
108
|
+
const rootFieldMap = rootType.getFields();
|
|
109
|
+
for (const fieldName in rootFieldMap) {
|
|
110
|
+
const annotations = (0, utils_1.getDirective)(schema, rootFieldMap[fieldName], 'soap');
|
|
111
|
+
if (!annotations) {
|
|
112
|
+
// skip fields without @soap directive
|
|
113
|
+
// we have to skip Query.placeholder field when only mutations were created
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const soapAnnotations = Object.assign({}, ...annotations);
|
|
117
|
+
rootValue[fieldName] = createRootValueMethod({
|
|
118
|
+
soapAnnotations,
|
|
119
|
+
fetchFn,
|
|
120
|
+
jsonToXMLConverter,
|
|
121
|
+
xmlToJSONConverter,
|
|
122
|
+
operationHeadersFactory,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return rootValue;
|
|
127
|
+
}
|
|
128
|
+
function createExecutorFromSchemaAST(schema, fetchFn = fetch_1.fetch, operationHeaders = {}) {
|
|
129
|
+
let rootValue;
|
|
130
|
+
return function soapExecutor({ document, variables, context }) {
|
|
131
|
+
if (!rootValue) {
|
|
132
|
+
rootValue = createRootValue(schema, fetchFn, operationHeaders);
|
|
133
|
+
}
|
|
134
|
+
return (0, graphql_1.execute)({
|
|
135
|
+
schema,
|
|
136
|
+
document,
|
|
137
|
+
rootValue,
|
|
138
|
+
contextValue: context,
|
|
139
|
+
variableValues: variables,
|
|
140
|
+
fieldResolver: defaultFieldResolver,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
exports.createExecutorFromSchemaAST = createExecutorFromSchemaAST;
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createExecutorFromSchemaAST = exports.getSubgraphExecutor = void 0;
|
|
4
|
+
const executor_js_1 = require("./executor.js");
|
|
5
|
+
const getSubgraphExecutor = function getSOAPSubgraphExecutor({ transportEntry, getSubgraph, fetch }) {
|
|
6
|
+
return (0, executor_js_1.createExecutorFromSchemaAST)(getSubgraph(), fetch, transportEntry.headers);
|
|
7
|
+
};
|
|
8
|
+
exports.getSubgraphExecutor = getSubgraphExecutor;
|
|
9
|
+
var executor_js_2 = require("./executor.js");
|
|
10
|
+
Object.defineProperty(exports, "createExecutorFromSchemaAST", { enumerable: true, get: function () { return executor_js_2.createExecutorFromSchemaAST; } });
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseXmlOptions = void 0;
|
|
4
|
+
exports.parseXmlOptions = {
|
|
5
|
+
attributeNamePrefix: '',
|
|
6
|
+
attributesGroupName: 'attributes',
|
|
7
|
+
textNodeName: 'innerText',
|
|
8
|
+
ignoreAttributes: false,
|
|
9
|
+
removeNSPrefix: true,
|
|
10
|
+
isArray: (_, __, ___, isAttribute) => !isAttribute,
|
|
11
|
+
allowBooleanAttributes: true,
|
|
12
|
+
};
|
package/esm/executor.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { XMLBuilder as JSONToXMLConverter, XMLParser } from 'fast-xml-parser';
|
|
2
|
+
import { execute, isListType, isNonNullType, } from 'graphql';
|
|
3
|
+
import { process } from '@graphql-mesh/cross-helpers';
|
|
4
|
+
import { getInterpolatedHeadersFactory, } from '@graphql-mesh/string-interpolation';
|
|
5
|
+
import { getDirective, getRootTypes } from '@graphql-tools/utils';
|
|
6
|
+
import { fetch as defaultFetchFn } from '@whatwg-node/fetch';
|
|
7
|
+
import { parseXmlOptions } from './parseXmlOptions';
|
|
8
|
+
function isOriginallyListType(type) {
|
|
9
|
+
if (isNonNullType(type)) {
|
|
10
|
+
return isOriginallyListType(type.ofType);
|
|
11
|
+
}
|
|
12
|
+
return isListType(type);
|
|
13
|
+
}
|
|
14
|
+
const defaultFieldResolver = function soapDefaultResolver(root, args, context, info) {
|
|
15
|
+
const rootField = root[info.fieldName];
|
|
16
|
+
if (typeof rootField === 'function') {
|
|
17
|
+
return rootField(args, context, info);
|
|
18
|
+
}
|
|
19
|
+
const fieldValue = rootField;
|
|
20
|
+
const isArray = Array.isArray(fieldValue);
|
|
21
|
+
const isPlural = isOriginallyListType(info.returnType);
|
|
22
|
+
if (isPlural && !isArray) {
|
|
23
|
+
return [fieldValue];
|
|
24
|
+
}
|
|
25
|
+
if (!isPlural && isArray) {
|
|
26
|
+
return fieldValue[0];
|
|
27
|
+
}
|
|
28
|
+
return fieldValue;
|
|
29
|
+
};
|
|
30
|
+
function normalizeArgsForConverter(args) {
|
|
31
|
+
if (args != null) {
|
|
32
|
+
if (typeof args === 'object') {
|
|
33
|
+
for (const key in args) {
|
|
34
|
+
args[key] = normalizeArgsForConverter(args[key]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return {
|
|
39
|
+
innerText: args,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return args;
|
|
44
|
+
}
|
|
45
|
+
function normalizeResult(result) {
|
|
46
|
+
if (result != null && typeof result === 'object') {
|
|
47
|
+
for (const key in result) {
|
|
48
|
+
if (key === 'innerText') {
|
|
49
|
+
return result.innerText;
|
|
50
|
+
}
|
|
51
|
+
result[key] = normalizeResult(result[key]);
|
|
52
|
+
}
|
|
53
|
+
if (Array.isArray(result) && result.length === 1) {
|
|
54
|
+
return result[0];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
function createRootValueMethod({ soapAnnotations, fetchFn, jsonToXMLConverter, xmlToJSONConverter, operationHeadersFactory, }) {
|
|
60
|
+
return async function rootValueMethod(args, context, info) {
|
|
61
|
+
const requestJson = {
|
|
62
|
+
'soap:Envelope': {
|
|
63
|
+
attributes: {
|
|
64
|
+
'xmlns:soap': 'http://www.w3.org/2003/05/soap-envelope',
|
|
65
|
+
},
|
|
66
|
+
'soap:Body': {
|
|
67
|
+
attributes: {
|
|
68
|
+
xmlns: soapAnnotations.bindingNamespace,
|
|
69
|
+
},
|
|
70
|
+
...normalizeArgsForConverter(args),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
const requestXML = jsonToXMLConverter.build(requestJson);
|
|
75
|
+
const currentFetchFn = context?.fetch || fetchFn;
|
|
76
|
+
const response = await currentFetchFn(soapAnnotations.endpoint, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: requestXML,
|
|
79
|
+
headers: {
|
|
80
|
+
'Content-Type': 'application/soap+xml; charset=utf-8',
|
|
81
|
+
...operationHeadersFactory({
|
|
82
|
+
args,
|
|
83
|
+
context,
|
|
84
|
+
info,
|
|
85
|
+
env: process.env,
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
}, context, info);
|
|
89
|
+
const responseXML = await response.text();
|
|
90
|
+
const responseJSON = xmlToJSONConverter.parse(responseXML, parseXmlOptions);
|
|
91
|
+
return normalizeResult(responseJSON.Envelope[0].Body[0][soapAnnotations.elementName]);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function createRootValue(schema, fetchFn, operationHeaders) {
|
|
95
|
+
const rootValue = {};
|
|
96
|
+
const rootTypes = getRootTypes(schema);
|
|
97
|
+
const jsonToXMLConverter = new JSONToXMLConverter({
|
|
98
|
+
attributeNamePrefix: '',
|
|
99
|
+
attributesGroupName: 'attributes',
|
|
100
|
+
textNodeName: 'innerText',
|
|
101
|
+
});
|
|
102
|
+
const xmlToJSONConverter = new XMLParser(parseXmlOptions);
|
|
103
|
+
const operationHeadersFactory = getInterpolatedHeadersFactory(operationHeaders);
|
|
104
|
+
for (const rootType of rootTypes) {
|
|
105
|
+
const rootFieldMap = rootType.getFields();
|
|
106
|
+
for (const fieldName in rootFieldMap) {
|
|
107
|
+
const annotations = getDirective(schema, rootFieldMap[fieldName], 'soap');
|
|
108
|
+
if (!annotations) {
|
|
109
|
+
// skip fields without @soap directive
|
|
110
|
+
// we have to skip Query.placeholder field when only mutations were created
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const soapAnnotations = Object.assign({}, ...annotations);
|
|
114
|
+
rootValue[fieldName] = createRootValueMethod({
|
|
115
|
+
soapAnnotations,
|
|
116
|
+
fetchFn,
|
|
117
|
+
jsonToXMLConverter,
|
|
118
|
+
xmlToJSONConverter,
|
|
119
|
+
operationHeadersFactory,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return rootValue;
|
|
124
|
+
}
|
|
125
|
+
export function createExecutorFromSchemaAST(schema, fetchFn = defaultFetchFn, operationHeaders = {}) {
|
|
126
|
+
let rootValue;
|
|
127
|
+
return function soapExecutor({ document, variables, context }) {
|
|
128
|
+
if (!rootValue) {
|
|
129
|
+
rootValue = createRootValue(schema, fetchFn, operationHeaders);
|
|
130
|
+
}
|
|
131
|
+
return execute({
|
|
132
|
+
schema,
|
|
133
|
+
document,
|
|
134
|
+
rootValue,
|
|
135
|
+
contextValue: context,
|
|
136
|
+
variableValues: variables,
|
|
137
|
+
fieldResolver: defaultFieldResolver,
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createExecutorFromSchemaAST } from './executor.js';
|
|
2
|
+
export const getSubgraphExecutor = function getSOAPSubgraphExecutor({ transportEntry, getSubgraph, fetch }) {
|
|
3
|
+
return createExecutorFromSchemaAST(getSubgraph(), fetch, transportEntry.headers);
|
|
4
|
+
};
|
|
5
|
+
export { createExecutorFromSchemaAST } from './executor.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const parseXmlOptions = {
|
|
2
|
+
attributeNamePrefix: '',
|
|
3
|
+
attributesGroupName: 'attributes',
|
|
4
|
+
textNodeName: 'innerText',
|
|
5
|
+
ignoreAttributes: false,
|
|
6
|
+
removeNSPrefix: true,
|
|
7
|
+
isArray: (_, __, ___, isAttribute) => !isAttribute,
|
|
8
|
+
allowBooleanAttributes: true,
|
|
9
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@graphql-mesh/transport-soap",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"peerDependencies": {
|
|
6
|
+
"@graphql-mesh/cross-helpers": "^0.4.1",
|
|
7
|
+
"@graphql-mesh/transport-common": "^0.0.0",
|
|
8
|
+
"@graphql-mesh/types": "^0.96.2",
|
|
9
|
+
"@graphql-tools/utils": "^10.0.12",
|
|
10
|
+
"@whatwg-node/fetch": "^0.9.15",
|
|
11
|
+
"graphql": "*",
|
|
12
|
+
"tslib": "^2.4.0"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@graphql-mesh/string-interpolation": "^0.5.3",
|
|
16
|
+
"fast-xml-parser": "^4.3.2"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "Urigo/graphql-mesh",
|
|
21
|
+
"directory": "packages/transports/soap"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=16.0.0"
|
|
26
|
+
},
|
|
27
|
+
"main": "cjs/index.js",
|
|
28
|
+
"module": "esm/index.js",
|
|
29
|
+
"typings": "typings/index.d.ts",
|
|
30
|
+
"typescript": {
|
|
31
|
+
"definition": "typings/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"type": "module",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "./typings/index.d.cts",
|
|
38
|
+
"default": "./cjs/index.js"
|
|
39
|
+
},
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "./typings/index.d.ts",
|
|
42
|
+
"default": "./esm/index.js"
|
|
43
|
+
},
|
|
44
|
+
"default": {
|
|
45
|
+
"types": "./typings/index.d.ts",
|
|
46
|
+
"default": "./esm/index.js"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"./package.json": "./package.json"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { GraphQLSchema } from 'graphql';
|
|
2
|
+
import { MeshFetch } from '@graphql-mesh/types';
|
|
3
|
+
import { Executor } from '@graphql-tools/utils';
|
|
4
|
+
export declare function createExecutorFromSchemaAST(schema: GraphQLSchema, fetchFn?: MeshFetch, operationHeaders?: Record<string, string>): Executor;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { GraphQLSchema } from 'graphql';
|
|
2
|
+
import { MeshFetch } from '@graphql-mesh/types';
|
|
3
|
+
import { Executor } from '@graphql-tools/utils';
|
|
4
|
+
export declare function createExecutorFromSchemaAST(schema: GraphQLSchema, fetchFn?: MeshFetch, operationHeaders?: Record<string, string>): Executor;
|