@graphql-mesh/grpc 1.0.0-alpha-3fc47d119.0 → 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/cjs/index.js +454 -0
- package/cjs/package.json +1 -0
- package/cjs/patchLongJs.js +14 -0
- package/cjs/scalars.js +32 -0
- package/cjs/utils.js +96 -0
- package/{index.mjs → esm/index.js} +120 -213
- package/esm/patchLongJs.js +11 -0
- package/esm/scalars.js +27 -0
- package/esm/utils.js +89 -0
- package/package.json +30 -23
- package/typings/index.d.cts +37 -0
- package/{index.d.ts → typings/index.d.ts} +12 -14
- package/typings/patchLongJs.d.ts +1 -0
- package/typings/scalars.d.ts +2 -0
- package/typings/utils.d.cts +7 -0
- package/{utils.d.ts → typings/utils.d.ts} +2 -1
- package/index.js +0 -548
- /package/{patchLongJs.d.ts → typings/patchLongJs.d.cts} +0 -0
- /package/{scalars.d.ts → typings/scalars.d.cts} +0 -0
package/index.js
DELETED
|
@@ -1,548 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
4
|
-
|
|
5
|
-
const Long = _interopDefault(require('long'));
|
|
6
|
-
const stringInterpolation = require('@graphql-mesh/string-interpolation');
|
|
7
|
-
const grpcJs = require('@grpc/grpc-js');
|
|
8
|
-
const protoLoader = require('@grpc/proto-loader');
|
|
9
|
-
const graphqlCompose = require('graphql-compose');
|
|
10
|
-
const graphqlScalars = require('graphql-scalars');
|
|
11
|
-
const lodashGet = _interopDefault(require('lodash.get'));
|
|
12
|
-
const lodashHas = _interopDefault(require('lodash.has'));
|
|
13
|
-
const protobufjs = _interopDefault(require('protobufjs'));
|
|
14
|
-
const grpcReflection = _interopDefault(require('@ardatan/grpc-reflection-js'));
|
|
15
|
-
const descriptor = require('protobufjs/ext/descriptor/index.js');
|
|
16
|
-
const descriptor__default = _interopDefault(descriptor);
|
|
17
|
-
const utils = require('@graphql-mesh/utils');
|
|
18
|
-
const crossHelpers = require('@graphql-mesh/cross-helpers');
|
|
19
|
-
const graphql = require('graphql');
|
|
20
|
-
const globby = _interopDefault(require('globby'));
|
|
21
|
-
|
|
22
|
-
function patchLongJs() {
|
|
23
|
-
const originalLongFromValue = Long.fromValue.bind(Long);
|
|
24
|
-
Long.fromValue = (value) => {
|
|
25
|
-
if (typeof value === 'bigint') {
|
|
26
|
-
return Long.fromValue(value.toString());
|
|
27
|
-
}
|
|
28
|
-
return originalLongFromValue(value);
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
patchLongJs();
|
|
32
|
-
|
|
33
|
-
const SCALARS = new Map([
|
|
34
|
-
['bool', 'Boolean'],
|
|
35
|
-
['bytes', 'Byte'],
|
|
36
|
-
['double', 'Float'],
|
|
37
|
-
['fixed32', 'Int'],
|
|
38
|
-
['fixed64', 'BigInt'],
|
|
39
|
-
['float', 'Float'],
|
|
40
|
-
['int32', 'Int'],
|
|
41
|
-
['int64', 'BigInt'],
|
|
42
|
-
['sfixed32', 'Int'],
|
|
43
|
-
['sfixed64', 'BigInt'],
|
|
44
|
-
['sint32', 'Int'],
|
|
45
|
-
['sint64', 'BigInt'],
|
|
46
|
-
['string', 'String'],
|
|
47
|
-
['uint32', 'UnsignedInt'],
|
|
48
|
-
['uint64', 'BigInt'], // A new scalar might be needed
|
|
49
|
-
]);
|
|
50
|
-
function isScalarType(type) {
|
|
51
|
-
return SCALARS.has(type);
|
|
52
|
-
}
|
|
53
|
-
function getGraphQLScalar(scalarType) {
|
|
54
|
-
const gqlScalar = SCALARS.get(scalarType);
|
|
55
|
-
if (!gqlScalar) {
|
|
56
|
-
throw new Error(`Could not find GraphQL Scalar for type ${scalarType}`);
|
|
57
|
-
}
|
|
58
|
-
return SCALARS.get(scalarType);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function getTypeName(schemaComposer, pathWithName, isInput) {
|
|
62
|
-
if (pathWithName === null || pathWithName === void 0 ? void 0 : pathWithName.length) {
|
|
63
|
-
const baseTypeName = pathWithName.filter(Boolean).join('_');
|
|
64
|
-
if (isScalarType(baseTypeName)) {
|
|
65
|
-
return getGraphQLScalar(baseTypeName);
|
|
66
|
-
}
|
|
67
|
-
if (schemaComposer.isEnumType(baseTypeName)) {
|
|
68
|
-
return baseTypeName;
|
|
69
|
-
}
|
|
70
|
-
return isInput ? baseTypeName + '_Input' : baseTypeName;
|
|
71
|
-
}
|
|
72
|
-
return 'Void';
|
|
73
|
-
}
|
|
74
|
-
function addIncludePathResolver(root, includePaths) {
|
|
75
|
-
const originalResolvePath = root.resolvePath;
|
|
76
|
-
root.resolvePath = (origin, target) => {
|
|
77
|
-
if (crossHelpers.path.isAbsolute(target)) {
|
|
78
|
-
return target;
|
|
79
|
-
}
|
|
80
|
-
for (const directory of includePaths) {
|
|
81
|
-
const fullPath = crossHelpers.path.join(directory, target);
|
|
82
|
-
if (crossHelpers.fs.existsSync(fullPath)) {
|
|
83
|
-
return fullPath;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const path = originalResolvePath(origin, target);
|
|
87
|
-
if (path === null) {
|
|
88
|
-
console.warn(`${target} not found in any of the include paths ${includePaths}`);
|
|
89
|
-
}
|
|
90
|
-
return path;
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function isBlob(input) {
|
|
94
|
-
return input != null && input.stream instanceof Function;
|
|
95
|
-
}
|
|
96
|
-
function addMetaDataToCall(callFn, input, context, metaData, isResponseStream = false) {
|
|
97
|
-
const callFnArguments = [];
|
|
98
|
-
if (!isBlob(input)) {
|
|
99
|
-
callFnArguments.push(input);
|
|
100
|
-
}
|
|
101
|
-
if (metaData) {
|
|
102
|
-
const meta = new grpcJs.Metadata();
|
|
103
|
-
for (const [key, value] of Object.entries(metaData)) {
|
|
104
|
-
let metaValue = value;
|
|
105
|
-
if (Array.isArray(value)) {
|
|
106
|
-
// Extract data from context
|
|
107
|
-
metaValue = lodashGet(context, value);
|
|
108
|
-
}
|
|
109
|
-
// Ensure that the metadata is compatible with what node-grpc expects
|
|
110
|
-
if (typeof metaValue !== 'string' && !(metaValue instanceof Buffer)) {
|
|
111
|
-
metaValue = JSON.stringify(metaValue);
|
|
112
|
-
}
|
|
113
|
-
if (typeof metaValue === 'string') {
|
|
114
|
-
metaValue = stringInterpolation.stringInterpolator.parse(metaValue, context);
|
|
115
|
-
}
|
|
116
|
-
meta.add(key, metaValue);
|
|
117
|
-
}
|
|
118
|
-
callFnArguments.push(meta);
|
|
119
|
-
}
|
|
120
|
-
return new Promise((resolve, reject) => {
|
|
121
|
-
const call = callFn(...callFnArguments, (error, response) => {
|
|
122
|
-
if (error) {
|
|
123
|
-
reject(error);
|
|
124
|
-
}
|
|
125
|
-
resolve(response);
|
|
126
|
-
});
|
|
127
|
-
if (isResponseStream) {
|
|
128
|
-
let isCancelled = false;
|
|
129
|
-
const responseStreamWithCancel = utils.withCancel(call, () => {
|
|
130
|
-
var _a;
|
|
131
|
-
if (!isCancelled) {
|
|
132
|
-
(_a = call.call) === null || _a === void 0 ? void 0 : _a.cancelWithStatus(0, 'Cancelled by GraphQL Mesh');
|
|
133
|
-
isCancelled = true;
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
resolve(responseStreamWithCancel);
|
|
137
|
-
if (isBlob(input)) {
|
|
138
|
-
input.stream().pipe(call);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/* eslint-disable import/no-duplicates */
|
|
145
|
-
const { Root } = protobufjs;
|
|
146
|
-
const QUERY_METHOD_PREFIXES = ['get', 'list'];
|
|
147
|
-
class GrpcHandler {
|
|
148
|
-
constructor({ config, baseDir, store, logger }) {
|
|
149
|
-
this.schemaComposer = new graphqlCompose.SchemaComposer();
|
|
150
|
-
this.logger = logger;
|
|
151
|
-
this.config = config;
|
|
152
|
-
this.baseDir = baseDir;
|
|
153
|
-
this.rootJsonAndDecodedDescriptorSets = store.proxy('descriptorSet.proto', {
|
|
154
|
-
codify: rootJsonAndDecodedDescriptorSets => `
|
|
155
|
-
import { FileDescriptorSet } from 'protobufjs/ext/descriptor/index.js';
|
|
156
|
-
|
|
157
|
-
export default [
|
|
158
|
-
${rootJsonAndDecodedDescriptorSets
|
|
159
|
-
.map(({ name, rootJson, decodedDescriptorSet }) => `
|
|
160
|
-
{
|
|
161
|
-
name: ${JSON.stringify(name)},
|
|
162
|
-
decodedDescriptorSet: FileDescriptorSet.fromObject(${JSON.stringify(decodedDescriptorSet.toJSON(), null, 2)}),
|
|
163
|
-
rootJson: ${JSON.stringify(rootJson, null, 2)},
|
|
164
|
-
},
|
|
165
|
-
`)
|
|
166
|
-
.join('\n')}
|
|
167
|
-
];
|
|
168
|
-
`.trim(),
|
|
169
|
-
fromJSON: jsonData => {
|
|
170
|
-
return jsonData.map(({ name, rootJson, decodedDescriptorSet }) => ({
|
|
171
|
-
name,
|
|
172
|
-
rootJson,
|
|
173
|
-
decodedDescriptorSet: descriptor.FileDescriptorSet.fromObject(decodedDescriptorSet),
|
|
174
|
-
}));
|
|
175
|
-
},
|
|
176
|
-
toJSON: rootJsonAndDecodedDescriptorSets => {
|
|
177
|
-
return rootJsonAndDecodedDescriptorSets.map(({ name, rootJson, decodedDescriptorSet }) => {
|
|
178
|
-
return {
|
|
179
|
-
name,
|
|
180
|
-
rootJson,
|
|
181
|
-
decodedDescriptorSet: decodedDescriptorSet.toJSON(),
|
|
182
|
-
};
|
|
183
|
-
});
|
|
184
|
-
},
|
|
185
|
-
validate: () => { },
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
async getRootPromisesFromReflection(creds) {
|
|
189
|
-
this.logger.debug(`Using the reflection`);
|
|
190
|
-
const grpcReflectionServer = this.config.endpoint;
|
|
191
|
-
this.logger.debug(`Creating gRPC Reflection Client`);
|
|
192
|
-
const reflectionClient = new grpcReflection.Client(grpcReflectionServer, creds);
|
|
193
|
-
const services = await reflectionClient.listServices();
|
|
194
|
-
const userServices = services.filter(service => service && !(service === null || service === void 0 ? void 0 : service.startsWith('grpc.')));
|
|
195
|
-
return userServices.map(async (service) => {
|
|
196
|
-
this.logger.debug(`Resolving root of Service: ${service} from the reflection response`);
|
|
197
|
-
const serviceRoot = await reflectionClient.fileContainingSymbol(service);
|
|
198
|
-
return serviceRoot;
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
async getRootPromiseFromDescriptorFilePath() {
|
|
202
|
-
var _a;
|
|
203
|
-
let fileName;
|
|
204
|
-
let options;
|
|
205
|
-
if (typeof this.config.descriptorSetFilePath === 'object') {
|
|
206
|
-
fileName = this.config.descriptorSetFilePath.file;
|
|
207
|
-
options = {
|
|
208
|
-
...this.config.descriptorSetFilePath.load,
|
|
209
|
-
includeDirs: (_a = this.config.descriptorSetFilePath.load.includeDirs) === null || _a === void 0 ? void 0 : _a.map(includeDir => crossHelpers.path.isAbsolute(includeDir) ? includeDir : crossHelpers.path.join(this.baseDir, includeDir)),
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
fileName = this.config.descriptorSetFilePath;
|
|
214
|
-
}
|
|
215
|
-
const absoluteFilePath = crossHelpers.path.isAbsolute(fileName) ? fileName : crossHelpers.path.join(this.baseDir, fileName);
|
|
216
|
-
this.logger.debug(`Using the descriptor set from ${absoluteFilePath} `);
|
|
217
|
-
const descriptorSetBuffer = await crossHelpers.fs.promises.readFile(absoluteFilePath);
|
|
218
|
-
this.logger.debug(`Reading ${absoluteFilePath} `);
|
|
219
|
-
let decodedDescriptorSet;
|
|
220
|
-
if (absoluteFilePath.endsWith('json')) {
|
|
221
|
-
this.logger.debug(`Parsing ${absoluteFilePath} as json`);
|
|
222
|
-
const descriptorSetJSON = JSON.parse(descriptorSetBuffer.toString());
|
|
223
|
-
decodedDescriptorSet = descriptor__default.FileDescriptorSet.fromObject(descriptorSetJSON);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
decodedDescriptorSet = descriptor__default.FileDescriptorSet.decode(descriptorSetBuffer);
|
|
227
|
-
}
|
|
228
|
-
this.logger.debug(`Creating root from descriptor set`);
|
|
229
|
-
const rootFromDescriptor = Root.fromDescriptor(decodedDescriptorSet);
|
|
230
|
-
if (options.includeDirs) {
|
|
231
|
-
if (!Array.isArray(options.includeDirs)) {
|
|
232
|
-
return Promise.reject(new Error('The includeDirs option must be an array'));
|
|
233
|
-
}
|
|
234
|
-
addIncludePathResolver(rootFromDescriptor, options.includeDirs);
|
|
235
|
-
}
|
|
236
|
-
return rootFromDescriptor;
|
|
237
|
-
}
|
|
238
|
-
async getRootPromiseFromProtoFilePath() {
|
|
239
|
-
var _a, _b;
|
|
240
|
-
this.logger.debug(`Using proto file(s)`);
|
|
241
|
-
let protoRoot = new Root();
|
|
242
|
-
let fileGlob;
|
|
243
|
-
let options = {
|
|
244
|
-
keepCase: true,
|
|
245
|
-
alternateCommentMode: true,
|
|
246
|
-
};
|
|
247
|
-
if (typeof this.config.protoFilePath === 'object') {
|
|
248
|
-
fileGlob = this.config.protoFilePath.file;
|
|
249
|
-
options = {
|
|
250
|
-
...options,
|
|
251
|
-
...this.config.protoFilePath.load,
|
|
252
|
-
includeDirs: (_b = (_a = this.config.protoFilePath.load) === null || _a === void 0 ? void 0 : _a.includeDirs) === null || _b === void 0 ? void 0 : _b.map(includeDir => crossHelpers.path.isAbsolute(includeDir) ? includeDir : crossHelpers.path.join(this.baseDir, includeDir)),
|
|
253
|
-
};
|
|
254
|
-
if (options.includeDirs) {
|
|
255
|
-
if (!Array.isArray(options.includeDirs)) {
|
|
256
|
-
return Promise.reject(new Error('The includeDirs option must be an array'));
|
|
257
|
-
}
|
|
258
|
-
addIncludePathResolver(protoRoot, options.includeDirs);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
fileGlob = this.config.protoFilePath;
|
|
263
|
-
}
|
|
264
|
-
const fileNames = await globby(fileGlob, {
|
|
265
|
-
cwd: this.baseDir,
|
|
266
|
-
});
|
|
267
|
-
this.logger.debug(`Loading proto files(${fileGlob}); \n ${fileNames.join('\n')} `);
|
|
268
|
-
protoRoot = await protoRoot.load(fileNames.map(filePath => (crossHelpers.path.isAbsolute(filePath) ? filePath : crossHelpers.path.join(this.baseDir, filePath))), options);
|
|
269
|
-
this.logger.debug(`Adding proto content to the root`);
|
|
270
|
-
return protoRoot;
|
|
271
|
-
}
|
|
272
|
-
getCachedDescriptorSets(creds) {
|
|
273
|
-
return this.rootJsonAndDecodedDescriptorSets.getWithSet(async () => {
|
|
274
|
-
const rootPromises = [];
|
|
275
|
-
this.logger.debug(`Building Roots`);
|
|
276
|
-
if (this.config.useReflection) {
|
|
277
|
-
const reflectionPromises = await this.getRootPromisesFromReflection(creds);
|
|
278
|
-
rootPromises.push(...reflectionPromises);
|
|
279
|
-
}
|
|
280
|
-
if (this.config.descriptorSetFilePath) {
|
|
281
|
-
const rootPromise = this.getRootPromiseFromDescriptorFilePath();
|
|
282
|
-
rootPromises.push(rootPromise);
|
|
283
|
-
}
|
|
284
|
-
if (this.config.protoFilePath) {
|
|
285
|
-
const rootPromise = this.getRootPromiseFromProtoFilePath();
|
|
286
|
-
rootPromises.push(rootPromise);
|
|
287
|
-
}
|
|
288
|
-
return Promise.all(rootPromises.map(async (root$, i) => {
|
|
289
|
-
const root = await root$;
|
|
290
|
-
const rootName = root.name || `Root${i}`;
|
|
291
|
-
const rootLogger = this.logger.child(rootName);
|
|
292
|
-
rootLogger.debug(`Resolving entire the root tree`);
|
|
293
|
-
root.resolveAll();
|
|
294
|
-
rootLogger.debug(`Creating artifacts from descriptor set and root`);
|
|
295
|
-
return {
|
|
296
|
-
name: rootName,
|
|
297
|
-
rootJson: root.toJSON({
|
|
298
|
-
keepComments: true,
|
|
299
|
-
}),
|
|
300
|
-
decodedDescriptorSet: root.toDescriptor('proto3'),
|
|
301
|
-
};
|
|
302
|
-
}));
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
async getCredentials() {
|
|
306
|
-
if (this.config.credentialsSsl) {
|
|
307
|
-
this.logger.debug(() => `Using SSL Connection with credentials at ${this.config.credentialsSsl.privateKey} & ${this.config.credentialsSsl.certChain}`);
|
|
308
|
-
const absolutePrivateKeyPath = crossHelpers.path.isAbsolute(this.config.credentialsSsl.privateKey)
|
|
309
|
-
? this.config.credentialsSsl.privateKey
|
|
310
|
-
: crossHelpers.path.join(this.baseDir, this.config.credentialsSsl.privateKey);
|
|
311
|
-
const absoluteCertChainPath = crossHelpers.path.isAbsolute(this.config.credentialsSsl.certChain)
|
|
312
|
-
? this.config.credentialsSsl.certChain
|
|
313
|
-
: crossHelpers.path.join(this.baseDir, this.config.credentialsSsl.certChain);
|
|
314
|
-
const sslFiles = [crossHelpers.fs.promises.readFile(absolutePrivateKeyPath), crossHelpers.fs.promises.readFile(absoluteCertChainPath)];
|
|
315
|
-
if (this.config.credentialsSsl.rootCA !== 'rootCA') {
|
|
316
|
-
const absoluteRootCAPath = crossHelpers.path.isAbsolute(this.config.credentialsSsl.rootCA)
|
|
317
|
-
? this.config.credentialsSsl.rootCA
|
|
318
|
-
: crossHelpers.path.join(this.baseDir, this.config.credentialsSsl.rootCA);
|
|
319
|
-
sslFiles.unshift(crossHelpers.fs.promises.readFile(absoluteRootCAPath));
|
|
320
|
-
}
|
|
321
|
-
const [rootCA, privateKey, certChain] = await Promise.all(sslFiles);
|
|
322
|
-
return grpcJs.credentials.createSsl(rootCA, privateKey, certChain);
|
|
323
|
-
}
|
|
324
|
-
else if (this.config.useHTTPS) {
|
|
325
|
-
this.logger.debug(`Using SSL Connection`);
|
|
326
|
-
return grpcJs.credentials.createSsl();
|
|
327
|
-
}
|
|
328
|
-
this.logger.debug(`Using insecure connection`);
|
|
329
|
-
return grpcJs.credentials.createInsecure();
|
|
330
|
-
}
|
|
331
|
-
walkToFindTypePath(rootJson, pathWithName, baseTypePath) {
|
|
332
|
-
const currentWalkingPath = [...pathWithName];
|
|
333
|
-
while (!lodashHas(rootJson.nested, currentWalkingPath.concat(baseTypePath).join('.nested.'))) {
|
|
334
|
-
if (!currentWalkingPath.length) {
|
|
335
|
-
break;
|
|
336
|
-
}
|
|
337
|
-
currentWalkingPath.pop();
|
|
338
|
-
}
|
|
339
|
-
return currentWalkingPath.concat(baseTypePath);
|
|
340
|
-
}
|
|
341
|
-
visit({ nested, name, currentPath, rootJson, creds, grpcObject, rootLogger: logger, }) {
|
|
342
|
-
var _a;
|
|
343
|
-
const pathWithName = [...currentPath, ...name.split('.')].filter(Boolean);
|
|
344
|
-
if ('nested' in nested) {
|
|
345
|
-
for (const key in nested.nested) {
|
|
346
|
-
logger.debug(`Visiting ${currentPath}.nested[${key}]`);
|
|
347
|
-
const currentNested = nested.nested[key];
|
|
348
|
-
this.visit({
|
|
349
|
-
nested: currentNested,
|
|
350
|
-
name: key,
|
|
351
|
-
currentPath: pathWithName,
|
|
352
|
-
rootJson,
|
|
353
|
-
creds,
|
|
354
|
-
grpcObject,
|
|
355
|
-
rootLogger: logger,
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
const typeName = pathWithName.join('_');
|
|
360
|
-
if ('values' in nested) {
|
|
361
|
-
const enumTypeConfig = {
|
|
362
|
-
name: typeName,
|
|
363
|
-
values: {},
|
|
364
|
-
description: nested.comment,
|
|
365
|
-
};
|
|
366
|
-
const commentMap = nested.comments;
|
|
367
|
-
for (const [key, value] of Object.entries(nested.values)) {
|
|
368
|
-
logger.debug(`Visiting ${currentPath}.nested.values[${key}]`);
|
|
369
|
-
enumTypeConfig.values[key] = {
|
|
370
|
-
value,
|
|
371
|
-
description: commentMap === null || commentMap === void 0 ? void 0 : commentMap[key],
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
this.schemaComposer.createEnumTC(enumTypeConfig);
|
|
375
|
-
}
|
|
376
|
-
else if ('fields' in nested) {
|
|
377
|
-
const inputTypeName = typeName + '_Input';
|
|
378
|
-
const outputTypeName = typeName;
|
|
379
|
-
const description = nested.comment;
|
|
380
|
-
const fieldEntries = Object.entries(nested.fields);
|
|
381
|
-
if (fieldEntries.length) {
|
|
382
|
-
const inputTC = this.schemaComposer.createInputTC({
|
|
383
|
-
name: inputTypeName,
|
|
384
|
-
description,
|
|
385
|
-
fields: {},
|
|
386
|
-
});
|
|
387
|
-
const outputTC = this.schemaComposer.createObjectTC({
|
|
388
|
-
name: outputTypeName,
|
|
389
|
-
description,
|
|
390
|
-
fields: {},
|
|
391
|
-
});
|
|
392
|
-
for (const [fieldName, { type, rule, comment }] of fieldEntries) {
|
|
393
|
-
logger.debug(`Visiting ${currentPath}.nested.fields[${fieldName}]`);
|
|
394
|
-
const baseFieldTypePath = type.split('.');
|
|
395
|
-
inputTC.addFields({
|
|
396
|
-
[fieldName]: {
|
|
397
|
-
type: () => {
|
|
398
|
-
const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
|
|
399
|
-
const fieldInputTypeName = getTypeName(this.schemaComposer, fieldTypePath, true);
|
|
400
|
-
return rule === 'repeated' ? `[${fieldInputTypeName}]` : fieldInputTypeName;
|
|
401
|
-
},
|
|
402
|
-
description: comment,
|
|
403
|
-
},
|
|
404
|
-
});
|
|
405
|
-
outputTC.addFields({
|
|
406
|
-
[fieldName]: {
|
|
407
|
-
type: () => {
|
|
408
|
-
const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
|
|
409
|
-
const fieldTypeName = getTypeName(this.schemaComposer, fieldTypePath, false);
|
|
410
|
-
return rule === 'repeated' ? `[${fieldTypeName}]` : fieldTypeName;
|
|
411
|
-
},
|
|
412
|
-
description: comment,
|
|
413
|
-
},
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
this.schemaComposer.createScalarTC({
|
|
419
|
-
...graphqlScalars.GraphQLJSON.toConfig(),
|
|
420
|
-
name: inputTypeName,
|
|
421
|
-
description,
|
|
422
|
-
});
|
|
423
|
-
this.schemaComposer.createScalarTC({
|
|
424
|
-
...graphqlScalars.GraphQLJSON.toConfig(),
|
|
425
|
-
name: outputTypeName,
|
|
426
|
-
description,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
else if ('methods' in nested) {
|
|
431
|
-
const objPath = pathWithName.join('.');
|
|
432
|
-
const ServiceClient = lodashGet(grpcObject, objPath);
|
|
433
|
-
if (typeof ServiceClient !== 'function') {
|
|
434
|
-
throw new Error(`Object at path ${objPath} is not a Service constructor`);
|
|
435
|
-
}
|
|
436
|
-
const client = new ServiceClient((_a = stringInterpolation.stringInterpolator.parse(this.config.endpoint, { env: crossHelpers.process.env })) !== null && _a !== void 0 ? _a : this.config.endpoint, creds);
|
|
437
|
-
for (const methodName in nested.methods) {
|
|
438
|
-
const method = nested.methods[methodName];
|
|
439
|
-
const rootFieldName = [...pathWithName, methodName].join('_');
|
|
440
|
-
const fieldConfig = {
|
|
441
|
-
type: () => {
|
|
442
|
-
var _a;
|
|
443
|
-
const baseResponseTypePath = (_a = method.responseType) === null || _a === void 0 ? void 0 : _a.split('.');
|
|
444
|
-
if (baseResponseTypePath) {
|
|
445
|
-
const responseTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseResponseTypePath);
|
|
446
|
-
return getTypeName(this.schemaComposer, responseTypePath, false);
|
|
447
|
-
}
|
|
448
|
-
return 'Void';
|
|
449
|
-
},
|
|
450
|
-
description: method.comment,
|
|
451
|
-
};
|
|
452
|
-
fieldConfig.args = {
|
|
453
|
-
input: () => {
|
|
454
|
-
var _a;
|
|
455
|
-
if (method.requestStream) {
|
|
456
|
-
return 'File';
|
|
457
|
-
}
|
|
458
|
-
const baseRequestTypePath = (_a = method.requestType) === null || _a === void 0 ? void 0 : _a.split('.');
|
|
459
|
-
if (baseRequestTypePath) {
|
|
460
|
-
const requestTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseRequestTypePath);
|
|
461
|
-
const requestTypeName = getTypeName(this.schemaComposer, requestTypePath, true);
|
|
462
|
-
return requestTypeName;
|
|
463
|
-
}
|
|
464
|
-
return undefined;
|
|
465
|
-
},
|
|
466
|
-
};
|
|
467
|
-
if (method.responseStream) {
|
|
468
|
-
this.schemaComposer.Subscription.addFields({
|
|
469
|
-
[rootFieldName]: {
|
|
470
|
-
...fieldConfig,
|
|
471
|
-
subscribe: (__, args, context) => addMetaDataToCall(client[methodName].bind(client), args.input, context, this.config.metaData, true),
|
|
472
|
-
resolve: (payload) => payload,
|
|
473
|
-
},
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
else {
|
|
477
|
-
const methodNameLowerCased = methodName.toLowerCase();
|
|
478
|
-
const prefixQueryMethod = this.config.prefixQueryMethod || QUERY_METHOD_PREFIXES;
|
|
479
|
-
const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
|
|
480
|
-
? this.schemaComposer.Query
|
|
481
|
-
: this.schemaComposer.Mutation;
|
|
482
|
-
rootTypeComposer.addFields({
|
|
483
|
-
[rootFieldName]: {
|
|
484
|
-
...fieldConfig,
|
|
485
|
-
resolve: (_, args, context) => addMetaDataToCall(client[methodName].bind(client), args.input, context, this.config.metaData),
|
|
486
|
-
},
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
const connectivityStateFieldName = pathWithName.join('_') + '_connectivityState';
|
|
491
|
-
this.schemaComposer.Query.addFields({
|
|
492
|
-
[connectivityStateFieldName]: {
|
|
493
|
-
type: 'ConnectivityState',
|
|
494
|
-
args: {
|
|
495
|
-
tryToConnect: {
|
|
496
|
-
type: 'Boolean',
|
|
497
|
-
},
|
|
498
|
-
},
|
|
499
|
-
resolve: (_, { tryToConnect }) => client.getChannel().getConnectivityState(tryToConnect),
|
|
500
|
-
},
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
async getMeshSource() {
|
|
505
|
-
this.config.requestTimeout = this.config.requestTimeout || 200000;
|
|
506
|
-
this.schemaComposer.add(graphqlScalars.GraphQLBigInt);
|
|
507
|
-
this.schemaComposer.add(graphqlScalars.GraphQLByte);
|
|
508
|
-
this.schemaComposer.add(graphqlScalars.GraphQLUnsignedInt);
|
|
509
|
-
this.schemaComposer.add(graphqlScalars.GraphQLVoid);
|
|
510
|
-
this.schemaComposer.add(graphqlScalars.GraphQLJSON);
|
|
511
|
-
this.schemaComposer.createScalarTC({
|
|
512
|
-
name: 'File',
|
|
513
|
-
});
|
|
514
|
-
// identical of grpc's ConnectivityState
|
|
515
|
-
this.schemaComposer.createEnumTC({
|
|
516
|
-
name: 'ConnectivityState',
|
|
517
|
-
values: {
|
|
518
|
-
IDLE: { value: 0 },
|
|
519
|
-
CONNECTING: { value: 1 },
|
|
520
|
-
READY: { value: 2 },
|
|
521
|
-
TRANSIENT_FAILURE: { value: 3 },
|
|
522
|
-
SHUTDOWN: { value: 4 },
|
|
523
|
-
},
|
|
524
|
-
});
|
|
525
|
-
this.logger.debug(`Getting channel credentials`);
|
|
526
|
-
const creds = await this.getCredentials();
|
|
527
|
-
this.logger.debug(`Getting stored root and decoded descriptor set objects`);
|
|
528
|
-
const artifacts = await this.getCachedDescriptorSets(creds);
|
|
529
|
-
for (const { name, rootJson, decodedDescriptorSet } of artifacts) {
|
|
530
|
-
const rootLogger = this.logger.child(name);
|
|
531
|
-
rootLogger.debug(`Creating package definition from file descriptor set object`);
|
|
532
|
-
const packageDefinition = protoLoader.loadFileDescriptorSetFromObject(decodedDescriptorSet);
|
|
533
|
-
rootLogger.debug(`Creating service client for package definition`);
|
|
534
|
-
const grpcObject = grpcJs.loadPackageDefinition(packageDefinition);
|
|
535
|
-
this.logger.debug(`Building the schema structure based on the root object`);
|
|
536
|
-
this.visit({ nested: rootJson, name: '', currentPath: [], rootJson, creds, grpcObject, rootLogger });
|
|
537
|
-
}
|
|
538
|
-
// graphql-compose doesn't add @defer and @stream to the schema
|
|
539
|
-
graphql.specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
|
|
540
|
-
this.logger.debug(`Building the final GraphQL Schema`);
|
|
541
|
-
const schema = this.schemaComposer.buildSchema();
|
|
542
|
-
return {
|
|
543
|
-
schema,
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
module.exports = GrpcHandler;
|
|
File without changes
|
|
File without changes
|