@graphql-mesh/grpc 1.0.0-alpha-20230424111644-b7c761da0 → 1.0.0-alpha-20230522105300-fe9c79867

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.
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.grpcRootJsonDirective = exports.ObjMapScalar = exports.grpcConnectivityStateDirective = exports.grpcMethodDirective = void 0;
4
+ const graphql_1 = require("graphql");
5
+ exports.grpcMethodDirective = new graphql_1.GraphQLDirective({
6
+ name: 'grpcMethod',
7
+ locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
8
+ args: {
9
+ rootJsonName: {
10
+ type: graphql_1.GraphQLString,
11
+ },
12
+ objPath: {
13
+ type: graphql_1.GraphQLString,
14
+ },
15
+ methodName: {
16
+ type: graphql_1.GraphQLString,
17
+ },
18
+ responseStream: {
19
+ type: graphql_1.GraphQLBoolean,
20
+ },
21
+ },
22
+ });
23
+ exports.grpcConnectivityStateDirective = new graphql_1.GraphQLDirective({
24
+ name: 'grpcConnectivityState',
25
+ locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
26
+ args: {
27
+ rootJsonName: {
28
+ type: graphql_1.GraphQLString,
29
+ },
30
+ objPath: {
31
+ type: graphql_1.GraphQLString,
32
+ },
33
+ },
34
+ });
35
+ exports.ObjMapScalar = new graphql_1.GraphQLScalarType({
36
+ name: 'ObjMap',
37
+ serialize: value => JSON.stringify(value),
38
+ parseValue: value => JSON.parse(value.toString()),
39
+ parseLiteral: ast => {
40
+ if (ast.kind === 'StringValue') {
41
+ return JSON.parse(ast.value);
42
+ }
43
+ return null;
44
+ },
45
+ });
46
+ exports.grpcRootJsonDirective = new graphql_1.GraphQLDirective({
47
+ name: 'grpcRootJson',
48
+ locations: [graphql_1.DirectiveLocation.OBJECT],
49
+ args: {
50
+ name: {
51
+ type: graphql_1.GraphQLString,
52
+ },
53
+ rootJson: {
54
+ type: exports.ObjMapScalar,
55
+ },
56
+ loadOptions: {
57
+ type: exports.ObjMapScalar,
58
+ },
59
+ },
60
+ isRepeatable: true,
61
+ });
package/cjs/index.js CHANGED
@@ -13,49 +13,27 @@ const index_js_1 = tslib_1.__importDefault(require("protobufjs/ext/descriptor/in
13
13
  const grpc_reflection_js_1 = require("@ardatan/grpc-reflection-js");
14
14
  const cross_helpers_1 = require("@graphql-mesh/cross-helpers");
15
15
  const cross_helpers_2 = require("@graphql-mesh/cross-helpers");
16
+ const store_1 = require("@graphql-mesh/store");
16
17
  const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
18
+ const utils_1 = require("@graphql-mesh/utils");
19
+ const utils_2 = require("@graphql-tools/utils");
17
20
  const grpc_js_1 = require("@grpc/grpc-js");
18
21
  const proto_loader_1 = require("@grpc/proto-loader");
22
+ const directives_js_1 = require("./directives.js");
19
23
  require("./patchLongJs.js");
20
24
  const utils_js_1 = require("./utils.js");
21
25
  const { Root } = protobufjs_1.default;
22
26
  const QUERY_METHOD_PREFIXES = ['get', 'list', 'search'];
23
27
  class GrpcHandler {
24
- constructor({ config, baseDir, store, logger, pubsub, }) {
28
+ constructor({ config, baseDir, store, logger, pubsub, importFn, }) {
29
+ this.grpcObjectByserviceClientByObjPath = new WeakMap();
25
30
  this.schemaComposer = new graphql_compose_1.SchemaComposer();
26
31
  this.logger = logger;
27
32
  this.config = config;
28
33
  this.baseDir = baseDir;
29
- this.rootJsonEntries = store.proxy('rootJsonEntries', {
30
- codify: rootJsonEntries => `
31
- export default [
32
- ${rootJsonEntries
33
- .map(({ name, rootJson }) => `
34
- {
35
- name: ${JSON.stringify(name)},
36
- rootJson: ${JSON.stringify(rootJson, null, 2)},
37
- },
38
- `)
39
- .join('\n')}
40
- ];
41
- `.trim(),
42
- fromJSON: jsonData => {
43
- return jsonData.map(({ name, rootJson }) => ({
44
- name,
45
- rootJson,
46
- }));
47
- },
48
- toJSON: rootJsonEntries => {
49
- return rootJsonEntries.map(({ name, rootJson }) => {
50
- return {
51
- name,
52
- rootJson,
53
- };
54
- });
55
- },
56
- validate: () => { },
57
- });
34
+ this.schemaWithAnnotationsProxy = store.proxy('schemaWithAnnotations', store_1.PredefinedProxyOptions.GraphQLSchemaWithDiffing);
58
35
  this.pubsub = pubsub;
36
+ this.importFn = importFn;
59
37
  }
60
38
  async processReflection(creds) {
61
39
  this.logger.debug(`Using the reflection`);
@@ -147,38 +125,36 @@ ${rootJsonEntries
147
125
  this.logger.debug(`Adding proto content to the root`);
148
126
  return protoRoot;
149
127
  }
150
- getCachedDescriptorSets(creds) {
151
- return this.rootJsonEntries.getWithSet(async () => {
152
- const rootPromises = [];
153
- this.logger.debug(`Building Roots`);
154
- if (this.config.source) {
155
- const filePath = typeof this.config.source === 'string' ? this.config.source : this.config.source.file;
156
- if (filePath.endsWith('json')) {
157
- rootPromises.push(this.processDescriptorFile());
158
- }
159
- else if (filePath.endsWith('proto')) {
160
- rootPromises.push(this.processProtoFile());
161
- }
128
+ async getDescriptorSets(creds) {
129
+ const rootPromises = [];
130
+ this.logger.debug(`Building Roots`);
131
+ if (this.config.source) {
132
+ const filePath = typeof this.config.source === 'string' ? this.config.source : this.config.source.file;
133
+ if (filePath.endsWith('json')) {
134
+ rootPromises.push(this.processDescriptorFile());
162
135
  }
163
- else {
164
- const reflectionPromises = await this.processReflection(creds);
165
- rootPromises.push(...reflectionPromises);
136
+ else if (filePath.endsWith('proto')) {
137
+ rootPromises.push(this.processProtoFile());
166
138
  }
167
- return Promise.all(rootPromises.map(async (root$, i) => {
168
- const root = await root$;
169
- const rootName = root.name || `Root${i}`;
170
- const rootLogger = this.logger.child(rootName);
171
- rootLogger.debug(`Resolving entire the root tree`);
172
- root.resolveAll();
173
- rootLogger.debug(`Creating artifacts from descriptor set and root`);
174
- return {
175
- name: rootName,
176
- rootJson: root.toJSON({
177
- keepComments: true,
178
- }),
179
- };
180
- }));
181
- });
139
+ }
140
+ else {
141
+ const reflectionPromises = await this.processReflection(creds);
142
+ rootPromises.push(...reflectionPromises);
143
+ }
144
+ return Promise.all(rootPromises.map(async (root$, i) => {
145
+ const root = await root$;
146
+ const rootName = root.name || `Root${i}`;
147
+ const rootLogger = this.logger.child(rootName);
148
+ rootLogger.debug(`Resolving entire the root tree`);
149
+ root.resolveAll();
150
+ rootLogger.debug(`Creating artifacts from descriptor set and root`);
151
+ return {
152
+ name: rootName,
153
+ rootJson: root.toJSON({
154
+ keepComments: true,
155
+ }),
156
+ };
157
+ }));
182
158
  }
183
159
  async getCredentials() {
184
160
  if (this.config.credentialsSsl) {
@@ -219,8 +195,102 @@ ${rootJsonEntries
219
195
  }
220
196
  return currentWalkingPath.concat(baseTypePath);
221
197
  }
222
- visit({ nested, name, currentPath, rootJson, creds, grpcObject, rootLogger: logger, }) {
198
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }) {
199
+ const packageDefinition = (0, proto_loader_1.fromJSON)(rootJson, loadOptions);
200
+ rootLogger.debug(`Creating service client for package definition`);
201
+ const grpcObject = (0, grpc_js_1.loadPackageDefinition)(packageDefinition);
202
+ return grpcObject;
203
+ }
204
+ getServiceClient({ grpcObject, objPath, creds, }) {
223
205
  var _a;
206
+ let serviceClientByObjPath = this.grpcObjectByserviceClientByObjPath.get(grpcObject);
207
+ if (!serviceClientByObjPath) {
208
+ serviceClientByObjPath = new Map();
209
+ this.grpcObjectByserviceClientByObjPath.set(grpcObject, serviceClientByObjPath);
210
+ }
211
+ let client = serviceClientByObjPath.get(objPath);
212
+ if (!client) {
213
+ const ServiceClient = (0, lodash_get_1.default)(grpcObject, objPath);
214
+ if (typeof ServiceClient !== 'function') {
215
+ throw new Error(`Object at path ${objPath} is not a Service constructor`);
216
+ }
217
+ client = new ServiceClient((_a = string_interpolation_1.stringInterpolator.parse(this.config.endpoint, { env: cross_helpers_1.process.env })) !== null && _a !== void 0 ? _a : this.config.endpoint, creds);
218
+ const subId = this.pubsub.subscribe('destroy', () => {
219
+ client.close();
220
+ this.pubsub.unsubscribe(subId);
221
+ });
222
+ serviceClientByObjPath.set(objPath, client);
223
+ }
224
+ return client;
225
+ }
226
+ getFieldResolver({ client, methodName, isResponseStream, }) {
227
+ const metaData = this.config.metaData;
228
+ const clientMethod = client[methodName].bind(client);
229
+ return function grpcFieldResolver(root, args, context) {
230
+ return (0, utils_js_1.addMetaDataToCall)(clientMethod, args.input, {
231
+ root,
232
+ args,
233
+ context,
234
+ env: cross_helpers_1.process.env,
235
+ }, metaData, isResponseStream);
236
+ };
237
+ }
238
+ getConnectivityStateResolver({ client, }) {
239
+ return function connectivityStateResolver(_, { tryToConnect }) {
240
+ return client.getChannel().getConnectivityState(tryToConnect);
241
+ };
242
+ }
243
+ processDirectives({ schema, creds }) {
244
+ const queryType = schema.getQueryType();
245
+ const rootJsonAnnotations = (0, utils_2.getDirective)(schema, queryType, 'grpcRootJson');
246
+ const rootJsonMap = new Map();
247
+ const grpcObjectByRootJsonName = new Map();
248
+ for (const { name, rootJson, loadOptions } of rootJsonAnnotations) {
249
+ rootJsonMap.set(name, rootJson);
250
+ const rootLogger = this.logger.child(name);
251
+ grpcObjectByRootJsonName.set(name, this.getGrpcObject({ rootJson, loadOptions, rootLogger }));
252
+ }
253
+ const rootTypes = (0, utils_2.getRootTypes)(schema);
254
+ for (const rootType of rootTypes) {
255
+ for (const fieldName in rootType.getFields()) {
256
+ const field = rootType.getFields()[fieldName];
257
+ const directives = (0, utils_2.getDirectives)(schema, field);
258
+ if (directives === null || directives === void 0 ? void 0 : directives.length) {
259
+ for (const directiveObj of directives) {
260
+ switch (directiveObj.name) {
261
+ case 'grpcMethod': {
262
+ const { rootJsonName, objPath, methodName, responseStream } = directiveObj.args;
263
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
264
+ const client = this.getServiceClient({
265
+ grpcObject,
266
+ objPath,
267
+ creds,
268
+ });
269
+ field.resolve = this.getFieldResolver({
270
+ client,
271
+ methodName,
272
+ isResponseStream: responseStream,
273
+ });
274
+ break;
275
+ }
276
+ case 'grpcConnectivityState': {
277
+ const { rootJsonName, objPath } = directiveObj.args;
278
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
279
+ const client = this.getServiceClient({
280
+ grpcObject,
281
+ objPath,
282
+ creds,
283
+ });
284
+ field.resolve = this.getConnectivityStateResolver({ client });
285
+ break;
286
+ }
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ }
293
+ visit({ nested, name, currentPath, rootJsonName, rootJson, rootLogger: logger, loadOptions, }) {
224
294
  const pathWithName = [...currentPath, ...name.split('.')].filter(Boolean);
225
295
  if ('nested' in nested) {
226
296
  for (const key in nested.nested) {
@@ -230,9 +300,8 @@ ${rootJsonEntries
230
300
  nested: currentNested,
231
301
  name: key,
232
302
  currentPath: pathWithName,
303
+ rootJsonName,
233
304
  rootJson,
234
- creds,
235
- grpcObject,
236
305
  rootLogger: logger,
237
306
  });
238
307
  }
@@ -322,15 +391,6 @@ ${rootJsonEntries
322
391
  }
323
392
  else if ('methods' in nested) {
324
393
  const objPath = pathWithName.join('.');
325
- const ServiceClient = (0, lodash_get_1.default)(grpcObject, objPath);
326
- if (typeof ServiceClient !== 'function') {
327
- throw new Error(`Object at path ${objPath} is not a Service constructor`);
328
- }
329
- const client = new ServiceClient((_a = string_interpolation_1.stringInterpolator.parse(this.config.endpoint, { env: cross_helpers_1.process.env })) !== null && _a !== void 0 ? _a : this.config.endpoint, creds);
330
- const subId = this.pubsub.subscribe('destroy', () => {
331
- client.close();
332
- this.pubsub.unsubscribe(subId);
333
- });
334
394
  for (const methodName in nested.methods) {
335
395
  const method = nested.methods[methodName];
336
396
  const rootFieldName = [...pathWithName, methodName].join('_');
@@ -370,19 +430,26 @@ ${rootJsonEntries
370
430
  const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
371
431
  ? this.schemaComposer.Query
372
432
  : this.schemaComposer.Mutation;
433
+ this.schemaComposer.addDirective(directives_js_1.grpcMethodDirective);
373
434
  rootTypeComposer.addFields({
374
435
  [rootFieldName]: {
375
436
  ...fieldConfig,
376
- resolve: (root, args, context, info) => (0, utils_js_1.addMetaDataToCall)(client[methodName].bind(client), args.input, {
377
- root,
378
- args,
379
- context,
380
- env: cross_helpers_1.process.env,
381
- }, this.config.metaData, !!method.responseStream),
437
+ directives: [
438
+ {
439
+ name: 'grpcMethod',
440
+ args: {
441
+ rootJsonName,
442
+ objPath,
443
+ methodName,
444
+ responseStream: !!method.responseStream,
445
+ },
446
+ },
447
+ ],
382
448
  },
383
449
  });
384
450
  }
385
451
  const connectivityStateFieldName = pathWithName.join('_') + '_connectivityState';
452
+ this.schemaComposer.addDirective(directives_js_1.grpcConnectivityStateDirective);
386
453
  this.schemaComposer.Query.addFields({
387
454
  [connectivityStateFieldName]: {
388
455
  type: 'ConnectivityState',
@@ -391,61 +458,96 @@ ${rootJsonEntries
391
458
  type: 'Boolean',
392
459
  },
393
460
  },
394
- resolve: (_, { tryToConnect }) => client.getChannel().getConnectivityState(tryToConnect),
461
+ directives: [
462
+ {
463
+ name: 'grpcConnectivityState',
464
+ args: {
465
+ rootJsonName,
466
+ objPath,
467
+ },
468
+ },
469
+ ],
395
470
  },
396
471
  });
397
472
  }
398
473
  }
399
- async getMeshSource() {
400
- this.config.requestTimeout = this.config.requestTimeout || 200000;
401
- this.schemaComposer.add(graphql_scalars_1.GraphQLBigInt);
402
- this.schemaComposer.add(graphql_scalars_1.GraphQLByte);
403
- this.schemaComposer.add(graphql_scalars_1.GraphQLUnsignedInt);
404
- this.schemaComposer.add(graphql_scalars_1.GraphQLVoid);
405
- this.schemaComposer.add(graphql_scalars_1.GraphQLJSON);
406
- this.schemaComposer.createScalarTC({
407
- name: 'File',
408
- });
409
- // identical of grpc's ConnectivityState
410
- this.schemaComposer.createEnumTC({
411
- name: 'ConnectivityState',
412
- values: {
413
- IDLE: { value: 0 },
414
- CONNECTING: { value: 1 },
415
- READY: { value: 2 },
416
- TRANSIENT_FAILURE: { value: 3 },
417
- SHUTDOWN: { value: 4 },
418
- },
474
+ async getCachedNonExecutableSchema(creds) {
475
+ var _a;
476
+ const interpolatedSource = (_a = this.config.source) === null || _a === void 0 ? void 0 : _a.toString();
477
+ if (interpolatedSource === null || interpolatedSource === void 0 ? void 0 : interpolatedSource.endsWith('.graphql')) {
478
+ this.logger.info(`Fetching GraphQL Schema with annotations`);
479
+ const sdl = await (0, utils_1.readFileOrUrl)(interpolatedSource, {
480
+ allowUnknownExtensions: true,
481
+ cwd: this.baseDir,
482
+ fetch: this.fetchFn,
483
+ importFn: this.importFn,
484
+ logger: this.logger,
485
+ headers: this.config.schemaHeaders,
486
+ });
487
+ return (0, graphql_1.buildSchema)(sdl, {
488
+ assumeValidSDL: true,
489
+ assumeValid: true,
490
+ });
491
+ }
492
+ return this.schemaWithAnnotationsProxy.getWithSet(async () => {
493
+ this.schemaComposer.add(graphql_scalars_1.GraphQLBigInt);
494
+ this.schemaComposer.add(graphql_scalars_1.GraphQLByte);
495
+ this.schemaComposer.add(graphql_scalars_1.GraphQLUnsignedInt);
496
+ this.schemaComposer.add(graphql_scalars_1.GraphQLVoid);
497
+ this.schemaComposer.add(graphql_scalars_1.GraphQLJSON);
498
+ this.schemaComposer.createScalarTC({
499
+ name: 'File',
500
+ });
501
+ // identical of grpc's ConnectivityState
502
+ this.schemaComposer.createEnumTC({
503
+ name: 'ConnectivityState',
504
+ values: {
505
+ IDLE: { value: 0 },
506
+ CONNECTING: { value: 1 },
507
+ READY: { value: 2 },
508
+ TRANSIENT_FAILURE: { value: 3 },
509
+ SHUTDOWN: { value: 4 },
510
+ },
511
+ });
512
+ this.logger.debug(`Getting stored root and decoded descriptor set objects`);
513
+ const descriptorSets = await this.getDescriptorSets(creds);
514
+ for (const { name: rootJsonName, rootJson } of descriptorSets) {
515
+ const rootLogger = this.logger.child(rootJsonName);
516
+ rootLogger.debug(`Creating package definition from file descriptor set object`);
517
+ let loadOptions;
518
+ if (typeof this.config.source === 'object') {
519
+ loadOptions = this.config.source.load;
520
+ }
521
+ this.logger.debug(`Building the schema structure based on the root object`);
522
+ this.visit({
523
+ nested: rootJson,
524
+ name: '',
525
+ currentPath: [],
526
+ rootJsonName,
527
+ rootJson,
528
+ rootLogger,
529
+ loadOptions,
530
+ });
531
+ this.schemaComposer.addDirective(directives_js_1.grpcRootJsonDirective);
532
+ this.schemaComposer.Query.setDirectiveByName('grpcRootJson', {
533
+ name: rootJsonName,
534
+ rootJson,
535
+ });
536
+ }
537
+ // graphql-compose doesn't add @defer and @stream to the schema
538
+ graphql_1.specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
539
+ this.logger.debug(`Building the final GraphQL Schema`);
540
+ const schema = this.schemaComposer.buildSchema();
541
+ return schema;
419
542
  });
543
+ }
544
+ async getMeshSource({ fetchFn }) {
545
+ this.fetchFn = fetchFn;
546
+ this.config.requestTimeout = this.config.requestTimeout || 200000;
420
547
  this.logger.debug(`Getting channel credentials`);
421
548
  const creds = await this.getCredentials();
422
- this.logger.debug(`Getting stored root and decoded descriptor set objects`);
423
- const artifacts = await this.getCachedDescriptorSets(creds);
424
- for (const { name, rootJson } of artifacts) {
425
- const rootLogger = this.logger.child(name);
426
- rootLogger.debug(`Creating package definition from file descriptor set object`);
427
- let options;
428
- if (typeof this.config.source === 'object') {
429
- options = this.config.source.load;
430
- }
431
- const packageDefinition = (0, proto_loader_1.fromJSON)(rootJson, options);
432
- rootLogger.debug(`Creating service client for package definition`);
433
- const grpcObject = (0, grpc_js_1.loadPackageDefinition)(packageDefinition);
434
- this.logger.debug(`Building the schema structure based on the root object`);
435
- this.visit({
436
- nested: rootJson,
437
- name: '',
438
- currentPath: [],
439
- rootJson,
440
- creds,
441
- grpcObject,
442
- rootLogger,
443
- });
444
- }
445
- // graphql-compose doesn't add @defer and @stream to the schema
446
- graphql_1.specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
447
- this.logger.debug(`Building the final GraphQL Schema`);
448
- const schema = this.schemaComposer.buildSchema();
549
+ const schema = await this.getCachedNonExecutableSchema(creds);
550
+ this.processDirectives({ schema, creds });
449
551
  return {
450
552
  schema,
451
553
  };
@@ -0,0 +1,58 @@
1
+ import { DirectiveLocation, GraphQLBoolean, GraphQLDirective, GraphQLScalarType, GraphQLString, } from 'graphql';
2
+ export const grpcMethodDirective = new GraphQLDirective({
3
+ name: 'grpcMethod',
4
+ locations: [DirectiveLocation.FIELD_DEFINITION],
5
+ args: {
6
+ rootJsonName: {
7
+ type: GraphQLString,
8
+ },
9
+ objPath: {
10
+ type: GraphQLString,
11
+ },
12
+ methodName: {
13
+ type: GraphQLString,
14
+ },
15
+ responseStream: {
16
+ type: GraphQLBoolean,
17
+ },
18
+ },
19
+ });
20
+ export const grpcConnectivityStateDirective = new GraphQLDirective({
21
+ name: 'grpcConnectivityState',
22
+ locations: [DirectiveLocation.FIELD_DEFINITION],
23
+ args: {
24
+ rootJsonName: {
25
+ type: GraphQLString,
26
+ },
27
+ objPath: {
28
+ type: GraphQLString,
29
+ },
30
+ },
31
+ });
32
+ export const ObjMapScalar = new GraphQLScalarType({
33
+ name: 'ObjMap',
34
+ serialize: value => JSON.stringify(value),
35
+ parseValue: value => JSON.parse(value.toString()),
36
+ parseLiteral: ast => {
37
+ if (ast.kind === 'StringValue') {
38
+ return JSON.parse(ast.value);
39
+ }
40
+ return null;
41
+ },
42
+ });
43
+ export const grpcRootJsonDirective = new GraphQLDirective({
44
+ name: 'grpcRootJson',
45
+ locations: [DirectiveLocation.OBJECT],
46
+ args: {
47
+ name: {
48
+ type: GraphQLString,
49
+ },
50
+ rootJson: {
51
+ type: ObjMapScalar,
52
+ },
53
+ loadOptions: {
54
+ type: ObjMapScalar,
55
+ },
56
+ },
57
+ isRepeatable: true,
58
+ });
package/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable import/no-duplicates */
2
2
  import globby from 'globby';
3
- import { specifiedDirectives } from 'graphql';
3
+ import { buildSchema, specifiedDirectives, } from 'graphql';
4
4
  import { SchemaComposer } from 'graphql-compose';
5
5
  import { GraphQLBigInt, GraphQLByte, GraphQLJSON, GraphQLUnsignedInt, GraphQLVoid, } from 'graphql-scalars';
6
6
  import lodashGet from 'lodash.get';
@@ -10,49 +10,27 @@ import descriptor from 'protobufjs/ext/descriptor/index.js';
10
10
  import { Client } from '@ardatan/grpc-reflection-js';
11
11
  import { path, process } from '@graphql-mesh/cross-helpers';
12
12
  import { fs } from '@graphql-mesh/cross-helpers';
13
+ import { PredefinedProxyOptions } from '@graphql-mesh/store';
13
14
  import { stringInterpolator } from '@graphql-mesh/string-interpolation';
15
+ import { readFileOrUrl } from '@graphql-mesh/utils';
16
+ import { getDirective, getDirectives, getRootTypes } from '@graphql-tools/utils';
14
17
  import { credentials, loadPackageDefinition } from '@grpc/grpc-js';
15
18
  import { fromJSON } from '@grpc/proto-loader';
19
+ import { grpcConnectivityStateDirective, grpcMethodDirective, grpcRootJsonDirective, } from './directives.js';
16
20
  import './patchLongJs.js';
17
21
  import { addIncludePathResolver, addMetaDataToCall, getTypeName } from './utils.js';
18
22
  const { Root } = protobufjs;
19
23
  const QUERY_METHOD_PREFIXES = ['get', 'list', 'search'];
20
24
  export default class GrpcHandler {
21
- constructor({ config, baseDir, store, logger, pubsub, }) {
25
+ constructor({ config, baseDir, store, logger, pubsub, importFn, }) {
26
+ this.grpcObjectByserviceClientByObjPath = new WeakMap();
22
27
  this.schemaComposer = new SchemaComposer();
23
28
  this.logger = logger;
24
29
  this.config = config;
25
30
  this.baseDir = baseDir;
26
- this.rootJsonEntries = store.proxy('rootJsonEntries', {
27
- codify: rootJsonEntries => `
28
- export default [
29
- ${rootJsonEntries
30
- .map(({ name, rootJson }) => `
31
- {
32
- name: ${JSON.stringify(name)},
33
- rootJson: ${JSON.stringify(rootJson, null, 2)},
34
- },
35
- `)
36
- .join('\n')}
37
- ];
38
- `.trim(),
39
- fromJSON: jsonData => {
40
- return jsonData.map(({ name, rootJson }) => ({
41
- name,
42
- rootJson,
43
- }));
44
- },
45
- toJSON: rootJsonEntries => {
46
- return rootJsonEntries.map(({ name, rootJson }) => {
47
- return {
48
- name,
49
- rootJson,
50
- };
51
- });
52
- },
53
- validate: () => { },
54
- });
31
+ this.schemaWithAnnotationsProxy = store.proxy('schemaWithAnnotations', PredefinedProxyOptions.GraphQLSchemaWithDiffing);
55
32
  this.pubsub = pubsub;
33
+ this.importFn = importFn;
56
34
  }
57
35
  async processReflection(creds) {
58
36
  this.logger.debug(`Using the reflection`);
@@ -144,38 +122,36 @@ ${rootJsonEntries
144
122
  this.logger.debug(`Adding proto content to the root`);
145
123
  return protoRoot;
146
124
  }
147
- getCachedDescriptorSets(creds) {
148
- return this.rootJsonEntries.getWithSet(async () => {
149
- const rootPromises = [];
150
- this.logger.debug(`Building Roots`);
151
- if (this.config.source) {
152
- const filePath = typeof this.config.source === 'string' ? this.config.source : this.config.source.file;
153
- if (filePath.endsWith('json')) {
154
- rootPromises.push(this.processDescriptorFile());
155
- }
156
- else if (filePath.endsWith('proto')) {
157
- rootPromises.push(this.processProtoFile());
158
- }
125
+ async getDescriptorSets(creds) {
126
+ const rootPromises = [];
127
+ this.logger.debug(`Building Roots`);
128
+ if (this.config.source) {
129
+ const filePath = typeof this.config.source === 'string' ? this.config.source : this.config.source.file;
130
+ if (filePath.endsWith('json')) {
131
+ rootPromises.push(this.processDescriptorFile());
159
132
  }
160
- else {
161
- const reflectionPromises = await this.processReflection(creds);
162
- rootPromises.push(...reflectionPromises);
133
+ else if (filePath.endsWith('proto')) {
134
+ rootPromises.push(this.processProtoFile());
163
135
  }
164
- return Promise.all(rootPromises.map(async (root$, i) => {
165
- const root = await root$;
166
- const rootName = root.name || `Root${i}`;
167
- const rootLogger = this.logger.child(rootName);
168
- rootLogger.debug(`Resolving entire the root tree`);
169
- root.resolveAll();
170
- rootLogger.debug(`Creating artifacts from descriptor set and root`);
171
- return {
172
- name: rootName,
173
- rootJson: root.toJSON({
174
- keepComments: true,
175
- }),
176
- };
177
- }));
178
- });
136
+ }
137
+ else {
138
+ const reflectionPromises = await this.processReflection(creds);
139
+ rootPromises.push(...reflectionPromises);
140
+ }
141
+ return Promise.all(rootPromises.map(async (root$, i) => {
142
+ const root = await root$;
143
+ const rootName = root.name || `Root${i}`;
144
+ const rootLogger = this.logger.child(rootName);
145
+ rootLogger.debug(`Resolving entire the root tree`);
146
+ root.resolveAll();
147
+ rootLogger.debug(`Creating artifacts from descriptor set and root`);
148
+ return {
149
+ name: rootName,
150
+ rootJson: root.toJSON({
151
+ keepComments: true,
152
+ }),
153
+ };
154
+ }));
179
155
  }
180
156
  async getCredentials() {
181
157
  if (this.config.credentialsSsl) {
@@ -216,8 +192,102 @@ ${rootJsonEntries
216
192
  }
217
193
  return currentWalkingPath.concat(baseTypePath);
218
194
  }
219
- visit({ nested, name, currentPath, rootJson, creds, grpcObject, rootLogger: logger, }) {
195
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }) {
196
+ const packageDefinition = fromJSON(rootJson, loadOptions);
197
+ rootLogger.debug(`Creating service client for package definition`);
198
+ const grpcObject = loadPackageDefinition(packageDefinition);
199
+ return grpcObject;
200
+ }
201
+ getServiceClient({ grpcObject, objPath, creds, }) {
220
202
  var _a;
203
+ let serviceClientByObjPath = this.grpcObjectByserviceClientByObjPath.get(grpcObject);
204
+ if (!serviceClientByObjPath) {
205
+ serviceClientByObjPath = new Map();
206
+ this.grpcObjectByserviceClientByObjPath.set(grpcObject, serviceClientByObjPath);
207
+ }
208
+ let client = serviceClientByObjPath.get(objPath);
209
+ if (!client) {
210
+ const ServiceClient = lodashGet(grpcObject, objPath);
211
+ if (typeof ServiceClient !== 'function') {
212
+ throw new Error(`Object at path ${objPath} is not a Service constructor`);
213
+ }
214
+ client = new ServiceClient((_a = stringInterpolator.parse(this.config.endpoint, { env: process.env })) !== null && _a !== void 0 ? _a : this.config.endpoint, creds);
215
+ const subId = this.pubsub.subscribe('destroy', () => {
216
+ client.close();
217
+ this.pubsub.unsubscribe(subId);
218
+ });
219
+ serviceClientByObjPath.set(objPath, client);
220
+ }
221
+ return client;
222
+ }
223
+ getFieldResolver({ client, methodName, isResponseStream, }) {
224
+ const metaData = this.config.metaData;
225
+ const clientMethod = client[methodName].bind(client);
226
+ return function grpcFieldResolver(root, args, context) {
227
+ return addMetaDataToCall(clientMethod, args.input, {
228
+ root,
229
+ args,
230
+ context,
231
+ env: process.env,
232
+ }, metaData, isResponseStream);
233
+ };
234
+ }
235
+ getConnectivityStateResolver({ client, }) {
236
+ return function connectivityStateResolver(_, { tryToConnect }) {
237
+ return client.getChannel().getConnectivityState(tryToConnect);
238
+ };
239
+ }
240
+ processDirectives({ schema, creds }) {
241
+ const queryType = schema.getQueryType();
242
+ const rootJsonAnnotations = getDirective(schema, queryType, 'grpcRootJson');
243
+ const rootJsonMap = new Map();
244
+ const grpcObjectByRootJsonName = new Map();
245
+ for (const { name, rootJson, loadOptions } of rootJsonAnnotations) {
246
+ rootJsonMap.set(name, rootJson);
247
+ const rootLogger = this.logger.child(name);
248
+ grpcObjectByRootJsonName.set(name, this.getGrpcObject({ rootJson, loadOptions, rootLogger }));
249
+ }
250
+ const rootTypes = getRootTypes(schema);
251
+ for (const rootType of rootTypes) {
252
+ for (const fieldName in rootType.getFields()) {
253
+ const field = rootType.getFields()[fieldName];
254
+ const directives = getDirectives(schema, field);
255
+ if (directives === null || directives === void 0 ? void 0 : directives.length) {
256
+ for (const directiveObj of directives) {
257
+ switch (directiveObj.name) {
258
+ case 'grpcMethod': {
259
+ const { rootJsonName, objPath, methodName, responseStream } = directiveObj.args;
260
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
261
+ const client = this.getServiceClient({
262
+ grpcObject,
263
+ objPath,
264
+ creds,
265
+ });
266
+ field.resolve = this.getFieldResolver({
267
+ client,
268
+ methodName,
269
+ isResponseStream: responseStream,
270
+ });
271
+ break;
272
+ }
273
+ case 'grpcConnectivityState': {
274
+ const { rootJsonName, objPath } = directiveObj.args;
275
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
276
+ const client = this.getServiceClient({
277
+ grpcObject,
278
+ objPath,
279
+ creds,
280
+ });
281
+ field.resolve = this.getConnectivityStateResolver({ client });
282
+ break;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ visit({ nested, name, currentPath, rootJsonName, rootJson, rootLogger: logger, loadOptions, }) {
221
291
  const pathWithName = [...currentPath, ...name.split('.')].filter(Boolean);
222
292
  if ('nested' in nested) {
223
293
  for (const key in nested.nested) {
@@ -227,9 +297,8 @@ ${rootJsonEntries
227
297
  nested: currentNested,
228
298
  name: key,
229
299
  currentPath: pathWithName,
300
+ rootJsonName,
230
301
  rootJson,
231
- creds,
232
- grpcObject,
233
302
  rootLogger: logger,
234
303
  });
235
304
  }
@@ -319,15 +388,6 @@ ${rootJsonEntries
319
388
  }
320
389
  else if ('methods' in nested) {
321
390
  const objPath = pathWithName.join('.');
322
- const ServiceClient = lodashGet(grpcObject, objPath);
323
- if (typeof ServiceClient !== 'function') {
324
- throw new Error(`Object at path ${objPath} is not a Service constructor`);
325
- }
326
- const client = new ServiceClient((_a = stringInterpolator.parse(this.config.endpoint, { env: process.env })) !== null && _a !== void 0 ? _a : this.config.endpoint, creds);
327
- const subId = this.pubsub.subscribe('destroy', () => {
328
- client.close();
329
- this.pubsub.unsubscribe(subId);
330
- });
331
391
  for (const methodName in nested.methods) {
332
392
  const method = nested.methods[methodName];
333
393
  const rootFieldName = [...pathWithName, methodName].join('_');
@@ -367,19 +427,26 @@ ${rootJsonEntries
367
427
  const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
368
428
  ? this.schemaComposer.Query
369
429
  : this.schemaComposer.Mutation;
430
+ this.schemaComposer.addDirective(grpcMethodDirective);
370
431
  rootTypeComposer.addFields({
371
432
  [rootFieldName]: {
372
433
  ...fieldConfig,
373
- resolve: (root, args, context, info) => addMetaDataToCall(client[methodName].bind(client), args.input, {
374
- root,
375
- args,
376
- context,
377
- env: process.env,
378
- }, this.config.metaData, !!method.responseStream),
434
+ directives: [
435
+ {
436
+ name: 'grpcMethod',
437
+ args: {
438
+ rootJsonName,
439
+ objPath,
440
+ methodName,
441
+ responseStream: !!method.responseStream,
442
+ },
443
+ },
444
+ ],
379
445
  },
380
446
  });
381
447
  }
382
448
  const connectivityStateFieldName = pathWithName.join('_') + '_connectivityState';
449
+ this.schemaComposer.addDirective(grpcConnectivityStateDirective);
383
450
  this.schemaComposer.Query.addFields({
384
451
  [connectivityStateFieldName]: {
385
452
  type: 'ConnectivityState',
@@ -388,61 +455,96 @@ ${rootJsonEntries
388
455
  type: 'Boolean',
389
456
  },
390
457
  },
391
- resolve: (_, { tryToConnect }) => client.getChannel().getConnectivityState(tryToConnect),
458
+ directives: [
459
+ {
460
+ name: 'grpcConnectivityState',
461
+ args: {
462
+ rootJsonName,
463
+ objPath,
464
+ },
465
+ },
466
+ ],
392
467
  },
393
468
  });
394
469
  }
395
470
  }
396
- async getMeshSource() {
397
- this.config.requestTimeout = this.config.requestTimeout || 200000;
398
- this.schemaComposer.add(GraphQLBigInt);
399
- this.schemaComposer.add(GraphQLByte);
400
- this.schemaComposer.add(GraphQLUnsignedInt);
401
- this.schemaComposer.add(GraphQLVoid);
402
- this.schemaComposer.add(GraphQLJSON);
403
- this.schemaComposer.createScalarTC({
404
- name: 'File',
405
- });
406
- // identical of grpc's ConnectivityState
407
- this.schemaComposer.createEnumTC({
408
- name: 'ConnectivityState',
409
- values: {
410
- IDLE: { value: 0 },
411
- CONNECTING: { value: 1 },
412
- READY: { value: 2 },
413
- TRANSIENT_FAILURE: { value: 3 },
414
- SHUTDOWN: { value: 4 },
415
- },
471
+ async getCachedNonExecutableSchema(creds) {
472
+ var _a;
473
+ const interpolatedSource = (_a = this.config.source) === null || _a === void 0 ? void 0 : _a.toString();
474
+ if (interpolatedSource === null || interpolatedSource === void 0 ? void 0 : interpolatedSource.endsWith('.graphql')) {
475
+ this.logger.info(`Fetching GraphQL Schema with annotations`);
476
+ const sdl = await readFileOrUrl(interpolatedSource, {
477
+ allowUnknownExtensions: true,
478
+ cwd: this.baseDir,
479
+ fetch: this.fetchFn,
480
+ importFn: this.importFn,
481
+ logger: this.logger,
482
+ headers: this.config.schemaHeaders,
483
+ });
484
+ return buildSchema(sdl, {
485
+ assumeValidSDL: true,
486
+ assumeValid: true,
487
+ });
488
+ }
489
+ return this.schemaWithAnnotationsProxy.getWithSet(async () => {
490
+ this.schemaComposer.add(GraphQLBigInt);
491
+ this.schemaComposer.add(GraphQLByte);
492
+ this.schemaComposer.add(GraphQLUnsignedInt);
493
+ this.schemaComposer.add(GraphQLVoid);
494
+ this.schemaComposer.add(GraphQLJSON);
495
+ this.schemaComposer.createScalarTC({
496
+ name: 'File',
497
+ });
498
+ // identical of grpc's ConnectivityState
499
+ this.schemaComposer.createEnumTC({
500
+ name: 'ConnectivityState',
501
+ values: {
502
+ IDLE: { value: 0 },
503
+ CONNECTING: { value: 1 },
504
+ READY: { value: 2 },
505
+ TRANSIENT_FAILURE: { value: 3 },
506
+ SHUTDOWN: { value: 4 },
507
+ },
508
+ });
509
+ this.logger.debug(`Getting stored root and decoded descriptor set objects`);
510
+ const descriptorSets = await this.getDescriptorSets(creds);
511
+ for (const { name: rootJsonName, rootJson } of descriptorSets) {
512
+ const rootLogger = this.logger.child(rootJsonName);
513
+ rootLogger.debug(`Creating package definition from file descriptor set object`);
514
+ let loadOptions;
515
+ if (typeof this.config.source === 'object') {
516
+ loadOptions = this.config.source.load;
517
+ }
518
+ this.logger.debug(`Building the schema structure based on the root object`);
519
+ this.visit({
520
+ nested: rootJson,
521
+ name: '',
522
+ currentPath: [],
523
+ rootJsonName,
524
+ rootJson,
525
+ rootLogger,
526
+ loadOptions,
527
+ });
528
+ this.schemaComposer.addDirective(grpcRootJsonDirective);
529
+ this.schemaComposer.Query.setDirectiveByName('grpcRootJson', {
530
+ name: rootJsonName,
531
+ rootJson,
532
+ });
533
+ }
534
+ // graphql-compose doesn't add @defer and @stream to the schema
535
+ specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
536
+ this.logger.debug(`Building the final GraphQL Schema`);
537
+ const schema = this.schemaComposer.buildSchema();
538
+ return schema;
416
539
  });
540
+ }
541
+ async getMeshSource({ fetchFn }) {
542
+ this.fetchFn = fetchFn;
543
+ this.config.requestTimeout = this.config.requestTimeout || 200000;
417
544
  this.logger.debug(`Getting channel credentials`);
418
545
  const creds = await this.getCredentials();
419
- this.logger.debug(`Getting stored root and decoded descriptor set objects`);
420
- const artifacts = await this.getCachedDescriptorSets(creds);
421
- for (const { name, rootJson } of artifacts) {
422
- const rootLogger = this.logger.child(name);
423
- rootLogger.debug(`Creating package definition from file descriptor set object`);
424
- let options;
425
- if (typeof this.config.source === 'object') {
426
- options = this.config.source.load;
427
- }
428
- const packageDefinition = fromJSON(rootJson, options);
429
- rootLogger.debug(`Creating service client for package definition`);
430
- const grpcObject = loadPackageDefinition(packageDefinition);
431
- this.logger.debug(`Building the schema structure based on the root object`);
432
- this.visit({
433
- nested: rootJson,
434
- name: '',
435
- currentPath: [],
436
- rootJson,
437
- creds,
438
- grpcObject,
439
- rootLogger,
440
- });
441
- }
442
- // graphql-compose doesn't add @defer and @stream to the schema
443
- specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
444
- this.logger.debug(`Building the final GraphQL Schema`);
445
- const schema = this.schemaComposer.buildSchema();
546
+ const schema = await this.getCachedNonExecutableSchema(creds);
547
+ this.processDirectives({ schema, creds });
446
548
  return {
447
549
  schema,
448
550
  };
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@graphql-mesh/grpc",
3
- "version": "1.0.0-alpha-20230424111644-b7c761da0",
3
+ "version": "1.0.0-alpha-20230522105300-fe9c79867",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@graphql-mesh/cross-helpers": "^0.3.4",
7
- "@graphql-mesh/store": "1.0.0-alpha-20230424111644-b7c761da0",
8
- "@graphql-mesh/types": "1.0.0-alpha-20230424111644-b7c761da0",
9
- "@graphql-mesh/utils": "1.0.0-alpha-20230424111644-b7c761da0",
6
+ "@graphql-mesh/cross-helpers": "0.4.0-alpha-20230522105300-fe9c79867",
7
+ "@graphql-mesh/store": "1.0.0-alpha-20230522105300-fe9c79867",
8
+ "@graphql-mesh/types": "1.0.0-alpha-20230522105300-fe9c79867",
9
+ "@graphql-mesh/utils": "1.0.0-alpha-20230522105300-fe9c79867",
10
+ "@graphql-tools/utils": "^9.2.1",
10
11
  "graphql": "*",
11
12
  "tslib": "^2.4.0"
12
13
  },
13
14
  "dependencies": {
14
15
  "@ardatan/grpc-reflection-js": "0.0.2",
15
- "@graphql-mesh/string-interpolation": "0.4.4",
16
+ "@graphql-mesh/string-interpolation": "0.5.0-alpha-20230522105300-fe9c79867",
16
17
  "@grpc/grpc-js": "^1.1.7",
17
- "@grpc/proto-loader": "0.7.6",
18
+ "@grpc/proto-loader": "0.7.7",
18
19
  "globby": "11.1.0",
19
20
  "graphql-compose": "9.0.10",
20
21
  "graphql-scalars": "^1.20.4",
@@ -0,0 +1,5 @@
1
+ import { GraphQLDirective, GraphQLScalarType } from 'graphql';
2
+ export declare const grpcMethodDirective: GraphQLDirective;
3
+ export declare const grpcConnectivityStateDirective: GraphQLDirective;
4
+ export declare const ObjMapScalar: GraphQLScalarType<any, string>;
5
+ export declare const grpcRootJsonDirective: GraphQLDirective;
@@ -0,0 +1,5 @@
1
+ import { GraphQLDirective, GraphQLScalarType } from 'graphql';
2
+ export declare const grpcMethodDirective: GraphQLDirective;
3
+ export declare const grpcConnectivityStateDirective: GraphQLDirective;
4
+ export declare const ObjMapScalar: GraphQLScalarType<any, string>;
5
+ export declare const grpcRootJsonDirective: GraphQLDirective;
@@ -1,37 +1,68 @@
1
- import { AnyNestedObject } from 'protobufjs';
1
+ import { GraphQLFieldResolver, GraphQLSchema } from 'graphql';
2
+ import { AnyNestedObject, IParseOptions } from 'protobufjs';
2
3
  import protobufjs from 'protobufjs';
3
4
  import { Logger, MeshHandler, MeshHandlerOptions, YamlConfig } from '@graphql-mesh/types';
5
+ import { GetMeshSourcePayload } from '@graphql-mesh/types';
4
6
  import { ChannelCredentials, loadPackageDefinition } from '@grpc/grpc-js';
7
+ import { ServiceClient } from '@grpc/grpc-js/build/src/make-client.cjs';
5
8
  import './patchLongJs.cjs';
6
- type RootJsonEntry = {
7
- name: string;
8
- rootJson: protobufjs.INamespace;
9
- };
9
+ interface LoadOptions extends IParseOptions {
10
+ includeDirs?: string[];
11
+ }
10
12
  export default class GrpcHandler implements MeshHandler {
11
13
  private config;
12
14
  private baseDir;
13
- private rootJsonEntries;
15
+ private schemaWithAnnotationsProxy;
14
16
  private logger;
15
17
  private pubsub;
16
- constructor({ config, baseDir, store, logger, pubsub, }: MeshHandlerOptions<YamlConfig.GrpcHandler>);
18
+ private fetchFn;
19
+ private importFn;
20
+ constructor({ config, baseDir, store, logger, pubsub, importFn, }: MeshHandlerOptions<YamlConfig.GrpcHandler>);
17
21
  processReflection(creds: ChannelCredentials): Promise<Promise<protobufjs.Root>[]>;
18
22
  processDescriptorFile(): Promise<protobufjs.Root>;
19
23
  processProtoFile(): Promise<protobufjs.Root>;
20
- getCachedDescriptorSets(creds: ChannelCredentials): Promise<RootJsonEntry[]>;
24
+ getDescriptorSets(creds: ChannelCredentials): Promise<{
25
+ name: string;
26
+ rootJson: protobufjs.INamespace;
27
+ }[]>;
21
28
  getCredentials(): Promise<ChannelCredentials>;
22
29
  walkToFindTypePath(rootJson: protobufjs.INamespace, pathWithName: string[], baseTypePath: string[]): string[];
23
- visit({ nested, name, currentPath, rootJson, creds, grpcObject, rootLogger: logger, }: {
30
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }: {
31
+ rootJson: protobufjs.INamespace;
32
+ loadOptions: LoadOptions;
33
+ rootLogger: Logger;
34
+ }): import("@grpc/grpc-js").GrpcObject;
35
+ private grpcObjectByserviceClientByObjPath;
36
+ getServiceClient({ grpcObject, objPath, creds, }: {
37
+ grpcObject: ReturnType<typeof loadPackageDefinition>;
38
+ objPath: string;
39
+ creds: ChannelCredentials;
40
+ }): ServiceClient;
41
+ getFieldResolver({ client, methodName, isResponseStream, }: {
42
+ client: ServiceClient;
43
+ methodName: string;
44
+ isResponseStream: boolean;
45
+ }): GraphQLFieldResolver<any, any>;
46
+ getConnectivityStateResolver({ client, }: {
47
+ client: ServiceClient;
48
+ }): GraphQLFieldResolver<any, any>;
49
+ processDirectives({ schema, creds }: {
50
+ schema: GraphQLSchema;
51
+ creds: ChannelCredentials;
52
+ }): void;
53
+ visit({ nested, name, currentPath, rootJsonName, rootJson, rootLogger: logger, loadOptions, }: {
24
54
  nested: AnyNestedObject;
25
55
  name: string;
26
56
  currentPath: string[];
57
+ rootJsonName: string;
27
58
  rootJson: protobufjs.INamespace;
28
- creds: ChannelCredentials;
29
- grpcObject: ReturnType<typeof loadPackageDefinition>;
30
59
  rootLogger: Logger;
60
+ loadOptions?: LoadOptions;
31
61
  }): void;
32
62
  private schemaComposer;
33
- getMeshSource(): Promise<{
34
- schema: import("graphql").GraphQLSchema;
63
+ private getCachedNonExecutableSchema;
64
+ getMeshSource({ fetchFn }: GetMeshSourcePayload): Promise<{
65
+ schema: GraphQLSchema;
35
66
  }>;
36
67
  }
37
68
  export {};
@@ -1,37 +1,68 @@
1
- import { AnyNestedObject } from 'protobufjs';
1
+ import { GraphQLFieldResolver, GraphQLSchema } from 'graphql';
2
+ import { AnyNestedObject, IParseOptions } from 'protobufjs';
2
3
  import protobufjs from 'protobufjs';
3
4
  import { Logger, MeshHandler, MeshHandlerOptions, YamlConfig } from '@graphql-mesh/types';
5
+ import { GetMeshSourcePayload } from '@graphql-mesh/types';
4
6
  import { ChannelCredentials, loadPackageDefinition } from '@grpc/grpc-js';
7
+ import { ServiceClient } from '@grpc/grpc-js/build/src/make-client.js';
5
8
  import './patchLongJs.js';
6
- type RootJsonEntry = {
7
- name: string;
8
- rootJson: protobufjs.INamespace;
9
- };
9
+ interface LoadOptions extends IParseOptions {
10
+ includeDirs?: string[];
11
+ }
10
12
  export default class GrpcHandler implements MeshHandler {
11
13
  private config;
12
14
  private baseDir;
13
- private rootJsonEntries;
15
+ private schemaWithAnnotationsProxy;
14
16
  private logger;
15
17
  private pubsub;
16
- constructor({ config, baseDir, store, logger, pubsub, }: MeshHandlerOptions<YamlConfig.GrpcHandler>);
18
+ private fetchFn;
19
+ private importFn;
20
+ constructor({ config, baseDir, store, logger, pubsub, importFn, }: MeshHandlerOptions<YamlConfig.GrpcHandler>);
17
21
  processReflection(creds: ChannelCredentials): Promise<Promise<protobufjs.Root>[]>;
18
22
  processDescriptorFile(): Promise<protobufjs.Root>;
19
23
  processProtoFile(): Promise<protobufjs.Root>;
20
- getCachedDescriptorSets(creds: ChannelCredentials): Promise<RootJsonEntry[]>;
24
+ getDescriptorSets(creds: ChannelCredentials): Promise<{
25
+ name: string;
26
+ rootJson: protobufjs.INamespace;
27
+ }[]>;
21
28
  getCredentials(): Promise<ChannelCredentials>;
22
29
  walkToFindTypePath(rootJson: protobufjs.INamespace, pathWithName: string[], baseTypePath: string[]): string[];
23
- visit({ nested, name, currentPath, rootJson, creds, grpcObject, rootLogger: logger, }: {
30
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }: {
31
+ rootJson: protobufjs.INamespace;
32
+ loadOptions: LoadOptions;
33
+ rootLogger: Logger;
34
+ }): import("@grpc/grpc-js").GrpcObject;
35
+ private grpcObjectByserviceClientByObjPath;
36
+ getServiceClient({ grpcObject, objPath, creds, }: {
37
+ grpcObject: ReturnType<typeof loadPackageDefinition>;
38
+ objPath: string;
39
+ creds: ChannelCredentials;
40
+ }): ServiceClient;
41
+ getFieldResolver({ client, methodName, isResponseStream, }: {
42
+ client: ServiceClient;
43
+ methodName: string;
44
+ isResponseStream: boolean;
45
+ }): GraphQLFieldResolver<any, any>;
46
+ getConnectivityStateResolver({ client, }: {
47
+ client: ServiceClient;
48
+ }): GraphQLFieldResolver<any, any>;
49
+ processDirectives({ schema, creds }: {
50
+ schema: GraphQLSchema;
51
+ creds: ChannelCredentials;
52
+ }): void;
53
+ visit({ nested, name, currentPath, rootJsonName, rootJson, rootLogger: logger, loadOptions, }: {
24
54
  nested: AnyNestedObject;
25
55
  name: string;
26
56
  currentPath: string[];
57
+ rootJsonName: string;
27
58
  rootJson: protobufjs.INamespace;
28
- creds: ChannelCredentials;
29
- grpcObject: ReturnType<typeof loadPackageDefinition>;
30
59
  rootLogger: Logger;
60
+ loadOptions?: LoadOptions;
31
61
  }): void;
32
62
  private schemaComposer;
33
- getMeshSource(): Promise<{
34
- schema: import("graphql").GraphQLSchema;
63
+ private getCachedNonExecutableSchema;
64
+ getMeshSource({ fetchFn }: GetMeshSourcePayload): Promise<{
65
+ schema: GraphQLSchema;
35
66
  }>;
36
67
  }
37
68
  export {};