@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.
@@ -1,160 +1,35 @@
1
- import Long from 'long';
2
- import { stringInterpolator } from '@graphql-mesh/string-interpolation';
3
- import { Metadata, credentials, loadPackageDefinition } from '@grpc/grpc-js';
4
- import { loadFileDescriptorSetFromObject } from '@grpc/proto-loader';
1
+ /* eslint-disable import/no-duplicates */
2
+ import globby from 'globby';
3
+ import { specifiedDirectives } from 'graphql';
5
4
  import { SchemaComposer } from 'graphql-compose';
6
- import { GraphQLJSON, GraphQLBigInt, GraphQLByte, GraphQLUnsignedInt, GraphQLVoid } from 'graphql-scalars';
5
+ import { GraphQLBigInt, GraphQLByte, GraphQLJSON, GraphQLUnsignedInt, GraphQLVoid, } from 'graphql-scalars';
7
6
  import lodashGet from 'lodash.get';
8
7
  import lodashHas from 'lodash.has';
9
8
  import protobufjs from 'protobufjs';
10
- import grpcReflection from '@ardatan/grpc-reflection-js';
11
- import descriptor, { FileDescriptorSet } from 'protobufjs/ext/descriptor/index.js';
12
- import { withCancel } from '@graphql-mesh/utils';
13
- import { path, fs, process } from '@graphql-mesh/cross-helpers';
14
- import { specifiedDirectives } from 'graphql';
15
- import globby from 'globby';
16
-
17
- function patchLongJs() {
18
- const originalLongFromValue = Long.fromValue.bind(Long);
19
- Long.fromValue = (value) => {
20
- if (typeof value === 'bigint') {
21
- return Long.fromValue(value.toString());
22
- }
23
- return originalLongFromValue(value);
24
- };
25
- }
26
- patchLongJs();
27
-
28
- const SCALARS = new Map([
29
- ['bool', 'Boolean'],
30
- ['bytes', 'Byte'],
31
- ['double', 'Float'],
32
- ['fixed32', 'Int'],
33
- ['fixed64', 'BigInt'],
34
- ['float', 'Float'],
35
- ['int32', 'Int'],
36
- ['int64', 'BigInt'],
37
- ['sfixed32', 'Int'],
38
- ['sfixed64', 'BigInt'],
39
- ['sint32', 'Int'],
40
- ['sint64', 'BigInt'],
41
- ['string', 'String'],
42
- ['uint32', 'UnsignedInt'],
43
- ['uint64', 'BigInt'], // A new scalar might be needed
44
- ]);
45
- function isScalarType(type) {
46
- return SCALARS.has(type);
47
- }
48
- function getGraphQLScalar(scalarType) {
49
- const gqlScalar = SCALARS.get(scalarType);
50
- if (!gqlScalar) {
51
- throw new Error(`Could not find GraphQL Scalar for type ${scalarType}`);
52
- }
53
- return SCALARS.get(scalarType);
54
- }
55
-
56
- function getTypeName(schemaComposer, pathWithName, isInput) {
57
- if (pathWithName === null || pathWithName === void 0 ? void 0 : pathWithName.length) {
58
- const baseTypeName = pathWithName.filter(Boolean).join('_');
59
- if (isScalarType(baseTypeName)) {
60
- return getGraphQLScalar(baseTypeName);
61
- }
62
- if (schemaComposer.isEnumType(baseTypeName)) {
63
- return baseTypeName;
64
- }
65
- return isInput ? baseTypeName + '_Input' : baseTypeName;
66
- }
67
- return 'Void';
68
- }
69
- function addIncludePathResolver(root, includePaths) {
70
- const originalResolvePath = root.resolvePath;
71
- root.resolvePath = (origin, target) => {
72
- if (path.isAbsolute(target)) {
73
- return target;
74
- }
75
- for (const directory of includePaths) {
76
- const fullPath = path.join(directory, target);
77
- if (fs.existsSync(fullPath)) {
78
- return fullPath;
79
- }
80
- }
81
- const path$1 = originalResolvePath(origin, target);
82
- if (path$1 === null) {
83
- console.warn(`${target} not found in any of the include paths ${includePaths}`);
84
- }
85
- return path$1;
86
- };
87
- }
88
- function isBlob(input) {
89
- return input != null && input.stream instanceof Function;
90
- }
91
- function addMetaDataToCall(callFn, input, context, metaData, isResponseStream = false) {
92
- const callFnArguments = [];
93
- if (!isBlob(input)) {
94
- callFnArguments.push(input);
95
- }
96
- if (metaData) {
97
- const meta = new Metadata();
98
- for (const [key, value] of Object.entries(metaData)) {
99
- let metaValue = value;
100
- if (Array.isArray(value)) {
101
- // Extract data from context
102
- metaValue = lodashGet(context, value);
103
- }
104
- // Ensure that the metadata is compatible with what node-grpc expects
105
- if (typeof metaValue !== 'string' && !(metaValue instanceof Buffer)) {
106
- metaValue = JSON.stringify(metaValue);
107
- }
108
- if (typeof metaValue === 'string') {
109
- metaValue = stringInterpolator.parse(metaValue, context);
110
- }
111
- meta.add(key, metaValue);
112
- }
113
- callFnArguments.push(meta);
114
- }
115
- return new Promise((resolve, reject) => {
116
- const call = callFn(...callFnArguments, (error, response) => {
117
- if (error) {
118
- reject(error);
119
- }
120
- resolve(response);
121
- });
122
- if (isResponseStream) {
123
- let isCancelled = false;
124
- const responseStreamWithCancel = withCancel(call, () => {
125
- var _a;
126
- if (!isCancelled) {
127
- (_a = call.call) === null || _a === void 0 ? void 0 : _a.cancelWithStatus(0, 'Cancelled by GraphQL Mesh');
128
- isCancelled = true;
129
- }
130
- });
131
- resolve(responseStreamWithCancel);
132
- if (isBlob(input)) {
133
- input.stream().pipe(call);
134
- }
135
- }
136
- });
137
- }
138
-
139
- /* eslint-disable import/no-duplicates */
9
+ import descriptor from 'protobufjs/ext/descriptor/index.js';
10
+ import { Client } from '@ardatan/grpc-reflection-js';
11
+ import { path, process } from '@graphql-mesh/cross-helpers';
12
+ import { fs } from '@graphql-mesh/cross-helpers';
13
+ import { stringInterpolator } from '@graphql-mesh/string-interpolation';
14
+ import { credentials, loadPackageDefinition } from '@grpc/grpc-js';
15
+ import { fromJSON } from '@grpc/proto-loader';
16
+ import './patchLongJs.js';
17
+ import { addIncludePathResolver, addMetaDataToCall, getTypeName } from './utils.js';
140
18
  const { Root } = protobufjs;
141
- const QUERY_METHOD_PREFIXES = ['get', 'list'];
142
- class GrpcHandler {
143
- constructor({ config, baseDir, store, logger }) {
19
+ const QUERY_METHOD_PREFIXES = ['get', 'list', 'search'];
20
+ export default class GrpcHandler {
21
+ constructor({ config, baseDir, store, logger, pubsub, }) {
144
22
  this.schemaComposer = new SchemaComposer();
145
23
  this.logger = logger;
146
24
  this.config = config;
147
25
  this.baseDir = baseDir;
148
- this.rootJsonAndDecodedDescriptorSets = store.proxy('descriptorSet.proto', {
149
- codify: rootJsonAndDecodedDescriptorSets => `
150
- import { FileDescriptorSet } from 'protobufjs/ext/descriptor/index.js';
151
-
26
+ this.rootJsonEntries = store.proxy('rootJsonEntries', {
27
+ codify: rootJsonEntries => `
152
28
  export default [
153
- ${rootJsonAndDecodedDescriptorSets
154
- .map(({ name, rootJson, decodedDescriptorSet }) => `
29
+ ${rootJsonEntries
30
+ .map(({ name, rootJson }) => `
155
31
  {
156
32
  name: ${JSON.stringify(name)},
157
- decodedDescriptorSet: FileDescriptorSet.fromObject(${JSON.stringify(decodedDescriptorSet.toJSON(), null, 2)}),
158
33
  rootJson: ${JSON.stringify(rootJson, null, 2)},
159
34
  },
160
35
  `)
@@ -162,29 +37,32 @@ ${rootJsonAndDecodedDescriptorSets
162
37
  ];
163
38
  `.trim(),
164
39
  fromJSON: jsonData => {
165
- return jsonData.map(({ name, rootJson, decodedDescriptorSet }) => ({
40
+ return jsonData.map(({ name, rootJson }) => ({
166
41
  name,
167
42
  rootJson,
168
- decodedDescriptorSet: FileDescriptorSet.fromObject(decodedDescriptorSet),
169
43
  }));
170
44
  },
171
- toJSON: rootJsonAndDecodedDescriptorSets => {
172
- return rootJsonAndDecodedDescriptorSets.map(({ name, rootJson, decodedDescriptorSet }) => {
45
+ toJSON: rootJsonEntries => {
46
+ return rootJsonEntries.map(({ name, rootJson }) => {
173
47
  return {
174
48
  name,
175
49
  rootJson,
176
- decodedDescriptorSet: decodedDescriptorSet.toJSON(),
177
50
  };
178
51
  });
179
52
  },
180
53
  validate: () => { },
181
54
  });
55
+ this.pubsub = pubsub;
182
56
  }
183
- async getRootPromisesFromReflection(creds) {
57
+ async processReflection(creds) {
184
58
  this.logger.debug(`Using the reflection`);
185
59
  const grpcReflectionServer = this.config.endpoint;
186
60
  this.logger.debug(`Creating gRPC Reflection Client`);
187
- const reflectionClient = new grpcReflection.Client(grpcReflectionServer, creds);
61
+ const reflectionClient = new Client(grpcReflectionServer, creds);
62
+ const subId = this.pubsub.subscribe('destroy', () => {
63
+ reflectionClient.grpcClient.close();
64
+ this.pubsub.unsubscribe(subId);
65
+ });
188
66
  const services = await reflectionClient.listServices();
189
67
  const userServices = services.filter(service => service && !(service === null || service === void 0 ? void 0 : service.startsWith('grpc.')));
190
68
  return userServices.map(async (service) => {
@@ -193,21 +71,23 @@ ${rootJsonAndDecodedDescriptorSets
193
71
  return serviceRoot;
194
72
  });
195
73
  }
196
- async getRootPromiseFromDescriptorFilePath() {
74
+ async processDescriptorFile() {
197
75
  var _a;
198
76
  let fileName;
199
77
  let options;
200
- if (typeof this.config.descriptorSetFilePath === 'object') {
201
- fileName = this.config.descriptorSetFilePath.file;
78
+ if (typeof this.config.source === 'object') {
79
+ fileName = this.config.source.file;
202
80
  options = {
203
- ...this.config.descriptorSetFilePath.load,
204
- includeDirs: (_a = this.config.descriptorSetFilePath.load.includeDirs) === null || _a === void 0 ? void 0 : _a.map(includeDir => path.isAbsolute(includeDir) ? includeDir : path.join(this.baseDir, includeDir)),
81
+ ...this.config.source.load,
82
+ includeDirs: (_a = this.config.source.load.includeDirs) === null || _a === void 0 ? void 0 : _a.map(includeDir => path.isAbsolute(includeDir) ? includeDir : path.join(this.baseDir, includeDir)),
205
83
  };
206
84
  }
207
85
  else {
208
- fileName = this.config.descriptorSetFilePath;
86
+ fileName = this.config.source;
209
87
  }
210
- const absoluteFilePath = path.isAbsolute(fileName) ? fileName : path.join(this.baseDir, fileName);
88
+ const absoluteFilePath = path.isAbsolute(fileName)
89
+ ? fileName
90
+ : path.join(this.baseDir, fileName);
211
91
  this.logger.debug(`Using the descriptor set from ${absoluteFilePath} `);
212
92
  const descriptorSetBuffer = await fs.promises.readFile(absoluteFilePath);
213
93
  this.logger.debug(`Reading ${absoluteFilePath} `);
@@ -230,7 +110,7 @@ ${rootJsonAndDecodedDescriptorSets
230
110
  }
231
111
  return rootFromDescriptor;
232
112
  }
233
- async getRootPromiseFromProtoFilePath() {
113
+ async processProtoFile() {
234
114
  var _a, _b;
235
115
  this.logger.debug(`Using proto file(s)`);
236
116
  let protoRoot = new Root();
@@ -239,46 +119,47 @@ ${rootJsonAndDecodedDescriptorSets
239
119
  keepCase: true,
240
120
  alternateCommentMode: true,
241
121
  };
242
- if (typeof this.config.protoFilePath === 'object') {
243
- fileGlob = this.config.protoFilePath.file;
122
+ if (typeof this.config.source === 'object') {
123
+ fileGlob = this.config.source.file;
244
124
  options = {
245
125
  ...options,
246
- ...this.config.protoFilePath.load,
247
- includeDirs: (_b = (_a = this.config.protoFilePath.load) === null || _a === void 0 ? void 0 : _a.includeDirs) === null || _b === void 0 ? void 0 : _b.map(includeDir => path.isAbsolute(includeDir) ? includeDir : path.join(this.baseDir, includeDir)),
126
+ ...this.config.source.load,
127
+ includeDirs: (_b = (_a = this.config.source.load) === null || _a === void 0 ? void 0 : _a.includeDirs) === null || _b === void 0 ? void 0 : _b.map(includeDir => path.isAbsolute(includeDir) ? includeDir : path.join(this.baseDir, includeDir)),
248
128
  };
249
129
  if (options.includeDirs) {
250
130
  if (!Array.isArray(options.includeDirs)) {
251
- return Promise.reject(new Error('The includeDirs option must be an array'));
131
+ throw new Error('The includeDirs option must be an array');
252
132
  }
253
133
  addIncludePathResolver(protoRoot, options.includeDirs);
254
134
  }
255
135
  }
256
136
  else {
257
- fileGlob = this.config.protoFilePath;
137
+ fileGlob = this.config.source;
258
138
  }
259
139
  const fileNames = await globby(fileGlob, {
260
140
  cwd: this.baseDir,
261
141
  });
262
142
  this.logger.debug(`Loading proto files(${fileGlob}); \n ${fileNames.join('\n')} `);
263
- protoRoot = await protoRoot.load(fileNames.map(filePath => (path.isAbsolute(filePath) ? filePath : path.join(this.baseDir, filePath))), options);
143
+ protoRoot = await protoRoot.load(fileNames.map(filePath => path.isAbsolute(filePath) ? filePath : path.join(this.baseDir, filePath)), options);
264
144
  this.logger.debug(`Adding proto content to the root`);
265
145
  return protoRoot;
266
146
  }
267
147
  getCachedDescriptorSets(creds) {
268
- return this.rootJsonAndDecodedDescriptorSets.getWithSet(async () => {
148
+ return this.rootJsonEntries.getWithSet(async () => {
269
149
  const rootPromises = [];
270
150
  this.logger.debug(`Building Roots`);
271
- if (this.config.useReflection) {
272
- const reflectionPromises = await this.getRootPromisesFromReflection(creds);
273
- rootPromises.push(...reflectionPromises);
274
- }
275
- if (this.config.descriptorSetFilePath) {
276
- const rootPromise = this.getRootPromiseFromDescriptorFilePath();
277
- rootPromises.push(rootPromise);
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
+ }
278
159
  }
279
- if (this.config.protoFilePath) {
280
- const rootPromise = this.getRootPromiseFromProtoFilePath();
281
- rootPromises.push(rootPromise);
160
+ else {
161
+ const reflectionPromises = await this.processReflection(creds);
162
+ rootPromises.push(...reflectionPromises);
282
163
  }
283
164
  return Promise.all(rootPromises.map(async (root$, i) => {
284
165
  const root = await root$;
@@ -292,7 +173,6 @@ ${rootJsonAndDecodedDescriptorSets
292
173
  rootJson: root.toJSON({
293
174
  keepComments: true,
294
175
  }),
295
- decodedDescriptorSet: root.toDescriptor('proto3'),
296
176
  };
297
177
  }));
298
178
  });
@@ -306,7 +186,10 @@ ${rootJsonAndDecodedDescriptorSets
306
186
  const absoluteCertChainPath = path.isAbsolute(this.config.credentialsSsl.certChain)
307
187
  ? this.config.credentialsSsl.certChain
308
188
  : path.join(this.baseDir, this.config.credentialsSsl.certChain);
309
- const sslFiles = [fs.promises.readFile(absolutePrivateKeyPath), fs.promises.readFile(absoluteCertChainPath)];
189
+ const sslFiles = [
190
+ fs.promises.readFile(absolutePrivateKeyPath),
191
+ fs.promises.readFile(absoluteCertChainPath),
192
+ ];
310
193
  if (this.config.credentialsSsl.rootCA !== 'rootCA') {
311
194
  const absoluteRootCAPath = path.isAbsolute(this.config.credentialsSsl.rootCA)
312
195
  ? this.config.credentialsSsl.rootCA
@@ -384,14 +267,20 @@ ${rootJsonAndDecodedDescriptorSets
384
267
  description,
385
268
  fields: {},
386
269
  });
387
- for (const [fieldName, { type, rule, comment }] of fieldEntries) {
270
+ for (const [fieldName, { type, rule, comment, keyType }] of fieldEntries) {
388
271
  logger.debug(`Visiting ${currentPath}.nested.fields[${fieldName}]`);
389
272
  const baseFieldTypePath = type.split('.');
390
273
  inputTC.addFields({
391
274
  [fieldName]: {
392
275
  type: () => {
393
- const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
394
- const fieldInputTypeName = getTypeName(this.schemaComposer, fieldTypePath, true);
276
+ let fieldInputTypeName;
277
+ if (keyType) {
278
+ fieldInputTypeName = 'JSON';
279
+ }
280
+ else {
281
+ const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
282
+ fieldInputTypeName = getTypeName(this.schemaComposer, fieldTypePath, true);
283
+ }
395
284
  return rule === 'repeated' ? `[${fieldInputTypeName}]` : fieldInputTypeName;
396
285
  },
397
286
  description: comment,
@@ -400,8 +289,14 @@ ${rootJsonAndDecodedDescriptorSets
400
289
  outputTC.addFields({
401
290
  [fieldName]: {
402
291
  type: () => {
403
- const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
404
- const fieldTypeName = getTypeName(this.schemaComposer, fieldTypePath, false);
292
+ let fieldTypeName;
293
+ if (keyType) {
294
+ fieldTypeName = 'JSON';
295
+ }
296
+ else {
297
+ const fieldTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseFieldTypePath);
298
+ fieldTypeName = getTypeName(this.schemaComposer, fieldTypePath, false);
299
+ }
405
300
  return rule === 'repeated' ? `[${fieldTypeName}]` : fieldTypeName;
406
301
  },
407
302
  description: comment,
@@ -429,6 +324,10 @@ ${rootJsonAndDecodedDescriptorSets
429
324
  throw new Error(`Object at path ${objPath} is not a Service constructor`);
430
325
  }
431
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
+ });
432
331
  for (const methodName in nested.methods) {
433
332
  const method = nested.methods[methodName];
434
333
  const rootFieldName = [...pathWithName, methodName].join('_');
@@ -438,7 +337,11 @@ ${rootJsonAndDecodedDescriptorSets
438
337
  const baseResponseTypePath = (_a = method.responseType) === null || _a === void 0 ? void 0 : _a.split('.');
439
338
  if (baseResponseTypePath) {
440
339
  const responseTypePath = this.walkToFindTypePath(rootJson, pathWithName, baseResponseTypePath);
441
- return getTypeName(this.schemaComposer, responseTypePath, false);
340
+ let typeName = getTypeName(this.schemaComposer, responseTypePath, false);
341
+ if (method.responseStream) {
342
+ typeName = `[${typeName}]`;
343
+ }
344
+ return typeName;
442
345
  }
443
346
  return 'Void';
444
347
  },
@@ -459,28 +362,22 @@ ${rootJsonAndDecodedDescriptorSets
459
362
  return undefined;
460
363
  },
461
364
  };
462
- if (method.responseStream) {
463
- this.schemaComposer.Subscription.addFields({
464
- [rootFieldName]: {
465
- ...fieldConfig,
466
- subscribe: (__, args, context) => addMetaDataToCall(client[methodName].bind(client), args.input, context, this.config.metaData, true),
467
- resolve: (payload) => payload,
468
- },
469
- });
470
- }
471
- else {
472
- const methodNameLowerCased = methodName.toLowerCase();
473
- const prefixQueryMethod = this.config.prefixQueryMethod || QUERY_METHOD_PREFIXES;
474
- const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
475
- ? this.schemaComposer.Query
476
- : this.schemaComposer.Mutation;
477
- rootTypeComposer.addFields({
478
- [rootFieldName]: {
479
- ...fieldConfig,
480
- resolve: (_, args, context) => addMetaDataToCall(client[methodName].bind(client), args.input, context, this.config.metaData),
481
- },
482
- });
483
- }
365
+ const methodNameLowerCased = methodName.toLowerCase();
366
+ const prefixQueryMethod = this.config.prefixQueryMethod || QUERY_METHOD_PREFIXES;
367
+ const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
368
+ ? this.schemaComposer.Query
369
+ : this.schemaComposer.Mutation;
370
+ rootTypeComposer.addFields({
371
+ [rootFieldName]: {
372
+ ...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),
379
+ },
380
+ });
484
381
  }
485
382
  const connectivityStateFieldName = pathWithName.join('_') + '_connectivityState';
486
383
  this.schemaComposer.Query.addFields({
@@ -521,14 +418,26 @@ ${rootJsonAndDecodedDescriptorSets
521
418
  const creds = await this.getCredentials();
522
419
  this.logger.debug(`Getting stored root and decoded descriptor set objects`);
523
420
  const artifacts = await this.getCachedDescriptorSets(creds);
524
- for (const { name, rootJson, decodedDescriptorSet } of artifacts) {
421
+ for (const { name, rootJson } of artifacts) {
525
422
  const rootLogger = this.logger.child(name);
526
423
  rootLogger.debug(`Creating package definition from file descriptor set object`);
527
- const packageDefinition = loadFileDescriptorSetFromObject(decodedDescriptorSet);
424
+ let options;
425
+ if (typeof this.config.source === 'object') {
426
+ options = this.config.source.load;
427
+ }
428
+ const packageDefinition = fromJSON(rootJson, options);
528
429
  rootLogger.debug(`Creating service client for package definition`);
529
430
  const grpcObject = loadPackageDefinition(packageDefinition);
530
431
  this.logger.debug(`Building the schema structure based on the root object`);
531
- this.visit({ nested: rootJson, name: '', currentPath: [], rootJson, creds, grpcObject, rootLogger });
432
+ this.visit({
433
+ nested: rootJson,
434
+ name: '',
435
+ currentPath: [],
436
+ rootJson,
437
+ creds,
438
+ grpcObject,
439
+ rootLogger,
440
+ });
532
441
  }
533
442
  // graphql-compose doesn't add @defer and @stream to the schema
534
443
  specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
@@ -539,5 +448,3 @@ ${rootJsonAndDecodedDescriptorSets
539
448
  };
540
449
  }
541
450
  }
542
-
543
- export default GrpcHandler;
@@ -0,0 +1,11 @@
1
+ import Long from 'long';
2
+ function patchLongJs() {
3
+ const originalLongFromValue = Long.fromValue.bind(Long);
4
+ Long.fromValue = (value) => {
5
+ if (typeof value === 'bigint') {
6
+ return Long.fromValue(value.toString());
7
+ }
8
+ return originalLongFromValue(value);
9
+ };
10
+ }
11
+ patchLongJs();
package/esm/scalars.js ADDED
@@ -0,0 +1,27 @@
1
+ const SCALARS = new Map([
2
+ ['bool', 'Boolean'],
3
+ ['bytes', 'Byte'],
4
+ ['double', 'Float'],
5
+ ['fixed32', 'Int'],
6
+ ['fixed64', 'BigInt'],
7
+ ['float', 'Float'],
8
+ ['int32', 'Int'],
9
+ ['int64', 'BigInt'],
10
+ ['sfixed32', 'Int'],
11
+ ['sfixed64', 'BigInt'],
12
+ ['sint32', 'Int'],
13
+ ['sint64', 'BigInt'],
14
+ ['string', 'String'],
15
+ ['uint32', 'UnsignedInt'],
16
+ ['uint64', 'BigInt'], // A new scalar might be needed
17
+ ]);
18
+ export function isScalarType(type) {
19
+ return SCALARS.has(type);
20
+ }
21
+ export function getGraphQLScalar(scalarType) {
22
+ const gqlScalar = SCALARS.get(scalarType);
23
+ if (!gqlScalar) {
24
+ throw new Error(`Could not find GraphQL Scalar for type ${scalarType}`);
25
+ }
26
+ return SCALARS.get(scalarType);
27
+ }
package/esm/utils.js ADDED
@@ -0,0 +1,89 @@
1
+ import lodashGet from 'lodash.get';
2
+ import { fs, path as pathModule } from '@graphql-mesh/cross-helpers';
3
+ import { stringInterpolator } from '@graphql-mesh/string-interpolation';
4
+ import { withCancel } from '@graphql-mesh/utils';
5
+ import { Metadata, } from '@grpc/grpc-js';
6
+ import { getGraphQLScalar, isScalarType } from './scalars.js';
7
+ export function getTypeName(schemaComposer, pathWithName, isInput) {
8
+ if (pathWithName === null || pathWithName === void 0 ? void 0 : pathWithName.length) {
9
+ const baseTypeName = pathWithName.filter(Boolean).join('_');
10
+ if (isScalarType(baseTypeName)) {
11
+ return getGraphQLScalar(baseTypeName);
12
+ }
13
+ if (schemaComposer.isEnumType(baseTypeName)) {
14
+ return baseTypeName;
15
+ }
16
+ return isInput ? baseTypeName + '_Input' : baseTypeName;
17
+ }
18
+ return 'Void';
19
+ }
20
+ export function addIncludePathResolver(root, includePaths) {
21
+ const originalResolvePath = root.resolvePath;
22
+ root.resolvePath = (origin, target) => {
23
+ if (pathModule.isAbsolute(target)) {
24
+ return target;
25
+ }
26
+ for (const directory of includePaths) {
27
+ const fullPath = pathModule.join(directory, target);
28
+ if (fs.existsSync(fullPath)) {
29
+ return fullPath;
30
+ }
31
+ }
32
+ const path = originalResolvePath(origin, target);
33
+ if (path === null) {
34
+ console.warn(`${target} not found in any of the include paths ${includePaths}`);
35
+ }
36
+ return path;
37
+ };
38
+ }
39
+ function isBlob(input) {
40
+ return input != null && input.stream instanceof Function;
41
+ }
42
+ export function addMetaDataToCall(callFn, input, resolverData, metaData, isResponseStream = false) {
43
+ const callFnArguments = [];
44
+ if (!isBlob(input)) {
45
+ callFnArguments.push(input);
46
+ }
47
+ if (metaData) {
48
+ const meta = new Metadata();
49
+ for (const [key, value] of Object.entries(metaData)) {
50
+ let metaValue = value;
51
+ if (Array.isArray(value)) {
52
+ // Extract data from context
53
+ metaValue = lodashGet(resolverData.context, value);
54
+ }
55
+ // Ensure that the metadata is compatible with what node-grpc expects
56
+ if (typeof metaValue !== 'string' && !(metaValue instanceof Buffer)) {
57
+ metaValue = JSON.stringify(metaValue);
58
+ }
59
+ if (typeof metaValue === 'string') {
60
+ metaValue = stringInterpolator.parse(metaValue, resolverData);
61
+ }
62
+ meta.add(key, metaValue);
63
+ }
64
+ callFnArguments.push(meta);
65
+ }
66
+ return new Promise((resolve, reject) => {
67
+ const call = callFn(...callFnArguments, (error, response) => {
68
+ if (error) {
69
+ reject(error);
70
+ }
71
+ resolve(response);
72
+ });
73
+ if (isResponseStream) {
74
+ let isCancelled = false;
75
+ const responseStreamWithCancel = withCancel(call, () => {
76
+ var _a;
77
+ if (!isCancelled) {
78
+ (_a = call.call) === null || _a === void 0 ? void 0 : _a.cancelWithStatus(0, 'Cancelled by GraphQL Mesh');
79
+ isCancelled = true;
80
+ }
81
+ });
82
+ resolve(responseStreamWithCancel);
83
+ if (isBlob(input)) {
84
+ const blobStream = input.stream();
85
+ blobStream.pipe(call);
86
+ }
87
+ }
88
+ });
89
+ }