@omnigraph/grpc 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.grpcRootJsonDirective = exports.EnumDirective = exports.grpcConnectivityStateDirective = exports.grpcMethodDirective = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const transport_common_1 = require("@graphql-mesh/transport-common");
6
+ exports.grpcMethodDirective = new graphql_1.GraphQLDirective({
7
+ name: 'grpcMethod',
8
+ locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
9
+ args: {
10
+ subgraph: {
11
+ type: graphql_1.GraphQLString,
12
+ },
13
+ rootJsonName: {
14
+ type: graphql_1.GraphQLString,
15
+ },
16
+ objPath: {
17
+ type: graphql_1.GraphQLString,
18
+ },
19
+ methodName: {
20
+ type: graphql_1.GraphQLString,
21
+ },
22
+ responseStream: {
23
+ type: graphql_1.GraphQLBoolean,
24
+ },
25
+ },
26
+ });
27
+ exports.grpcConnectivityStateDirective = new graphql_1.GraphQLDirective({
28
+ name: 'grpcConnectivityState',
29
+ locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
30
+ args: {
31
+ subgraph: {
32
+ type: graphql_1.GraphQLString,
33
+ },
34
+ rootJsonName: {
35
+ type: graphql_1.GraphQLString,
36
+ },
37
+ objPath: {
38
+ type: graphql_1.GraphQLString,
39
+ },
40
+ },
41
+ });
42
+ exports.EnumDirective = new graphql_1.GraphQLDirective({
43
+ name: 'enum',
44
+ locations: [graphql_1.DirectiveLocation.ENUM_VALUE],
45
+ args: {
46
+ subgraph: {
47
+ type: graphql_1.GraphQLString,
48
+ },
49
+ value: {
50
+ type: graphql_1.GraphQLString,
51
+ },
52
+ },
53
+ });
54
+ exports.grpcRootJsonDirective = new graphql_1.GraphQLDirective({
55
+ name: 'grpcRootJson',
56
+ locations: [graphql_1.DirectiveLocation.OBJECT],
57
+ args: {
58
+ subgraph: {
59
+ type: graphql_1.GraphQLString,
60
+ },
61
+ name: {
62
+ type: graphql_1.GraphQLString,
63
+ },
64
+ rootJson: {
65
+ type: transport_common_1.ObjMapScalar,
66
+ },
67
+ loadOptions: {
68
+ type: transport_common_1.ObjMapScalar,
69
+ },
70
+ },
71
+ isRepeatable: true,
72
+ });
@@ -0,0 +1,465 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.gRPCLoader = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_1 = require("graphql");
6
+ const graphql_compose_1 = require("graphql-compose");
7
+ const graphql_scalars_1 = require("graphql-scalars");
8
+ const directives_js_1 = require("./directives.js");
9
+ const grpc_js_1 = require("@grpc/grpc-js");
10
+ const protobufjs_1 = tslib_1.__importDefault(require("protobufjs"));
11
+ const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
12
+ const node_path_1 = require("node:path");
13
+ const cross_helpers_1 = require("@graphql-mesh/cross-helpers");
14
+ const globby_1 = tslib_1.__importDefault(require("globby"));
15
+ const utils_js_1 = require("./utils.js");
16
+ const utils_1 = require("@graphql-tools/utils");
17
+ const index_js_1 = tslib_1.__importDefault(require("protobufjs/ext/descriptor/index.js"));
18
+ const grpc_reflection_js_1 = require("@ardatan/grpc-reflection-js");
19
+ const disposablestack_1 = require("@whatwg-node/disposablestack");
20
+ const { Root } = protobufjs_1.default;
21
+ const QUERY_METHOD_PREFIXES = ['get', 'list', 'search'];
22
+ class gRPCLoader {
23
+ constructor(subgraphName, baseDir, logger, config) {
24
+ this.subgraphName = subgraphName;
25
+ this.baseDir = baseDir;
26
+ this.logger = logger;
27
+ this.config = config;
28
+ this.schemaComposer = new graphql_compose_1.SchemaComposer();
29
+ this.asyncDisposableStack = new disposablestack_1.AsyncDisposableStack;
30
+ }
31
+ [Symbol.asyncDispose]() {
32
+ return this.asyncDisposableStack.disposeAsync();
33
+ }
34
+ async buildSchema() {
35
+ this.schemaComposer.add(graphql_scalars_1.GraphQLBigInt);
36
+ this.schemaComposer.add(graphql_scalars_1.GraphQLByte);
37
+ this.schemaComposer.add(graphql_scalars_1.GraphQLUnsignedInt);
38
+ this.schemaComposer.add(graphql_scalars_1.GraphQLVoid);
39
+ this.schemaComposer.add(graphql_scalars_1.GraphQLJSON);
40
+ this.schemaComposer.createScalarTC({
41
+ name: 'File',
42
+ });
43
+ // identical of grpc's ConnectivityState
44
+ this.schemaComposer.createEnumTC({
45
+ name: 'ConnectivityState',
46
+ values: {
47
+ IDLE: { value: 0 },
48
+ CONNECTING: { value: 1 },
49
+ READY: { value: 2 },
50
+ TRANSIENT_FAILURE: { value: 3 },
51
+ SHUTDOWN: { value: 4 },
52
+ },
53
+ });
54
+ this.config.requestTimeout = this.config.requestTimeout || 200000;
55
+ this.logger.debug(`Getting channel credentials`);
56
+ const creds = await this.getCredentials();
57
+ this.logger.debug(`Getting stored root and decoded descriptor set objects`);
58
+ const descriptorSets = await this.getDescriptorSets(creds);
59
+ const directives = [];
60
+ for (const { name: rootJsonName, rootJson } of descriptorSets) {
61
+ const rootLogger = this.logger.child(rootJsonName);
62
+ this.logger.debug(`Building the schema structure based on the root object`);
63
+ this.visit({
64
+ nested: rootJson,
65
+ name: '',
66
+ currentPath: [],
67
+ rootJsonName,
68
+ rootJson,
69
+ rootLogger,
70
+ });
71
+ this.schemaComposer.addDirective(directives_js_1.grpcRootJsonDirective);
72
+ directives.push({
73
+ name: 'grpcRootJson',
74
+ args: {
75
+ subgraph: this.subgraphName,
76
+ name: rootJsonName,
77
+ rootJson,
78
+ },
79
+ });
80
+ }
81
+ this.schemaComposer.Query.setDirectives(directives);
82
+ // graphql-compose doesn't add @defer and @stream to the schema
83
+ graphql_1.specifiedDirectives.forEach(directive => this.schemaComposer.addDirective(directive));
84
+ if (!this.schemaComposer.hasDirective('stream')) {
85
+ this.schemaComposer.addDirective(utils_1.GraphQLStreamDirective);
86
+ }
87
+ this.logger.debug(`Building the final GraphQL Schema`);
88
+ const schema = this.schemaComposer.buildSchema();
89
+ const schemaExtensions = schema.extensions = schema.extensions || {};
90
+ const directiveExtensions = schemaExtensions.directives = schemaExtensions.directives || {};
91
+ directiveExtensions.transport = {
92
+ subgraph: this.subgraphName,
93
+ kind: 'grpc',
94
+ location: this.config.endpoint,
95
+ options: {
96
+ requestTimeout: this.config.requestTimeout,
97
+ credentialsSsl: this.config.credentialsSsl,
98
+ useHTTPS: this.config.useHTTPS,
99
+ metaData: this.config.metaData,
100
+ },
101
+ };
102
+ return schema;
103
+ }
104
+ processReflection(creds) {
105
+ this.logger.debug(`Using the reflection`);
106
+ const reflectionEndpoint = string_interpolation_1.stringInterpolator.parse(this.config.endpoint, { env: process.env });
107
+ this.logger.debug(`Creating gRPC Reflection Client`);
108
+ const reflectionClient = new grpc_reflection_js_1.Client(reflectionEndpoint, creds);
109
+ this.asyncDisposableStack.defer(() => reflectionClient.grpcClient.close());
110
+ return reflectionClient.listServices().then(services => (services.filter(service => service && !service?.startsWith('grpc.'))
111
+ .map(service => {
112
+ this.logger.debug(`Resolving root of Service: ${service} from the reflection response`);
113
+ return reflectionClient.fileContainingSymbol(service);
114
+ })));
115
+ }
116
+ async processDescriptorFile() {
117
+ let fileName;
118
+ let options;
119
+ if (typeof this.config.source === 'object') {
120
+ fileName = this.config.source.file;
121
+ options = {
122
+ ...this.config.source.load,
123
+ includeDirs: this.config.source.load.includeDirs?.map(includeDir => (0, node_path_1.isAbsolute)(includeDir) ? includeDir : (0, node_path_1.join)(this.baseDir, includeDir)),
124
+ };
125
+ }
126
+ else {
127
+ fileName = this.config.source;
128
+ }
129
+ fileName = string_interpolation_1.stringInterpolator.parse(fileName, { env: process.env });
130
+ const absoluteFilePath = (0, node_path_1.isAbsolute)(fileName)
131
+ ? fileName
132
+ : (0, node_path_1.join)(this.baseDir, fileName);
133
+ this.logger.debug(`Using the descriptor set from ${absoluteFilePath} `);
134
+ const descriptorSetBuffer = await cross_helpers_1.fs.promises.readFile(absoluteFilePath);
135
+ this.logger.debug(`Reading ${absoluteFilePath} `);
136
+ let decodedDescriptorSet;
137
+ if (absoluteFilePath.endsWith('json')) {
138
+ this.logger.debug(`Parsing ${absoluteFilePath} as json`);
139
+ const descriptorSetJSON = JSON.parse(descriptorSetBuffer.toString());
140
+ decodedDescriptorSet = index_js_1.default.FileDescriptorSet.fromObject(descriptorSetJSON);
141
+ }
142
+ else {
143
+ decodedDescriptorSet = index_js_1.default.FileDescriptorSet.decode(descriptorSetBuffer);
144
+ }
145
+ this.logger.debug(`Creating root from descriptor set`);
146
+ const rootFromDescriptor = Root.fromDescriptor(decodedDescriptorSet);
147
+ if (options.includeDirs) {
148
+ if (!Array.isArray(options.includeDirs)) {
149
+ return Promise.reject(new Error('The includeDirs option must be an array'));
150
+ }
151
+ (0, utils_js_1.addIncludePathResolver)(rootFromDescriptor, options.includeDirs);
152
+ }
153
+ return rootFromDescriptor;
154
+ }
155
+ async processProtoFile() {
156
+ this.logger.debug(`Using proto file(s)`);
157
+ let protoRoot = new Root();
158
+ let fileGlob;
159
+ let options = {
160
+ keepCase: true,
161
+ alternateCommentMode: true,
162
+ };
163
+ if (typeof this.config.source === 'object') {
164
+ fileGlob = this.config.source.file;
165
+ options = {
166
+ ...options,
167
+ ...this.config.source.load,
168
+ includeDirs: this.config.source.load?.includeDirs?.map(includeDir => (0, node_path_1.isAbsolute)(includeDir) ? includeDir : (0, node_path_1.join)(this.baseDir, includeDir)),
169
+ };
170
+ if (options.includeDirs) {
171
+ if (!Array.isArray(options.includeDirs)) {
172
+ throw new Error('The includeDirs option must be an array');
173
+ }
174
+ (0, utils_js_1.addIncludePathResolver)(protoRoot, options.includeDirs);
175
+ }
176
+ }
177
+ else {
178
+ fileGlob = this.config.source;
179
+ }
180
+ fileGlob = string_interpolation_1.stringInterpolator.parse(fileGlob, { env: process.env });
181
+ const fileNames = await (0, globby_1.default)(fileGlob, {
182
+ cwd: this.baseDir,
183
+ });
184
+ this.logger.debug(`Loading proto files(${fileGlob}); \n ${fileNames.join('\n')} `);
185
+ protoRoot = await protoRoot.load(fileNames.map(filePath => (0, node_path_1.isAbsolute)(filePath) ? filePath : (0, node_path_1.join)(this.baseDir, filePath)), options);
186
+ this.logger.debug(`Adding proto content to the root`);
187
+ return protoRoot;
188
+ }
189
+ async getDescriptorSets(creds) {
190
+ const rootPromises = [];
191
+ this.logger.debug(`Building Roots`);
192
+ if (this.config.source) {
193
+ const filePath = typeof this.config.source === 'string' ? this.config.source : this.config.source.file;
194
+ if (filePath.endsWith('json')) {
195
+ rootPromises.push(this.processDescriptorFile());
196
+ }
197
+ else if (filePath.endsWith('proto')) {
198
+ rootPromises.push(this.processProtoFile());
199
+ }
200
+ }
201
+ else {
202
+ const reflectionPromises = await this.processReflection(creds);
203
+ rootPromises.push(...reflectionPromises);
204
+ }
205
+ return Promise.all(rootPromises.map(async (root$, i) => {
206
+ const root = await root$;
207
+ const rootName = root.name || `Root${i}`;
208
+ const rootLogger = this.logger.child(rootName);
209
+ rootLogger.debug(`Resolving entire the root tree`);
210
+ root.resolveAll();
211
+ rootLogger.debug(`Creating artifacts from descriptor set and root`);
212
+ return {
213
+ name: rootName,
214
+ rootJson: root.toJSON({
215
+ keepComments: true,
216
+ }),
217
+ };
218
+ }));
219
+ }
220
+ getCredentials() {
221
+ this.logger.debug(`Getting channel credentials`);
222
+ if (this.config.credentialsSsl) {
223
+ this.logger.debug(() => `Using SSL Connection with credentials at ${this.config.credentialsSsl.privateKey} & ${this.config.credentialsSsl.certChain}`);
224
+ const absolutePrivateKeyPath = (0, node_path_1.isAbsolute)(this.config.credentialsSsl.privateKey)
225
+ ? this.config.credentialsSsl.privateKey
226
+ : (0, node_path_1.join)(this.baseDir, this.config.credentialsSsl.privateKey);
227
+ const absoluteCertChainPath = (0, node_path_1.isAbsolute)(this.config.credentialsSsl.certChain)
228
+ ? this.config.credentialsSsl.certChain
229
+ : (0, node_path_1.join)(this.baseDir, this.config.credentialsSsl.certChain);
230
+ const sslFiles = [
231
+ cross_helpers_1.fs.promises.readFile(absolutePrivateKeyPath),
232
+ cross_helpers_1.fs.promises.readFile(absoluteCertChainPath),
233
+ ];
234
+ if (this.config.credentialsSsl.rootCA !== 'rootCA') {
235
+ const absoluteRootCAPath = (0, node_path_1.isAbsolute)(this.config.credentialsSsl.rootCA)
236
+ ? this.config.credentialsSsl.rootCA
237
+ : (0, node_path_1.join)(this.baseDir, this.config.credentialsSsl.rootCA);
238
+ sslFiles.unshift(cross_helpers_1.fs.promises.readFile(absoluteRootCAPath));
239
+ }
240
+ return Promise.all(sslFiles).then(([rootCA, privateKey, certChain]) => grpc_js_1.credentials.createSsl(rootCA, privateKey, certChain));
241
+ }
242
+ else if (this.config.useHTTPS) {
243
+ this.logger.debug(`Using SSL Connection`);
244
+ return grpc_js_1.credentials.createSsl();
245
+ }
246
+ this.logger.debug(`Using insecure connection`);
247
+ return grpc_js_1.credentials.createInsecure();
248
+ }
249
+ visit({ nested, name, currentPath, rootJsonName, rootJson, rootLogger: logger, }) {
250
+ const pathWithName = [...currentPath, ...name.split('.')].filter(Boolean);
251
+ if ('nested' in nested) {
252
+ for (const key in nested.nested) {
253
+ logger.debug(`Visiting ${currentPath}.nested[${key}]`);
254
+ const currentNested = nested.nested[key];
255
+ this.visit({
256
+ nested: currentNested,
257
+ name: key,
258
+ currentPath: pathWithName,
259
+ rootJsonName,
260
+ rootJson,
261
+ rootLogger: logger,
262
+ });
263
+ }
264
+ }
265
+ const typeName = pathWithName.join('__');
266
+ if ('values' in nested) {
267
+ const enumValues = {};
268
+ const commentMap = nested.comments;
269
+ for (const [key, value] of Object.entries(nested.values)) {
270
+ logger.debug(`Visiting ${currentPath}.nested.values[${key}]`);
271
+ enumValues[key] = {
272
+ directives: [
273
+ {
274
+ name: 'enum',
275
+ args: {
276
+ subgraph: this.subgraphName,
277
+ value: JSON.stringify(value),
278
+ },
279
+ },
280
+ ],
281
+ description: commentMap?.[key],
282
+ };
283
+ }
284
+ this.schemaComposer.addDirective(directives_js_1.EnumDirective);
285
+ this.schemaComposer.createEnumTC({
286
+ name: typeName,
287
+ values: enumValues,
288
+ description: nested.comment,
289
+ });
290
+ }
291
+ else if ('fields' in nested) {
292
+ const inputTypeName = typeName + '_Input';
293
+ const outputTypeName = typeName;
294
+ const description = nested.comment;
295
+ const fieldEntries = Object.entries(nested.fields);
296
+ if (fieldEntries.length) {
297
+ const inputTC = this.schemaComposer.createInputTC({
298
+ name: inputTypeName,
299
+ description,
300
+ fields: {},
301
+ });
302
+ const outputTC = this.schemaComposer.createObjectTC({
303
+ name: outputTypeName,
304
+ description,
305
+ fields: {},
306
+ });
307
+ for (const [fieldName, { type, rule, comment, keyType }] of fieldEntries) {
308
+ logger.debug(`Visiting ${currentPath}.nested.fields[${fieldName}]`);
309
+ const baseFieldTypePath = type.split('.');
310
+ inputTC.addFields({
311
+ [fieldName]: {
312
+ type: () => {
313
+ let fieldInputTypeName;
314
+ if (keyType) {
315
+ fieldInputTypeName = 'JSON';
316
+ }
317
+ else {
318
+ const fieldTypePath = (0, utils_js_1.walkToFindTypePath)(rootJson, pathWithName, baseFieldTypePath);
319
+ fieldInputTypeName = (0, utils_js_1.getTypeName)(this.schemaComposer, fieldTypePath, true);
320
+ }
321
+ return rule === 'repeated' ? `[${fieldInputTypeName}]` : fieldInputTypeName;
322
+ },
323
+ description: comment,
324
+ },
325
+ });
326
+ outputTC.addFields({
327
+ [fieldName]: {
328
+ type: () => {
329
+ let fieldTypeName;
330
+ if (keyType) {
331
+ fieldTypeName = 'JSON';
332
+ }
333
+ else {
334
+ const fieldTypePath = (0, utils_js_1.walkToFindTypePath)(rootJson, pathWithName, baseFieldTypePath);
335
+ fieldTypeName = (0, utils_js_1.getTypeName)(this.schemaComposer, fieldTypePath, false);
336
+ }
337
+ return rule === 'repeated' ? `[${fieldTypeName}]` : fieldTypeName;
338
+ },
339
+ description: comment,
340
+ },
341
+ });
342
+ }
343
+ }
344
+ else {
345
+ this.schemaComposer.createScalarTC({
346
+ ...graphql_scalars_1.GraphQLJSON.toConfig(),
347
+ name: inputTypeName,
348
+ description,
349
+ });
350
+ this.schemaComposer.createScalarTC({
351
+ ...graphql_scalars_1.GraphQLJSON.toConfig(),
352
+ name: outputTypeName,
353
+ description,
354
+ });
355
+ }
356
+ }
357
+ else if ('methods' in nested) {
358
+ const objPath = pathWithName.join('.');
359
+ for (const methodName in nested.methods) {
360
+ const method = nested.methods[methodName];
361
+ const rootFieldName = [...pathWithName, methodName].join('_');
362
+ const fieldConfigTypeFactory = () => {
363
+ const baseResponseTypePath = method.responseType?.split('.');
364
+ if (baseResponseTypePath) {
365
+ const responseTypePath = (0, utils_js_1.walkToFindTypePath)(rootJson, pathWithName, baseResponseTypePath);
366
+ return (0, utils_js_1.getTypeName)(this.schemaComposer, responseTypePath, false);
367
+ }
368
+ return 'Void';
369
+ };
370
+ const fieldConfig = {
371
+ type: () => {
372
+ const typeName = fieldConfigTypeFactory();
373
+ if (method.responseStream) {
374
+ return `[${typeName}]`;
375
+ }
376
+ return typeName;
377
+ },
378
+ description: method.comment,
379
+ };
380
+ const fieldConfigArgs = {
381
+ input: () => {
382
+ if (method.requestStream) {
383
+ return 'File';
384
+ }
385
+ const baseRequestTypePath = method.requestType?.split('.');
386
+ if (baseRequestTypePath) {
387
+ const requestTypePath = (0, utils_js_1.walkToFindTypePath)(rootJson, pathWithName, baseRequestTypePath);
388
+ const requestTypeName = (0, utils_js_1.getTypeName)(this.schemaComposer, requestTypePath, true);
389
+ return requestTypeName;
390
+ }
391
+ return undefined;
392
+ },
393
+ };
394
+ fieldConfig.args = fieldConfigArgs;
395
+ const methodNameLowerCased = methodName.toLowerCase();
396
+ const prefixQueryMethod = this.config.prefixQueryMethod || QUERY_METHOD_PREFIXES;
397
+ const rootTypeComposer = prefixQueryMethod.some(prefix => methodNameLowerCased.startsWith(prefix))
398
+ ? this.schemaComposer.Query
399
+ : this.schemaComposer.Mutation;
400
+ this.schemaComposer.addDirective(directives_js_1.grpcMethodDirective);
401
+ rootTypeComposer.addFields({
402
+ [rootFieldName]: {
403
+ ...fieldConfig,
404
+ directives: [
405
+ {
406
+ name: 'grpcMethod',
407
+ args: {
408
+ subgraph: this.subgraphName,
409
+ rootJsonName,
410
+ objPath,
411
+ methodName,
412
+ responseStream: !!method.responseStream,
413
+ },
414
+ },
415
+ ],
416
+ },
417
+ });
418
+ if (method.responseStream) {
419
+ this.schemaComposer.Subscription.addFields({
420
+ [rootFieldName]: {
421
+ args: fieldConfigArgs,
422
+ description: method.comment,
423
+ type: fieldConfigTypeFactory,
424
+ directives: [
425
+ {
426
+ name: 'grpcMethod',
427
+ args: {
428
+ subgraph: this.subgraphName,
429
+ rootJsonName,
430
+ objPath,
431
+ methodName,
432
+ responseStream: true,
433
+ },
434
+ },
435
+ ],
436
+ },
437
+ });
438
+ }
439
+ }
440
+ const connectivityStateFieldName = pathWithName.join('_') + '_connectivityState';
441
+ this.schemaComposer.addDirective(directives_js_1.grpcConnectivityStateDirective);
442
+ this.schemaComposer.Query.addFields({
443
+ [connectivityStateFieldName]: {
444
+ type: 'ConnectivityState',
445
+ args: {
446
+ tryToConnect: {
447
+ type: 'Boolean',
448
+ },
449
+ },
450
+ directives: [
451
+ {
452
+ name: 'grpcConnectivityState',
453
+ args: {
454
+ subgraph: this.subgraphName,
455
+ rootJsonName,
456
+ objPath,
457
+ },
458
+ },
459
+ ],
460
+ },
461
+ });
462
+ }
463
+ }
464
+ }
465
+ exports.gRPCLoader = gRPCLoader;
package/cjs/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadGrpcSubgraph = loadGrpcSubgraph;
4
+ const gRPCLoader_1 = require("./gRPCLoader");
5
+ function loadGrpcSubgraph(name, options) {
6
+ return (ctx) => ({
7
+ name,
8
+ schema$: new gRPCLoader_1.gRPCLoader(name, ctx.cwd, ctx.logger, options).buildSchema(),
9
+ });
10
+ }
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
package/cjs/scalars.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isGrpcScalar = isGrpcScalar;
4
+ exports.getGraphQLScalarForGrpc = getGraphQLScalarForGrpc;
5
+ const SCALARS = new Map([
6
+ ['bool', 'Boolean'],
7
+ ['bytes', 'Byte'],
8
+ ['double', 'Float'],
9
+ ['fixed32', 'Int'],
10
+ ['fixed64', 'BigInt'],
11
+ ['float', 'Float'],
12
+ ['int32', 'Int'],
13
+ ['int64', 'BigInt'],
14
+ ['sfixed32', 'Int'],
15
+ ['sfixed64', 'BigInt'],
16
+ ['sint32', 'Int'],
17
+ ['sint64', 'BigInt'],
18
+ ['string', 'String'],
19
+ ['uint32', 'UnsignedInt'],
20
+ ['uint64', 'BigInt'], // A new scalar might be needed
21
+ ]);
22
+ function isGrpcScalar(type) {
23
+ return SCALARS.has(type);
24
+ }
25
+ function getGraphQLScalarForGrpc(scalarType) {
26
+ const gqlScalar = SCALARS.get(scalarType);
27
+ if (!gqlScalar) {
28
+ throw new Error(`Could not find GraphQL Scalar for type ${scalarType}`);
29
+ }
30
+ return SCALARS.get(scalarType);
31
+ }
package/cjs/utils.js ADDED
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addIncludePathResolver = addIncludePathResolver;
4
+ exports.getTypeName = getTypeName;
5
+ exports.walkToFindTypePath = walkToFindTypePath;
6
+ const tslib_1 = require("tslib");
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const scalars_js_1 = require("./scalars.js");
10
+ const lodash_has_1 = tslib_1.__importDefault(require("lodash.has"));
11
+ function addIncludePathResolver(root, includePaths) {
12
+ const originalResolvePath = root.resolvePath;
13
+ root.resolvePath = (origin, target) => {
14
+ if ((0, path_1.isAbsolute)(target)) {
15
+ return target;
16
+ }
17
+ for (const directory of includePaths) {
18
+ const fullPath = (0, path_1.join)(directory, target);
19
+ if ((0, fs_1.existsSync)(fullPath)) {
20
+ return fullPath;
21
+ }
22
+ }
23
+ const path = originalResolvePath(origin, target);
24
+ if (path === null) {
25
+ console.warn(`${target} not found in any of the include paths ${includePaths}`);
26
+ }
27
+ return path;
28
+ };
29
+ }
30
+ function getTypeName(schemaComposer, pathWithName, isInput) {
31
+ if (pathWithName?.length) {
32
+ const baseTypeName = pathWithName.filter(Boolean).join('__');
33
+ if ((0, scalars_js_1.isGrpcScalar)(baseTypeName)) {
34
+ return (0, scalars_js_1.getGraphQLScalarForGrpc)(baseTypeName);
35
+ }
36
+ if (schemaComposer.isEnumType(baseTypeName)) {
37
+ return baseTypeName;
38
+ }
39
+ return isInput ? baseTypeName + '_Input' : baseTypeName;
40
+ }
41
+ return 'Void';
42
+ }
43
+ function walkToFindTypePath(rootJson, pathWithName, baseTypePath) {
44
+ const currentWalkingPath = [...pathWithName];
45
+ while (!(0, lodash_has_1.default)(rootJson.nested, currentWalkingPath.concat(baseTypePath).join('.nested.'))) {
46
+ if (!currentWalkingPath.length) {
47
+ break;
48
+ }
49
+ currentWalkingPath.pop();
50
+ }
51
+ return currentWalkingPath.concat(baseTypePath);
52
+ }