@graphql-mesh/odata 1.0.0-alpha-20220804093904-8e2e41f7f → 1.0.0-alpha-20230420181317-a95037648
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/{index.js → cjs/index.js} +148 -137
- package/cjs/package.json +1 -0
- package/{index.mjs → esm/index.js} +54 -43
- package/package.json +34 -27
- package/typings/index.d.cts +16 -0
- package/{index.d.ts → typings/index.d.ts} +3 -3
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
5
|
+
const events_1 = tslib_1.__importDefault(require("events"));
|
|
6
|
+
const dataloader_1 = tslib_1.__importDefault(require("dataloader"));
|
|
7
|
+
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
8
|
+
const graphql_1 = require("graphql");
|
|
9
|
+
const graphql_compose_1 = require("graphql-compose");
|
|
10
|
+
const graphql_parse_resolve_info_1 = require("graphql-parse-resolve-info");
|
|
11
|
+
const graphql_scalars_1 = require("graphql-scalars");
|
|
12
|
+
const http_string_parser_1 = require("http-string-parser");
|
|
13
|
+
const pascal_case_1 = require("pascal-case");
|
|
14
|
+
const url_join_1 = tslib_1.__importDefault(require("url-join"));
|
|
15
|
+
const cross_helpers_1 = require("@graphql-mesh/cross-helpers");
|
|
16
|
+
const store_1 = require("@graphql-mesh/store");
|
|
17
|
+
const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
|
|
18
|
+
const utils_1 = require("@graphql-mesh/utils");
|
|
19
|
+
const delegate_1 = require("@graphql-tools/delegate");
|
|
20
|
+
const utils_2 = require("@graphql-tools/utils");
|
|
21
|
+
const fetch_1 = require("@whatwg-node/fetch");
|
|
23
22
|
const SCALARS = new Map([
|
|
24
23
|
['Edm.Binary', 'String'],
|
|
25
24
|
['Edm.Stream', 'String'],
|
|
@@ -66,9 +65,9 @@ const queryOptionsFields = {
|
|
|
66
65
|
},
|
|
67
66
|
};
|
|
68
67
|
class ODataHandler {
|
|
69
|
-
constructor({ name, config, baseDir,
|
|
68
|
+
constructor({ name, config, baseDir, importFn, logger, store, }) {
|
|
70
69
|
this.eventEmitterSet = new Set();
|
|
71
|
-
this.xmlParser = new
|
|
70
|
+
this.xmlParser = new fast_xml_parser_1.XMLParser({
|
|
72
71
|
attributeNamePrefix: '',
|
|
73
72
|
attributesGroupName: 'attributes',
|
|
74
73
|
textNodeName: 'innerText',
|
|
@@ -81,18 +80,17 @@ class ODataHandler {
|
|
|
81
80
|
this.name = name;
|
|
82
81
|
this.config = config;
|
|
83
82
|
this.baseDir = baseDir;
|
|
84
|
-
this.fetchFn = fetchFn;
|
|
85
83
|
this.importFn = importFn;
|
|
86
84
|
this.logger = logger;
|
|
87
|
-
this.metadataJson = store
|
|
85
|
+
this.metadataJson = store.proxy('metadata.json', store_1.PredefinedProxyOptions.JsonWithoutValidation);
|
|
88
86
|
}
|
|
89
87
|
async getCachedMetadataJson() {
|
|
90
88
|
return this.metadataJson.getWithSet(async () => {
|
|
91
|
-
const
|
|
92
|
-
env:
|
|
89
|
+
const endpoint = string_interpolation_1.stringInterpolator.parse(this.config.endpoint, {
|
|
90
|
+
env: cross_helpers_1.process.env,
|
|
93
91
|
});
|
|
94
|
-
const metadataUrl =
|
|
95
|
-
const metadataText = await
|
|
92
|
+
const metadataUrl = (0, url_join_1.default)(endpoint, '$metadata');
|
|
93
|
+
const metadataText = await (0, utils_1.readFileOrUrl)(this.config.source || metadataUrl, {
|
|
96
94
|
allowUnknownExtensions: true,
|
|
97
95
|
cwd: this.baseDir,
|
|
98
96
|
headers: this.config.schemaHeaders,
|
|
@@ -103,19 +101,20 @@ class ODataHandler {
|
|
|
103
101
|
return this.xmlParser.parse(metadataText);
|
|
104
102
|
});
|
|
105
103
|
}
|
|
106
|
-
async getMeshSource() {
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
104
|
+
async getMeshSource({ fetchFn }) {
|
|
105
|
+
this.fetchFn = fetchFn;
|
|
106
|
+
const { endpoint: nonInterpolatedBaseUrl, operationHeaders } = this.config;
|
|
107
|
+
const endpoint = string_interpolation_1.stringInterpolator.parse(nonInterpolatedBaseUrl, {
|
|
108
|
+
env: cross_helpers_1.process.env,
|
|
110
109
|
});
|
|
111
|
-
const schemaComposer = new
|
|
112
|
-
schemaComposer.add(
|
|
113
|
-
schemaComposer.add(
|
|
114
|
-
schemaComposer.add(
|
|
115
|
-
schemaComposer.add(
|
|
116
|
-
schemaComposer.add(
|
|
117
|
-
schemaComposer.add(
|
|
118
|
-
schemaComposer.add(
|
|
110
|
+
const schemaComposer = new graphql_compose_1.SchemaComposer();
|
|
111
|
+
schemaComposer.add(graphql_scalars_1.GraphQLBigInt);
|
|
112
|
+
schemaComposer.add(graphql_scalars_1.GraphQLGUID);
|
|
113
|
+
schemaComposer.add(graphql_scalars_1.GraphQLDateTime);
|
|
114
|
+
schemaComposer.add(graphql_scalars_1.GraphQLJSON);
|
|
115
|
+
schemaComposer.add(graphql_scalars_1.GraphQLByte);
|
|
116
|
+
schemaComposer.add(graphql_scalars_1.GraphQLDate);
|
|
117
|
+
schemaComposer.add(graphql_scalars_1.GraphQLISO8601Duration);
|
|
119
118
|
const aliasNamespaceMap = new Map();
|
|
120
119
|
const metadataJson = await this.getCachedMetadataJson();
|
|
121
120
|
const schemas = metadataJson.Edmx[0].DataServices[0].Schema;
|
|
@@ -145,7 +144,7 @@ class ODataHandler {
|
|
|
145
144
|
}
|
|
146
145
|
const actualTypeRefArr = actualTypeRef.split('.');
|
|
147
146
|
const typeName = multipleSchemas
|
|
148
|
-
?
|
|
147
|
+
? (0, pascal_case_1.pascalCase)(actualTypeRefArr.join('_'))
|
|
149
148
|
: actualTypeRefArr[actualTypeRefArr.length - 1];
|
|
150
149
|
let realTypeName = typeName;
|
|
151
150
|
if (SCALARS.has(actualTypeRef)) {
|
|
@@ -187,8 +186,8 @@ class ODataHandler {
|
|
|
187
186
|
throw actualError;
|
|
188
187
|
}
|
|
189
188
|
const urlStringWithoutSearchParams = urlString.split('?')[0];
|
|
190
|
-
if (
|
|
191
|
-
const actualReturnType =
|
|
189
|
+
if ((0, graphql_1.isListType)(info.returnType)) {
|
|
190
|
+
const actualReturnType = (0, graphql_1.getNamedType)(info.returnType);
|
|
192
191
|
const entityTypeExtensions = actualReturnType.extensions;
|
|
193
192
|
if ('Message' in responseJson && !('value' in responseJson)) {
|
|
194
193
|
const error = new Error(responseJson.Message);
|
|
@@ -211,16 +210,17 @@ class ODataHandler {
|
|
|
211
210
|
if ('ofType' in fieldType) {
|
|
212
211
|
fieldType = fieldType.ofType;
|
|
213
212
|
}
|
|
214
|
-
const { entityInfo: fieldEntityInfo } = fieldType
|
|
213
|
+
const { entityInfo: fieldEntityInfo } = fieldType
|
|
214
|
+
.extensions;
|
|
215
215
|
if (field instanceof Array) {
|
|
216
216
|
for (const fieldElement of field) {
|
|
217
|
-
const urlOfField = new URL(
|
|
217
|
+
const urlOfField = new URL((0, url_join_1.default)(identifierUrl, fieldName));
|
|
218
218
|
addIdentifierToUrl(urlOfField, fieldEntityInfo.identifierFieldName, fieldEntityInfo.identifierFieldTypeRef, fieldElement);
|
|
219
219
|
fieldElement['@odata.id'] = fieldElement['@odata.id'] || getUrlString(urlOfField);
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
else {
|
|
223
|
-
const urlOfField = new URL(
|
|
223
|
+
const urlOfField = new URL((0, url_join_1.default)(identifierUrl, fieldName));
|
|
224
224
|
addIdentifierToUrl(urlOfField, fieldEntityInfo.identifierFieldName, fieldEntityInfo.identifierFieldTypeRef, field);
|
|
225
225
|
field['@odata.id'] = field['@odata.id'] || getUrlString(urlOfField);
|
|
226
226
|
}
|
|
@@ -247,16 +247,17 @@ class ODataHandler {
|
|
|
247
247
|
if ('ofType' in fieldType) {
|
|
248
248
|
fieldType = fieldType.ofType;
|
|
249
249
|
}
|
|
250
|
-
const { entityInfo: fieldEntityInfo } = fieldType
|
|
250
|
+
const { entityInfo: fieldEntityInfo } = fieldType
|
|
251
|
+
.extensions;
|
|
251
252
|
if (field instanceof Array) {
|
|
252
253
|
for (const fieldElement of field) {
|
|
253
|
-
const urlOfField = new URL(
|
|
254
|
+
const urlOfField = new URL((0, url_join_1.default)(identifierUrl, fieldName));
|
|
254
255
|
addIdentifierToUrl(urlOfField, fieldEntityInfo.identifierFieldName, fieldEntityInfo.identifierFieldTypeRef, fieldElement);
|
|
255
256
|
fieldElement['@odata.id'] = fieldElement['@odata.id'] || getUrlString(urlOfField);
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
else {
|
|
259
|
-
const urlOfField = new URL(
|
|
260
|
+
const urlOfField = new URL((0, url_join_1.default)(identifierUrl, fieldName));
|
|
260
261
|
addIdentifierToUrl(urlOfField, fieldEntityInfo.identifierFieldName, fieldEntityInfo.identifierFieldTypeRef, field);
|
|
261
262
|
field['@odata.id'] = field['@odata.id'] || getUrlString(urlOfField);
|
|
262
263
|
}
|
|
@@ -285,7 +286,7 @@ class ODataHandler {
|
|
|
285
286
|
name: 'QueryOptions',
|
|
286
287
|
fields: queryOptionsFields,
|
|
287
288
|
});
|
|
288
|
-
const origHeadersFactory =
|
|
289
|
+
const origHeadersFactory = (0, string_interpolation_1.getInterpolatedHeadersFactory)(operationHeaders);
|
|
289
290
|
const headersFactory = (resolverData, method) => {
|
|
290
291
|
const headers = origHeadersFactory(resolverData);
|
|
291
292
|
if (headers.accept == null) {
|
|
@@ -296,9 +297,9 @@ class ODataHandler {
|
|
|
296
297
|
}
|
|
297
298
|
return headers;
|
|
298
299
|
};
|
|
299
|
-
const { args: commonArgs, contextVariables } =
|
|
300
|
+
const { args: commonArgs, contextVariables } = (0, string_interpolation_1.parseInterpolationStrings)([
|
|
300
301
|
...Object.values(operationHeaders || {}),
|
|
301
|
-
|
|
302
|
+
endpoint,
|
|
302
303
|
]);
|
|
303
304
|
function getTCByTypeNames(...typeNames) {
|
|
304
305
|
for (const typeName of typeNames) {
|
|
@@ -342,14 +343,14 @@ class ODataHandler {
|
|
|
342
343
|
}
|
|
343
344
|
return requests.map((_req, index) => {
|
|
344
345
|
const responseObj = batchResponseJson.responses.find((res) => res.id === index.toString());
|
|
345
|
-
return new
|
|
346
|
+
return new fetch_1.Response(JSON.stringify(responseObj.body), {
|
|
346
347
|
status: responseObj.status,
|
|
347
348
|
headers: responseObj.headers,
|
|
348
349
|
});
|
|
349
350
|
});
|
|
350
351
|
}
|
|
351
352
|
const DATALOADER_FACTORIES = {
|
|
352
|
-
multipart: (context) => new
|
|
353
|
+
multipart: (context) => new dataloader_1.default(async (requests) => {
|
|
353
354
|
var _a;
|
|
354
355
|
let requestBody = '';
|
|
355
356
|
const requestBoundary = 'batch_' + Date.now();
|
|
@@ -374,10 +375,10 @@ class ODataHandler {
|
|
|
374
375
|
requestBody += `--${requestBoundary}--\n`;
|
|
375
376
|
const batchHeaders = headersFactory({
|
|
376
377
|
context,
|
|
377
|
-
env:
|
|
378
|
+
env: cross_helpers_1.process.env,
|
|
378
379
|
}, 'POST');
|
|
379
380
|
batchHeaders['content-type'] = `multipart/mixed;boundary=${requestBoundary}`;
|
|
380
|
-
const batchResponse = await this.fetchFn(
|
|
381
|
+
const batchResponse = await this.fetchFn((0, url_join_1.default)(endpoint, '$batch'), {
|
|
381
382
|
method: 'POST',
|
|
382
383
|
body: requestBody,
|
|
383
384
|
headers: batchHeaders,
|
|
@@ -393,27 +394,27 @@ class ODataHandler {
|
|
|
393
394
|
const responseTextArr = actualResponse.split(responseBoundary);
|
|
394
395
|
return responseTextArr.map(responseTextWithContentHeader => {
|
|
395
396
|
const responseText = responseTextWithContentHeader.split('\n').slice(4).join('\n');
|
|
396
|
-
const { body, headers, statusCode, statusMessage } =
|
|
397
|
-
return new
|
|
397
|
+
const { body, headers, statusCode, statusMessage } = (0, http_string_parser_1.parseResponse)(responseText);
|
|
398
|
+
return new fetch_1.Response(body, {
|
|
398
399
|
headers,
|
|
399
400
|
status: parseInt(statusCode),
|
|
400
401
|
statusText: statusMessage,
|
|
401
402
|
});
|
|
402
403
|
});
|
|
403
404
|
}),
|
|
404
|
-
json: (context) => new
|
|
405
|
+
json: (context) => new dataloader_1.default(async (requests) => {
|
|
405
406
|
const batchHeaders = headersFactory({
|
|
406
407
|
context,
|
|
407
|
-
env:
|
|
408
|
+
env: cross_helpers_1.process.env,
|
|
408
409
|
}, 'POST');
|
|
409
410
|
batchHeaders['content-type'] = 'application/json';
|
|
410
|
-
const batchResponse = await this.fetchFn(
|
|
411
|
+
const batchResponse = await this.fetchFn((0, url_join_1.default)(endpoint, '$batch'), {
|
|
411
412
|
method: 'POST',
|
|
412
413
|
body: JSON.stringify({
|
|
413
414
|
requests: await Promise.all(requests.map(async (request, index) => {
|
|
414
415
|
var _a;
|
|
415
416
|
const id = index.toString();
|
|
416
|
-
const url = request.url.replace(
|
|
417
|
+
const url = request.url.replace(endpoint, '');
|
|
417
418
|
const method = request.method;
|
|
418
419
|
const headers = {};
|
|
419
420
|
(_a = request.headers) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => {
|
|
@@ -433,13 +434,19 @@ class ODataHandler {
|
|
|
433
434
|
const batchResponseJson = await batchResponse.json();
|
|
434
435
|
return handleBatchJsonResults(batchResponseJson, requests);
|
|
435
436
|
}),
|
|
436
|
-
none: () =>
|
|
437
|
+
none: () =>
|
|
438
|
+
// We should refactor here
|
|
439
|
+
new dataloader_1.default((requests) => Promise.all(requests.map(async (request) => this.fetchFn(request.url, {
|
|
440
|
+
method: request.method,
|
|
441
|
+
body: request.body && (await request.text()),
|
|
442
|
+
headers: (0, utils_1.getHeadersObj)(request.headers),
|
|
443
|
+
})))),
|
|
437
444
|
};
|
|
438
|
-
const dataLoaderFactory =
|
|
445
|
+
const dataLoaderFactory = (0, utils_2.memoize1)(DATALOADER_FACTORIES[this.config.batch || 'none']);
|
|
439
446
|
function buildName({ schemaNamespace, name }) {
|
|
440
447
|
const alias = aliasNamespaceMap.get(schemaNamespace) || schemaNamespace;
|
|
441
448
|
const ref = alias + '.' + name;
|
|
442
|
-
return multipleSchemas ?
|
|
449
|
+
return multipleSchemas ? (0, pascal_case_1.pascalCase)(ref.split('.').join('_')) : name;
|
|
443
450
|
}
|
|
444
451
|
schemas === null || schemas === void 0 ? void 0 : schemas.forEach((schemaObj) => {
|
|
445
452
|
const schemaNamespace = schemaObj.attributes.Namespace;
|
|
@@ -478,7 +485,7 @@ class ODataHandler {
|
|
|
478
485
|
const entityTypeName = buildName({ schemaNamespace, name: typeObj.attributes.Name });
|
|
479
486
|
const isOpenType = typeObj.attributes.OpenType === 'true';
|
|
480
487
|
const isAbstract = typeObj.attributes.Abstract === 'true';
|
|
481
|
-
const eventEmitter = new
|
|
488
|
+
const eventEmitter = new events_1.default();
|
|
482
489
|
eventEmitter.setMaxListeners(Infinity);
|
|
483
490
|
this.eventEmitterSet.add(eventEmitter);
|
|
484
491
|
const extensions = {
|
|
@@ -587,25 +594,25 @@ class ODataHandler {
|
|
|
587
594
|
return root[navigationPropertyName];
|
|
588
595
|
}
|
|
589
596
|
const url = new URL(root['@odata.id']);
|
|
590
|
-
url.href =
|
|
597
|
+
url.href = (0, url_join_1.default)(url.href, '/' + navigationPropertyName);
|
|
591
598
|
const returnType = info.returnType;
|
|
592
599
|
const { entityInfo } = returnType.extensions;
|
|
593
600
|
addIdentifierToUrl(url, entityInfo.identifierFieldName, entityInfo.identifierFieldTypeRef, args);
|
|
594
|
-
const parsedInfoFragment =
|
|
601
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
595
602
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
596
603
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
597
604
|
url.searchParams.set(key, value);
|
|
598
605
|
});
|
|
599
606
|
const urlString = getUrlString(url);
|
|
600
607
|
const method = 'GET';
|
|
601
|
-
const request = new
|
|
608
|
+
const request = new fetch_1.Request(urlString, {
|
|
602
609
|
method,
|
|
603
610
|
headers: headersFactory({
|
|
604
611
|
root,
|
|
605
612
|
args,
|
|
606
613
|
context,
|
|
607
614
|
info,
|
|
608
|
-
env:
|
|
615
|
+
env: cross_helpers_1.process.env,
|
|
609
616
|
}, method),
|
|
610
617
|
});
|
|
611
618
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -629,22 +636,22 @@ class ODataHandler {
|
|
|
629
636
|
return root[navigationPropertyName];
|
|
630
637
|
}
|
|
631
638
|
const url = new URL(root['@odata.id']);
|
|
632
|
-
url.href =
|
|
633
|
-
const parsedInfoFragment =
|
|
639
|
+
url.href = (0, url_join_1.default)(url.href, '/' + navigationPropertyName);
|
|
640
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
634
641
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
635
642
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
636
643
|
url.searchParams.set(key, value);
|
|
637
644
|
});
|
|
638
645
|
const urlString = getUrlString(url);
|
|
639
646
|
const method = 'GET';
|
|
640
|
-
const request = new
|
|
647
|
+
const request = new fetch_1.Request(urlString, {
|
|
641
648
|
method,
|
|
642
649
|
headers: headersFactory({
|
|
643
650
|
root,
|
|
644
651
|
args,
|
|
645
652
|
context,
|
|
646
653
|
info,
|
|
647
|
-
env:
|
|
654
|
+
env: cross_helpers_1.process.env,
|
|
648
655
|
}, method),
|
|
649
656
|
});
|
|
650
657
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -677,22 +684,22 @@ class ODataHandler {
|
|
|
677
684
|
return root[navigationPropertyName];
|
|
678
685
|
}
|
|
679
686
|
const url = new URL(root['@odata.id']);
|
|
680
|
-
url.href =
|
|
681
|
-
const parsedInfoFragment =
|
|
687
|
+
url.href = (0, url_join_1.default)(url.href, '/' + navigationPropertyName);
|
|
688
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
682
689
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
683
690
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
684
691
|
url.searchParams.set(key, value);
|
|
685
692
|
});
|
|
686
693
|
const urlString = getUrlString(url);
|
|
687
694
|
const method = 'GET';
|
|
688
|
-
const request = new
|
|
695
|
+
const request = new fetch_1.Request(urlString, {
|
|
689
696
|
method,
|
|
690
697
|
headers: headersFactory({
|
|
691
698
|
root,
|
|
692
699
|
args,
|
|
693
700
|
context,
|
|
694
701
|
info,
|
|
695
|
-
env:
|
|
702
|
+
env: cross_helpers_1.process.env,
|
|
696
703
|
}, method),
|
|
697
704
|
});
|
|
698
705
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -729,7 +736,8 @@ class ODataHandler {
|
|
|
729
736
|
});
|
|
730
737
|
}
|
|
731
738
|
const updateInputType = inputType.clone(`${entityTypeName}UpdateInput`);
|
|
732
|
-
(_c = updateInputType
|
|
739
|
+
(_c = updateInputType
|
|
740
|
+
.getFieldNames()) === null || _c === void 0 ? void 0 : _c.forEach(fieldName => updateInputType.makeOptional(fieldName));
|
|
733
741
|
// Types might be considered as unused implementations of interfaces so we must prevent that
|
|
734
742
|
schemaComposer.addSchemaMustHaveType(outputType);
|
|
735
743
|
});
|
|
@@ -749,27 +757,27 @@ class ODataHandler {
|
|
|
749
757
|
...commonArgs,
|
|
750
758
|
},
|
|
751
759
|
resolve: async (root, args, context, info) => {
|
|
752
|
-
const url = new URL(
|
|
753
|
-
url.href =
|
|
760
|
+
const url = new URL(endpoint);
|
|
761
|
+
url.href = (0, url_join_1.default)(url.href, '/' + functionName);
|
|
754
762
|
url.href += `(${Object.entries(args)
|
|
755
763
|
.filter(argEntry => argEntry[0] !== 'queryOptions')
|
|
756
764
|
.map(argEntry => argEntry.join(' = '))
|
|
757
765
|
.join(', ')})`;
|
|
758
|
-
const parsedInfoFragment =
|
|
766
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
759
767
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
760
768
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
761
769
|
url.searchParams.set(key, value);
|
|
762
770
|
});
|
|
763
771
|
const urlString = getUrlString(url);
|
|
764
772
|
const method = 'GET';
|
|
765
|
-
const request = new
|
|
773
|
+
const request = new fetch_1.Request(urlString, {
|
|
766
774
|
method,
|
|
767
775
|
headers: headersFactory({
|
|
768
776
|
root,
|
|
769
777
|
args,
|
|
770
778
|
context,
|
|
771
779
|
info,
|
|
772
|
-
env:
|
|
780
|
+
env: cross_helpers_1.process.env,
|
|
773
781
|
}, method),
|
|
774
782
|
});
|
|
775
783
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -837,30 +845,33 @@ class ODataHandler {
|
|
|
837
845
|
args,
|
|
838
846
|
resolve: async (root, args, context, info) => {
|
|
839
847
|
const url = new URL(root['@odata.id']);
|
|
840
|
-
url.href =
|
|
848
|
+
url.href = (0, url_join_1.default)(url.href, '/' + functionRef);
|
|
841
849
|
const argsEntries = Object.entries(args);
|
|
842
850
|
if (argsEntries.length) {
|
|
843
851
|
url.href += `(${argsEntries
|
|
844
852
|
.filter(argEntry => argEntry[0] !== 'queryOptions')
|
|
845
|
-
.map(([argName, value]) => [
|
|
853
|
+
.map(([argName, value]) => [
|
|
854
|
+
argName,
|
|
855
|
+
typeof value === 'string' ? `'${value}'` : value,
|
|
856
|
+
])
|
|
846
857
|
.map(argEntry => argEntry.join('='))
|
|
847
858
|
.join(',')})`;
|
|
848
859
|
}
|
|
849
|
-
const parsedInfoFragment =
|
|
860
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
850
861
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
851
862
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
852
863
|
url.searchParams.set(key, value);
|
|
853
864
|
});
|
|
854
865
|
const urlString = getUrlString(url);
|
|
855
866
|
const method = 'GET';
|
|
856
|
-
const request = new
|
|
867
|
+
const request = new fetch_1.Request(urlString, {
|
|
857
868
|
method,
|
|
858
869
|
headers: headersFactory({
|
|
859
870
|
root,
|
|
860
871
|
args,
|
|
861
872
|
context,
|
|
862
873
|
info,
|
|
863
|
-
env:
|
|
874
|
+
env: cross_helpers_1.process.env,
|
|
864
875
|
}, method),
|
|
865
876
|
});
|
|
866
877
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -901,18 +912,18 @@ class ODataHandler {
|
|
|
901
912
|
...commonArgs,
|
|
902
913
|
},
|
|
903
914
|
resolve: async (root, args, context, info) => {
|
|
904
|
-
const url = new URL(
|
|
905
|
-
url.href =
|
|
915
|
+
const url = new URL(endpoint);
|
|
916
|
+
url.href = (0, url_join_1.default)(url.href, '/' + actionName);
|
|
906
917
|
const urlString = getUrlString(url);
|
|
907
918
|
const method = 'POST';
|
|
908
|
-
const request = new
|
|
919
|
+
const request = new fetch_1.Request(urlString, {
|
|
909
920
|
method,
|
|
910
921
|
headers: headersFactory({
|
|
911
922
|
root,
|
|
912
923
|
args,
|
|
913
924
|
context,
|
|
914
925
|
info,
|
|
915
|
-
env:
|
|
926
|
+
env: cross_helpers_1.process.env,
|
|
916
927
|
}, method),
|
|
917
928
|
body: JSON.stringify(args),
|
|
918
929
|
});
|
|
@@ -972,17 +983,17 @@ class ODataHandler {
|
|
|
972
983
|
args,
|
|
973
984
|
resolve: async (root, args, context, info) => {
|
|
974
985
|
const url = new URL(root['@odata.id']);
|
|
975
|
-
url.href =
|
|
986
|
+
url.href = (0, url_join_1.default)(url.href, '/' + actionRef);
|
|
976
987
|
const urlString = getUrlString(url);
|
|
977
988
|
const method = 'POST';
|
|
978
|
-
const request = new
|
|
989
|
+
const request = new fetch_1.Request(urlString, {
|
|
979
990
|
method,
|
|
980
991
|
headers: headersFactory({
|
|
981
992
|
root,
|
|
982
993
|
args,
|
|
983
994
|
context,
|
|
984
995
|
info,
|
|
985
|
-
env:
|
|
996
|
+
env: cross_helpers_1.process.env,
|
|
986
997
|
}, method),
|
|
987
998
|
body: JSON.stringify(args),
|
|
988
999
|
});
|
|
@@ -1036,13 +1047,14 @@ class ODataHandler {
|
|
|
1036
1047
|
const { entityInfo: baseEntityInfo, eventEmitter: baseEventEmitter } = baseOutputType.getExtensions();
|
|
1037
1048
|
const baseEventEmitterListener = () => {
|
|
1038
1049
|
inputType.addFields(baseInputType.getFields());
|
|
1039
|
-
entityInfo.identifierFieldName =
|
|
1050
|
+
entityInfo.identifierFieldName =
|
|
1051
|
+
baseEntityInfo.identifierFieldName || entityInfo.identifierFieldName;
|
|
1040
1052
|
entityInfo.identifierFieldTypeRef =
|
|
1041
1053
|
baseEntityInfo.identifierFieldTypeRef || entityInfo.identifierFieldTypeRef;
|
|
1042
1054
|
entityInfo.actualFields.unshift(...baseEntityInfo.actualFields);
|
|
1043
1055
|
abstractType === null || abstractType === void 0 ? void 0 : abstractType.addFields(baseAbstractType === null || baseAbstractType === void 0 ? void 0 : baseAbstractType.getFields());
|
|
1044
1056
|
outputType.addFields(baseOutputType.getFields());
|
|
1045
|
-
if (baseAbstractType instanceof
|
|
1057
|
+
if (baseAbstractType instanceof graphql_compose_1.InterfaceTypeComposer) {
|
|
1046
1058
|
// abstractType.addInterface(baseAbstractType.getTypeName());
|
|
1047
1059
|
outputType.addInterface(baseAbstractType.getTypeName());
|
|
1048
1060
|
}
|
|
@@ -1071,23 +1083,23 @@ class ODataHandler {
|
|
|
1071
1083
|
...commonArgs,
|
|
1072
1084
|
},
|
|
1073
1085
|
resolve: async (root, args, context, info) => {
|
|
1074
|
-
const url = new URL(
|
|
1075
|
-
url.href =
|
|
1076
|
-
const parsedInfoFragment =
|
|
1086
|
+
const url = new URL(endpoint);
|
|
1087
|
+
url.href = (0, url_join_1.default)(url.href, '/' + singletonName);
|
|
1088
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
1077
1089
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
1078
1090
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
1079
1091
|
url.searchParams.set(key, value);
|
|
1080
1092
|
});
|
|
1081
1093
|
const urlString = getUrlString(url);
|
|
1082
1094
|
const method = 'GET';
|
|
1083
|
-
const request = new
|
|
1095
|
+
const request = new fetch_1.Request(urlString, {
|
|
1084
1096
|
method,
|
|
1085
1097
|
headers: headersFactory({
|
|
1086
1098
|
root,
|
|
1087
1099
|
args,
|
|
1088
1100
|
context,
|
|
1089
1101
|
info,
|
|
1090
|
-
env:
|
|
1102
|
+
env: cross_helpers_1.process.env,
|
|
1091
1103
|
}, method),
|
|
1092
1104
|
});
|
|
1093
1105
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -1119,23 +1131,23 @@ class ODataHandler {
|
|
|
1119
1131
|
queryOptions: { type: 'QueryOptions' },
|
|
1120
1132
|
},
|
|
1121
1133
|
resolve: async (root, args, context, info) => {
|
|
1122
|
-
const url = new URL(
|
|
1123
|
-
url.href =
|
|
1124
|
-
const parsedInfoFragment =
|
|
1134
|
+
const url = new URL(endpoint);
|
|
1135
|
+
url.href = (0, url_join_1.default)(url.href, '/' + entitySetName);
|
|
1136
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
1125
1137
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
1126
1138
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
1127
1139
|
url.searchParams.set(key, value);
|
|
1128
1140
|
});
|
|
1129
1141
|
const urlString = getUrlString(url);
|
|
1130
1142
|
const method = 'GET';
|
|
1131
|
-
const request = new
|
|
1143
|
+
const request = new fetch_1.Request(urlString, {
|
|
1132
1144
|
method,
|
|
1133
1145
|
headers: headersFactory({
|
|
1134
1146
|
root,
|
|
1135
1147
|
args,
|
|
1136
1148
|
context,
|
|
1137
1149
|
info,
|
|
1138
|
-
env:
|
|
1150
|
+
env: cross_helpers_1.process.env,
|
|
1139
1151
|
}, method),
|
|
1140
1152
|
});
|
|
1141
1153
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -1152,24 +1164,24 @@ class ODataHandler {
|
|
|
1152
1164
|
},
|
|
1153
1165
|
},
|
|
1154
1166
|
resolve: async (root, args, context, info) => {
|
|
1155
|
-
const url = new URL(
|
|
1156
|
-
url.href =
|
|
1167
|
+
const url = new URL(endpoint);
|
|
1168
|
+
url.href = (0, url_join_1.default)(url.href, '/' + entitySetName);
|
|
1157
1169
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1158
|
-
const parsedInfoFragment =
|
|
1170
|
+
const parsedInfoFragment = (0, graphql_parse_resolve_info_1.parseResolveInfo)(info);
|
|
1159
1171
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
1160
1172
|
searchParams === null || searchParams === void 0 ? void 0 : searchParams.forEach((value, key) => {
|
|
1161
1173
|
url.searchParams.set(key, value);
|
|
1162
1174
|
});
|
|
1163
1175
|
const urlString = getUrlString(url);
|
|
1164
1176
|
const method = 'GET';
|
|
1165
|
-
const request = new
|
|
1177
|
+
const request = new fetch_1.Request(urlString, {
|
|
1166
1178
|
method,
|
|
1167
1179
|
headers: headersFactory({
|
|
1168
1180
|
root,
|
|
1169
1181
|
args,
|
|
1170
1182
|
context,
|
|
1171
1183
|
info,
|
|
1172
|
-
env:
|
|
1184
|
+
env: cross_helpers_1.process.env,
|
|
1173
1185
|
}, method),
|
|
1174
1186
|
});
|
|
1175
1187
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -1187,18 +1199,18 @@ class ODataHandler {
|
|
|
1187
1199
|
queryOptions: { type: 'QueryOptions' },
|
|
1188
1200
|
},
|
|
1189
1201
|
resolve: async (root, args, context, info) => {
|
|
1190
|
-
const url = new URL(
|
|
1191
|
-
url.href =
|
|
1202
|
+
const url = new URL(endpoint);
|
|
1203
|
+
url.href = (0, url_join_1.default)(url.href, `/${entitySetName}/$count`);
|
|
1192
1204
|
const urlString = getUrlString(url);
|
|
1193
1205
|
const method = 'GET';
|
|
1194
|
-
const request = new
|
|
1206
|
+
const request = new fetch_1.Request(urlString, {
|
|
1195
1207
|
method,
|
|
1196
1208
|
headers: headersFactory({
|
|
1197
1209
|
root,
|
|
1198
1210
|
args,
|
|
1199
1211
|
context,
|
|
1200
1212
|
info,
|
|
1201
|
-
env:
|
|
1213
|
+
env: cross_helpers_1.process.env,
|
|
1202
1214
|
}, method),
|
|
1203
1215
|
});
|
|
1204
1216
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -1218,19 +1230,19 @@ class ODataHandler {
|
|
|
1218
1230
|
},
|
|
1219
1231
|
},
|
|
1220
1232
|
resolve: async (root, args, context, info) => {
|
|
1221
|
-
const url = new URL(
|
|
1222
|
-
url.href =
|
|
1233
|
+
const url = new URL(endpoint);
|
|
1234
|
+
url.href = (0, url_join_1.default)(url.href, '/' + entitySetName);
|
|
1223
1235
|
const urlString = getUrlString(url);
|
|
1224
1236
|
rebuildOpenInputObjects(args.input);
|
|
1225
1237
|
const method = 'POST';
|
|
1226
|
-
const request = new
|
|
1238
|
+
const request = new fetch_1.Request(urlString, {
|
|
1227
1239
|
method,
|
|
1228
1240
|
headers: headersFactory({
|
|
1229
1241
|
root,
|
|
1230
1242
|
args,
|
|
1231
1243
|
context,
|
|
1232
1244
|
info,
|
|
1233
|
-
env:
|
|
1245
|
+
env: cross_helpers_1.process.env,
|
|
1234
1246
|
}, method),
|
|
1235
1247
|
body: JSON.stringify(args.input),
|
|
1236
1248
|
});
|
|
@@ -1248,19 +1260,19 @@ class ODataHandler {
|
|
|
1248
1260
|
},
|
|
1249
1261
|
},
|
|
1250
1262
|
resolve: async (root, args, context, info) => {
|
|
1251
|
-
const url = new URL(
|
|
1252
|
-
url.href =
|
|
1263
|
+
const url = new URL(endpoint);
|
|
1264
|
+
url.href = (0, url_join_1.default)(url.href, '/' + entitySetName);
|
|
1253
1265
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1254
1266
|
const urlString = getUrlString(url);
|
|
1255
1267
|
const method = 'DELETE';
|
|
1256
|
-
const request = new
|
|
1268
|
+
const request = new fetch_1.Request(urlString, {
|
|
1257
1269
|
method,
|
|
1258
1270
|
headers: headersFactory({
|
|
1259
1271
|
root,
|
|
1260
1272
|
args,
|
|
1261
1273
|
context,
|
|
1262
1274
|
info,
|
|
1263
|
-
env:
|
|
1275
|
+
env: cross_helpers_1.process.env,
|
|
1264
1276
|
}, method),
|
|
1265
1277
|
});
|
|
1266
1278
|
const response = await context[contextDataloaderName].load(request);
|
|
@@ -1280,20 +1292,20 @@ class ODataHandler {
|
|
|
1280
1292
|
},
|
|
1281
1293
|
},
|
|
1282
1294
|
resolve: async (root, args, context, info) => {
|
|
1283
|
-
const url = new URL(
|
|
1284
|
-
url.href =
|
|
1295
|
+
const url = new URL(endpoint);
|
|
1296
|
+
url.href = (0, url_join_1.default)(url.href, '/' + entitySetName);
|
|
1285
1297
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1286
1298
|
const urlString = getUrlString(url);
|
|
1287
1299
|
rebuildOpenInputObjects(args.input);
|
|
1288
1300
|
const method = 'PATCH';
|
|
1289
|
-
const request = new
|
|
1301
|
+
const request = new fetch_1.Request(urlString, {
|
|
1290
1302
|
method,
|
|
1291
1303
|
headers: headersFactory({
|
|
1292
1304
|
root,
|
|
1293
1305
|
args,
|
|
1294
1306
|
context,
|
|
1295
1307
|
info,
|
|
1296
|
-
env:
|
|
1308
|
+
env: cross_helpers_1.process.env,
|
|
1297
1309
|
}, method),
|
|
1298
1310
|
body: JSON.stringify(args.input),
|
|
1299
1311
|
});
|
|
@@ -1307,11 +1319,11 @@ class ODataHandler {
|
|
|
1307
1319
|
});
|
|
1308
1320
|
});
|
|
1309
1321
|
// graphql-compose doesn't add @defer and @stream to the schema
|
|
1310
|
-
|
|
1322
|
+
graphql_1.specifiedDirectives.forEach(directive => schemaComposer.addDirective(directive));
|
|
1311
1323
|
const schema = schemaComposer.buildSchema();
|
|
1312
1324
|
this.eventEmitterSet.forEach(ee => ee.removeAllListeners());
|
|
1313
1325
|
this.eventEmitterSet.clear();
|
|
1314
|
-
const executor =
|
|
1326
|
+
const executor = (0, delegate_1.createDefaultExecutor)(schema);
|
|
1315
1327
|
return {
|
|
1316
1328
|
schema,
|
|
1317
1329
|
executor: (executionRequest) => {
|
|
@@ -1333,7 +1345,7 @@ class ODataHandler {
|
|
|
1333
1345
|
prepareSearchParams(fragment, schema) {
|
|
1334
1346
|
const fragmentTypeNames = Object.keys(fragment.fieldsByTypeName);
|
|
1335
1347
|
const returnType = schema.getType(fragmentTypeNames[0]);
|
|
1336
|
-
const { args, fields } =
|
|
1348
|
+
const { args, fields } = (0, graphql_parse_resolve_info_1.simplifyParsedResolveInfoFragmentWithType)(fragment, returnType);
|
|
1337
1349
|
const searchParams = new URLSearchParams();
|
|
1338
1350
|
if ('queryOptions' in args) {
|
|
1339
1351
|
const { queryOptions } = args;
|
|
@@ -1345,7 +1357,7 @@ class ODataHandler {
|
|
|
1345
1357
|
}
|
|
1346
1358
|
// $select doesn't work with inherited types' fields. So if there is an inline fragment for
|
|
1347
1359
|
// implemented types, we cannot use $select
|
|
1348
|
-
const isSelectable = !
|
|
1360
|
+
const isSelectable = !(0, graphql_1.isAbstractType)(returnType);
|
|
1349
1361
|
if (isSelectable) {
|
|
1350
1362
|
const { entityInfo } = returnType.extensions;
|
|
1351
1363
|
const selectionFields = [];
|
|
@@ -1374,5 +1386,4 @@ class ODataHandler {
|
|
|
1374
1386
|
return searchParams;
|
|
1375
1387
|
}
|
|
1376
1388
|
}
|
|
1377
|
-
|
|
1378
|
-
module.exports = ODataHandler;
|
|
1389
|
+
exports.default = ODataHandler;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import urljoin from 'url-join';
|
|
4
|
-
import { SchemaComposer, InterfaceTypeComposer } from 'graphql-compose';
|
|
5
|
-
import { GraphQLBigInt, GraphQLGUID, GraphQLDateTime, GraphQLJSON, GraphQLByte, GraphQLDate, GraphQLISO8601Duration } from 'graphql-scalars';
|
|
6
|
-
import { specifiedDirectives, isAbstractType, isListType, getNamedType } from 'graphql';
|
|
7
|
-
import { parseResolveInfo, simplifyParsedResolveInfoFragmentWithType } from 'graphql-parse-resolve-info';
|
|
1
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
2
|
+
import EventEmitter from 'events';
|
|
8
3
|
import DataLoader from 'dataloader';
|
|
4
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
5
|
+
import { getNamedType, isAbstractType, isListType, specifiedDirectives, } from 'graphql';
|
|
6
|
+
import { InterfaceTypeComposer, SchemaComposer, } from 'graphql-compose';
|
|
7
|
+
import { parseResolveInfo, simplifyParsedResolveInfoFragmentWithType, } from 'graphql-parse-resolve-info';
|
|
8
|
+
import { GraphQLBigInt, GraphQLByte, GraphQLDate, GraphQLDateTime, GraphQLGUID, GraphQLISO8601Duration, GraphQLJSON, } from 'graphql-scalars';
|
|
9
9
|
import { parseResponse } from 'http-string-parser';
|
|
10
10
|
import { pascalCase } from 'pascal-case';
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import { memoize1 } from '@graphql-tools/utils';
|
|
14
|
-
import { Request, Response } from '@whatwg-node/fetch';
|
|
11
|
+
import urljoin from 'url-join';
|
|
12
|
+
import { process } from '@graphql-mesh/cross-helpers';
|
|
15
13
|
import { PredefinedProxyOptions } from '@graphql-mesh/store';
|
|
14
|
+
import { getInterpolatedHeadersFactory, parseInterpolationStrings, stringInterpolator, } from '@graphql-mesh/string-interpolation';
|
|
15
|
+
import { getHeadersObj, readFileOrUrl } from '@graphql-mesh/utils';
|
|
16
16
|
import { createDefaultExecutor } from '@graphql-tools/delegate';
|
|
17
|
-
import {
|
|
18
|
-
|
|
17
|
+
import { memoize1 } from '@graphql-tools/utils';
|
|
18
|
+
import { Request, Response } from '@whatwg-node/fetch';
|
|
19
19
|
const SCALARS = new Map([
|
|
20
20
|
['Edm.Binary', 'String'],
|
|
21
21
|
['Edm.Stream', 'String'],
|
|
@@ -61,8 +61,8 @@ const queryOptionsFields = {
|
|
|
61
61
|
type: 'Boolean',
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
|
-
class ODataHandler {
|
|
65
|
-
constructor({ name, config, baseDir,
|
|
64
|
+
export default class ODataHandler {
|
|
65
|
+
constructor({ name, config, baseDir, importFn, logger, store, }) {
|
|
66
66
|
this.eventEmitterSet = new Set();
|
|
67
67
|
this.xmlParser = new XMLParser({
|
|
68
68
|
attributeNamePrefix: '',
|
|
@@ -77,18 +77,17 @@ class ODataHandler {
|
|
|
77
77
|
this.name = name;
|
|
78
78
|
this.config = config;
|
|
79
79
|
this.baseDir = baseDir;
|
|
80
|
-
this.fetchFn = fetchFn;
|
|
81
80
|
this.importFn = importFn;
|
|
82
81
|
this.logger = logger;
|
|
83
82
|
this.metadataJson = store.proxy('metadata.json', PredefinedProxyOptions.JsonWithoutValidation);
|
|
84
83
|
}
|
|
85
84
|
async getCachedMetadataJson() {
|
|
86
85
|
return this.metadataJson.getWithSet(async () => {
|
|
87
|
-
const
|
|
86
|
+
const endpoint = stringInterpolator.parse(this.config.endpoint, {
|
|
88
87
|
env: process.env,
|
|
89
88
|
});
|
|
90
|
-
const metadataUrl = urljoin(
|
|
91
|
-
const metadataText = await readFileOrUrl(this.config.
|
|
89
|
+
const metadataUrl = urljoin(endpoint, '$metadata');
|
|
90
|
+
const metadataText = await readFileOrUrl(this.config.source || metadataUrl, {
|
|
92
91
|
allowUnknownExtensions: true,
|
|
93
92
|
cwd: this.baseDir,
|
|
94
93
|
headers: this.config.schemaHeaders,
|
|
@@ -99,9 +98,10 @@ class ODataHandler {
|
|
|
99
98
|
return this.xmlParser.parse(metadataText);
|
|
100
99
|
});
|
|
101
100
|
}
|
|
102
|
-
async getMeshSource() {
|
|
103
|
-
|
|
104
|
-
const
|
|
101
|
+
async getMeshSource({ fetchFn }) {
|
|
102
|
+
this.fetchFn = fetchFn;
|
|
103
|
+
const { endpoint: nonInterpolatedBaseUrl, operationHeaders } = this.config;
|
|
104
|
+
const endpoint = stringInterpolator.parse(nonInterpolatedBaseUrl, {
|
|
105
105
|
env: process.env,
|
|
106
106
|
});
|
|
107
107
|
const schemaComposer = new SchemaComposer();
|
|
@@ -207,7 +207,8 @@ class ODataHandler {
|
|
|
207
207
|
if ('ofType' in fieldType) {
|
|
208
208
|
fieldType = fieldType.ofType;
|
|
209
209
|
}
|
|
210
|
-
const { entityInfo: fieldEntityInfo } = fieldType
|
|
210
|
+
const { entityInfo: fieldEntityInfo } = fieldType
|
|
211
|
+
.extensions;
|
|
211
212
|
if (field instanceof Array) {
|
|
212
213
|
for (const fieldElement of field) {
|
|
213
214
|
const urlOfField = new URL(urljoin(identifierUrl, fieldName));
|
|
@@ -243,7 +244,8 @@ class ODataHandler {
|
|
|
243
244
|
if ('ofType' in fieldType) {
|
|
244
245
|
fieldType = fieldType.ofType;
|
|
245
246
|
}
|
|
246
|
-
const { entityInfo: fieldEntityInfo } = fieldType
|
|
247
|
+
const { entityInfo: fieldEntityInfo } = fieldType
|
|
248
|
+
.extensions;
|
|
247
249
|
if (field instanceof Array) {
|
|
248
250
|
for (const fieldElement of field) {
|
|
249
251
|
const urlOfField = new URL(urljoin(identifierUrl, fieldName));
|
|
@@ -294,7 +296,7 @@ class ODataHandler {
|
|
|
294
296
|
};
|
|
295
297
|
const { args: commonArgs, contextVariables } = parseInterpolationStrings([
|
|
296
298
|
...Object.values(operationHeaders || {}),
|
|
297
|
-
|
|
299
|
+
endpoint,
|
|
298
300
|
]);
|
|
299
301
|
function getTCByTypeNames(...typeNames) {
|
|
300
302
|
for (const typeName of typeNames) {
|
|
@@ -373,7 +375,7 @@ class ODataHandler {
|
|
|
373
375
|
env: process.env,
|
|
374
376
|
}, 'POST');
|
|
375
377
|
batchHeaders['content-type'] = `multipart/mixed;boundary=${requestBoundary}`;
|
|
376
|
-
const batchResponse = await this.fetchFn(urljoin(
|
|
378
|
+
const batchResponse = await this.fetchFn(urljoin(endpoint, '$batch'), {
|
|
377
379
|
method: 'POST',
|
|
378
380
|
body: requestBody,
|
|
379
381
|
headers: batchHeaders,
|
|
@@ -403,13 +405,13 @@ class ODataHandler {
|
|
|
403
405
|
env: process.env,
|
|
404
406
|
}, 'POST');
|
|
405
407
|
batchHeaders['content-type'] = 'application/json';
|
|
406
|
-
const batchResponse = await this.fetchFn(urljoin(
|
|
408
|
+
const batchResponse = await this.fetchFn(urljoin(endpoint, '$batch'), {
|
|
407
409
|
method: 'POST',
|
|
408
410
|
body: JSON.stringify({
|
|
409
411
|
requests: await Promise.all(requests.map(async (request, index) => {
|
|
410
412
|
var _a;
|
|
411
413
|
const id = index.toString();
|
|
412
|
-
const url = request.url.replace(
|
|
414
|
+
const url = request.url.replace(endpoint, '');
|
|
413
415
|
const method = request.method;
|
|
414
416
|
const headers = {};
|
|
415
417
|
(_a = request.headers) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => {
|
|
@@ -429,7 +431,13 @@ class ODataHandler {
|
|
|
429
431
|
const batchResponseJson = await batchResponse.json();
|
|
430
432
|
return handleBatchJsonResults(batchResponseJson, requests);
|
|
431
433
|
}),
|
|
432
|
-
none: () =>
|
|
434
|
+
none: () =>
|
|
435
|
+
// We should refactor here
|
|
436
|
+
new DataLoader((requests) => Promise.all(requests.map(async (request) => this.fetchFn(request.url, {
|
|
437
|
+
method: request.method,
|
|
438
|
+
body: request.body && (await request.text()),
|
|
439
|
+
headers: getHeadersObj(request.headers),
|
|
440
|
+
})))),
|
|
433
441
|
};
|
|
434
442
|
const dataLoaderFactory = memoize1(DATALOADER_FACTORIES[this.config.batch || 'none']);
|
|
435
443
|
function buildName({ schemaNamespace, name }) {
|
|
@@ -725,7 +733,8 @@ class ODataHandler {
|
|
|
725
733
|
});
|
|
726
734
|
}
|
|
727
735
|
const updateInputType = inputType.clone(`${entityTypeName}UpdateInput`);
|
|
728
|
-
(_c = updateInputType
|
|
736
|
+
(_c = updateInputType
|
|
737
|
+
.getFieldNames()) === null || _c === void 0 ? void 0 : _c.forEach(fieldName => updateInputType.makeOptional(fieldName));
|
|
729
738
|
// Types might be considered as unused implementations of interfaces so we must prevent that
|
|
730
739
|
schemaComposer.addSchemaMustHaveType(outputType);
|
|
731
740
|
});
|
|
@@ -745,7 +754,7 @@ class ODataHandler {
|
|
|
745
754
|
...commonArgs,
|
|
746
755
|
},
|
|
747
756
|
resolve: async (root, args, context, info) => {
|
|
748
|
-
const url = new URL(
|
|
757
|
+
const url = new URL(endpoint);
|
|
749
758
|
url.href = urljoin(url.href, '/' + functionName);
|
|
750
759
|
url.href += `(${Object.entries(args)
|
|
751
760
|
.filter(argEntry => argEntry[0] !== 'queryOptions')
|
|
@@ -838,7 +847,10 @@ class ODataHandler {
|
|
|
838
847
|
if (argsEntries.length) {
|
|
839
848
|
url.href += `(${argsEntries
|
|
840
849
|
.filter(argEntry => argEntry[0] !== 'queryOptions')
|
|
841
|
-
.map(([argName, value]) => [
|
|
850
|
+
.map(([argName, value]) => [
|
|
851
|
+
argName,
|
|
852
|
+
typeof value === 'string' ? `'${value}'` : value,
|
|
853
|
+
])
|
|
842
854
|
.map(argEntry => argEntry.join('='))
|
|
843
855
|
.join(',')})`;
|
|
844
856
|
}
|
|
@@ -897,7 +909,7 @@ class ODataHandler {
|
|
|
897
909
|
...commonArgs,
|
|
898
910
|
},
|
|
899
911
|
resolve: async (root, args, context, info) => {
|
|
900
|
-
const url = new URL(
|
|
912
|
+
const url = new URL(endpoint);
|
|
901
913
|
url.href = urljoin(url.href, '/' + actionName);
|
|
902
914
|
const urlString = getUrlString(url);
|
|
903
915
|
const method = 'POST';
|
|
@@ -1032,7 +1044,8 @@ class ODataHandler {
|
|
|
1032
1044
|
const { entityInfo: baseEntityInfo, eventEmitter: baseEventEmitter } = baseOutputType.getExtensions();
|
|
1033
1045
|
const baseEventEmitterListener = () => {
|
|
1034
1046
|
inputType.addFields(baseInputType.getFields());
|
|
1035
|
-
entityInfo.identifierFieldName =
|
|
1047
|
+
entityInfo.identifierFieldName =
|
|
1048
|
+
baseEntityInfo.identifierFieldName || entityInfo.identifierFieldName;
|
|
1036
1049
|
entityInfo.identifierFieldTypeRef =
|
|
1037
1050
|
baseEntityInfo.identifierFieldTypeRef || entityInfo.identifierFieldTypeRef;
|
|
1038
1051
|
entityInfo.actualFields.unshift(...baseEntityInfo.actualFields);
|
|
@@ -1067,7 +1080,7 @@ class ODataHandler {
|
|
|
1067
1080
|
...commonArgs,
|
|
1068
1081
|
},
|
|
1069
1082
|
resolve: async (root, args, context, info) => {
|
|
1070
|
-
const url = new URL(
|
|
1083
|
+
const url = new URL(endpoint);
|
|
1071
1084
|
url.href = urljoin(url.href, '/' + singletonName);
|
|
1072
1085
|
const parsedInfoFragment = parseResolveInfo(info);
|
|
1073
1086
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
@@ -1115,7 +1128,7 @@ class ODataHandler {
|
|
|
1115
1128
|
queryOptions: { type: 'QueryOptions' },
|
|
1116
1129
|
},
|
|
1117
1130
|
resolve: async (root, args, context, info) => {
|
|
1118
|
-
const url = new URL(
|
|
1131
|
+
const url = new URL(endpoint);
|
|
1119
1132
|
url.href = urljoin(url.href, '/' + entitySetName);
|
|
1120
1133
|
const parsedInfoFragment = parseResolveInfo(info);
|
|
1121
1134
|
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
|
|
@@ -1148,7 +1161,7 @@ class ODataHandler {
|
|
|
1148
1161
|
},
|
|
1149
1162
|
},
|
|
1150
1163
|
resolve: async (root, args, context, info) => {
|
|
1151
|
-
const url = new URL(
|
|
1164
|
+
const url = new URL(endpoint);
|
|
1152
1165
|
url.href = urljoin(url.href, '/' + entitySetName);
|
|
1153
1166
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1154
1167
|
const parsedInfoFragment = parseResolveInfo(info);
|
|
@@ -1183,7 +1196,7 @@ class ODataHandler {
|
|
|
1183
1196
|
queryOptions: { type: 'QueryOptions' },
|
|
1184
1197
|
},
|
|
1185
1198
|
resolve: async (root, args, context, info) => {
|
|
1186
|
-
const url = new URL(
|
|
1199
|
+
const url = new URL(endpoint);
|
|
1187
1200
|
url.href = urljoin(url.href, `/${entitySetName}/$count`);
|
|
1188
1201
|
const urlString = getUrlString(url);
|
|
1189
1202
|
const method = 'GET';
|
|
@@ -1214,7 +1227,7 @@ class ODataHandler {
|
|
|
1214
1227
|
},
|
|
1215
1228
|
},
|
|
1216
1229
|
resolve: async (root, args, context, info) => {
|
|
1217
|
-
const url = new URL(
|
|
1230
|
+
const url = new URL(endpoint);
|
|
1218
1231
|
url.href = urljoin(url.href, '/' + entitySetName);
|
|
1219
1232
|
const urlString = getUrlString(url);
|
|
1220
1233
|
rebuildOpenInputObjects(args.input);
|
|
@@ -1244,7 +1257,7 @@ class ODataHandler {
|
|
|
1244
1257
|
},
|
|
1245
1258
|
},
|
|
1246
1259
|
resolve: async (root, args, context, info) => {
|
|
1247
|
-
const url = new URL(
|
|
1260
|
+
const url = new URL(endpoint);
|
|
1248
1261
|
url.href = urljoin(url.href, '/' + entitySetName);
|
|
1249
1262
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1250
1263
|
const urlString = getUrlString(url);
|
|
@@ -1276,7 +1289,7 @@ class ODataHandler {
|
|
|
1276
1289
|
},
|
|
1277
1290
|
},
|
|
1278
1291
|
resolve: async (root, args, context, info) => {
|
|
1279
|
-
const url = new URL(
|
|
1292
|
+
const url = new URL(endpoint);
|
|
1280
1293
|
url.href = urljoin(url.href, '/' + entitySetName);
|
|
1281
1294
|
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
|
|
1282
1295
|
const urlString = getUrlString(url);
|
|
@@ -1370,5 +1383,3 @@ class ODataHandler {
|
|
|
1370
1383
|
return searchParams;
|
|
1371
1384
|
}
|
|
1372
1385
|
}
|
|
1373
|
-
|
|
1374
|
-
export default ODataHandler;
|
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-mesh/odata",
|
|
3
|
-
"version": "1.0.0-alpha-
|
|
3
|
+
"version": "1.0.0-alpha-20230420181317-a95037648",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@graphql-mesh/
|
|
7
|
-
"@graphql-mesh/
|
|
8
|
-
"graphql": "
|
|
6
|
+
"@graphql-mesh/cross-helpers": "^0.3.4",
|
|
7
|
+
"@graphql-mesh/store": "1.0.0-alpha-20230420181317-a95037648",
|
|
8
|
+
"@graphql-mesh/types": "1.0.0-alpha-20230420181317-a95037648",
|
|
9
|
+
"@graphql-mesh/utils": "1.0.0-alpha-20230420181317-a95037648",
|
|
10
|
+
"@graphql-tools/utils": "^9.2.1",
|
|
11
|
+
"graphql": "*",
|
|
12
|
+
"tslib": "^2.4.0"
|
|
9
13
|
},
|
|
10
14
|
"dependencies": {
|
|
11
|
-
"@graphql-mesh/
|
|
12
|
-
"@graphql-
|
|
13
|
-
"@
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"graphql-compose": "9.0.8",
|
|
20
|
-
"graphql-parse-resolve-info": "4.12.3",
|
|
21
|
-
"graphql-scalars": "1.17.0",
|
|
15
|
+
"@graphql-mesh/string-interpolation": "0.4.4",
|
|
16
|
+
"@graphql-tools/delegate": "9.0.32",
|
|
17
|
+
"@whatwg-node/fetch": "^0.8.3",
|
|
18
|
+
"dataloader": "2.2.2",
|
|
19
|
+
"fast-xml-parser": "4.2.1",
|
|
20
|
+
"graphql-compose": "9.0.10",
|
|
21
|
+
"graphql-parse-resolve-info": "4.13.0",
|
|
22
|
+
"graphql-scalars": "^1.20.4",
|
|
22
23
|
"http-string-parser": "0.0.6",
|
|
23
24
|
"pascal-case": "3.1.2",
|
|
24
|
-
"tslib": "^2.4.0",
|
|
25
25
|
"url-join": "4.0.1"
|
|
26
26
|
},
|
|
27
27
|
"repository": {
|
|
@@ -30,21 +30,28 @@
|
|
|
30
30
|
"directory": "packages/handlers/odata"
|
|
31
31
|
},
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"main": "index.js",
|
|
34
|
-
"module": "index.
|
|
35
|
-
"typings": "index.d.ts",
|
|
33
|
+
"main": "cjs/index.js",
|
|
34
|
+
"module": "esm/index.js",
|
|
35
|
+
"typings": "typings/index.d.ts",
|
|
36
36
|
"typescript": {
|
|
37
|
-
"definition": "index.d.ts"
|
|
37
|
+
"definition": "typings/index.d.ts"
|
|
38
38
|
},
|
|
39
|
+
"type": "module",
|
|
39
40
|
"exports": {
|
|
40
41
|
".": {
|
|
41
|
-
"require":
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./typings/index.d.cts",
|
|
44
|
+
"default": "./cjs/index.js"
|
|
45
|
+
},
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./typings/index.d.ts",
|
|
48
|
+
"default": "./esm/index.js"
|
|
49
|
+
},
|
|
50
|
+
"default": {
|
|
51
|
+
"types": "./typings/index.d.ts",
|
|
52
|
+
"default": "./esm/index.js"
|
|
53
|
+
}
|
|
47
54
|
},
|
|
48
55
|
"./package.json": "./package.json"
|
|
49
56
|
}
|
|
50
|
-
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GetMeshSourcePayload, MeshHandler, MeshHandlerOptions, MeshSource, YamlConfig } from '@graphql-mesh/types';
|
|
2
|
+
export default class ODataHandler implements MeshHandler {
|
|
3
|
+
private name;
|
|
4
|
+
private config;
|
|
5
|
+
private fetchFn;
|
|
6
|
+
private logger;
|
|
7
|
+
private importFn;
|
|
8
|
+
private baseDir;
|
|
9
|
+
private eventEmitterSet;
|
|
10
|
+
private metadataJson;
|
|
11
|
+
private xmlParser;
|
|
12
|
+
constructor({ name, config, baseDir, importFn, logger, store, }: MeshHandlerOptions<YamlConfig.ODataHandler>);
|
|
13
|
+
getCachedMetadataJson(): Promise<any>;
|
|
14
|
+
getMeshSource({ fetchFn }: GetMeshSourcePayload): Promise<MeshSource>;
|
|
15
|
+
private prepareSearchParams;
|
|
16
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GetMeshSourcePayload, MeshHandler, MeshHandlerOptions, MeshSource, YamlConfig } from '@graphql-mesh/types';
|
|
2
2
|
export default class ODataHandler implements MeshHandler {
|
|
3
3
|
private name;
|
|
4
4
|
private config;
|
|
@@ -9,8 +9,8 @@ export default class ODataHandler implements MeshHandler {
|
|
|
9
9
|
private eventEmitterSet;
|
|
10
10
|
private metadataJson;
|
|
11
11
|
private xmlParser;
|
|
12
|
-
constructor({ name, config, baseDir,
|
|
12
|
+
constructor({ name, config, baseDir, importFn, logger, store, }: MeshHandlerOptions<YamlConfig.ODataHandler>);
|
|
13
13
|
getCachedMetadataJson(): Promise<any>;
|
|
14
|
-
getMeshSource(): Promise<MeshSource>;
|
|
14
|
+
getMeshSource({ fetchFn }: GetMeshSourcePayload): Promise<MeshSource>;
|
|
15
15
|
private prepareSearchParams;
|
|
16
16
|
}
|