@graphql-mesh/transport-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.
package/cjs/index.js ADDED
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.gRPCTransport = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const transport_common_1 = require("@graphql-mesh/transport-common");
6
+ const cross_helpers_1 = require("@graphql-mesh/cross-helpers");
7
+ const grpc_js_1 = require("@grpc/grpc-js");
8
+ const proto_loader_1 = require("@grpc/proto-loader");
9
+ const lodash_get_1 = tslib_1.__importDefault(require("lodash.get"));
10
+ const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
11
+ const disposablestack_1 = require("@whatwg-node/disposablestack");
12
+ const graphql_1 = require("graphql");
13
+ const utils_js_1 = require("./utils.js");
14
+ const graphql_scalars_1 = require("graphql-scalars");
15
+ const utils_1 = require("@graphql-tools/utils");
16
+ const utils_2 = require("@graphql-mesh/utils");
17
+ require("./patchLongJs.js");
18
+ class gRPCTransport extends disposablestack_1.DisposableStack {
19
+ constructor(baseDir, logger, endpoint, config) {
20
+ super();
21
+ this.baseDir = baseDir;
22
+ this.logger = logger;
23
+ this.endpoint = endpoint;
24
+ this.config = config;
25
+ this.grpcObjectByserviceClientByObjPath = new WeakMap();
26
+ }
27
+ getCredentials() {
28
+ this.logger.debug(`Getting channel credentials`);
29
+ if (this.config.credentialsSsl) {
30
+ this.logger.debug(() => `Using SSL Connection with credentials at ${this.config.credentialsSsl.privateKey} & ${this.config.credentialsSsl.certChain}`);
31
+ const absolutePrivateKeyPath = cross_helpers_1.path.isAbsolute(this.config.credentialsSsl.privateKey)
32
+ ? this.config.credentialsSsl.privateKey
33
+ : cross_helpers_1.path.join(this.baseDir, this.config.credentialsSsl.privateKey);
34
+ const absoluteCertChainPath = cross_helpers_1.path.isAbsolute(this.config.credentialsSsl.certChain)
35
+ ? this.config.credentialsSsl.certChain
36
+ : cross_helpers_1.path.join(this.baseDir, this.config.credentialsSsl.certChain);
37
+ const sslFiles = [
38
+ cross_helpers_1.fs.promises.readFile(absolutePrivateKeyPath),
39
+ cross_helpers_1.fs.promises.readFile(absoluteCertChainPath),
40
+ ];
41
+ if (this.config.credentialsSsl.rootCA !== 'rootCA') {
42
+ const absoluteRootCAPath = cross_helpers_1.path.isAbsolute(this.config.credentialsSsl.rootCA)
43
+ ? this.config.credentialsSsl.rootCA
44
+ : cross_helpers_1.path.join(this.baseDir, this.config.credentialsSsl.rootCA);
45
+ sslFiles.unshift(cross_helpers_1.fs.promises.readFile(absoluteRootCAPath));
46
+ }
47
+ return Promise.all(sslFiles).then(([rootCA, privateKey, certChain]) => grpc_js_1.credentials.createSsl(rootCA, privateKey, certChain));
48
+ }
49
+ else if (this.config.useHTTPS) {
50
+ this.logger.debug(`Using SSL Connection`);
51
+ return grpc_js_1.credentials.createSsl();
52
+ }
53
+ this.logger.debug(`Using insecure connection`);
54
+ return grpc_js_1.credentials.createInsecure();
55
+ }
56
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }) {
57
+ const packageDefinition = (0, proto_loader_1.fromJSON)(rootJson, loadOptions);
58
+ rootLogger.debug(`Creating service client for package definition`);
59
+ const grpcObject = (0, grpc_js_1.loadPackageDefinition)(packageDefinition);
60
+ return grpcObject;
61
+ }
62
+ getServiceClient({ grpcObject, objPath, creds, }) {
63
+ let serviceClientByObjPath = this.grpcObjectByserviceClientByObjPath.get(grpcObject);
64
+ if (!serviceClientByObjPath) {
65
+ serviceClientByObjPath = new Map();
66
+ this.grpcObjectByserviceClientByObjPath.set(grpcObject, serviceClientByObjPath);
67
+ }
68
+ let client = serviceClientByObjPath.get(objPath);
69
+ if (!client) {
70
+ const ServiceClient = (0, lodash_get_1.default)(grpcObject, objPath);
71
+ if (typeof ServiceClient !== 'function') {
72
+ throw new Error(`Object at path ${objPath} is not a Service constructor`);
73
+ }
74
+ client = new ServiceClient(string_interpolation_1.stringInterpolator.parse(this.endpoint, { env: cross_helpers_1.process.env }) ??
75
+ this.endpoint, creds);
76
+ this.defer(() => client.close());
77
+ serviceClientByObjPath.set(objPath, client);
78
+ }
79
+ return client;
80
+ }
81
+ getFieldResolver({ client, methodName, isResponseStream, }) {
82
+ const metaData = this.config.metaData;
83
+ const clientMethod = client[methodName].bind(client);
84
+ return function grpcFieldResolver(root, args, context) {
85
+ return (0, utils_js_1.addMetaDataToCall)(clientMethod, args.input, {
86
+ root,
87
+ args,
88
+ context,
89
+ env: cross_helpers_1.process.env,
90
+ }, metaData, isResponseStream);
91
+ };
92
+ }
93
+ getConnectivityStateResolver({ client, }) {
94
+ return function connectivityStateResolver(_, { tryToConnect }) {
95
+ return client.getChannel().getConnectivityState(tryToConnect);
96
+ };
97
+ }
98
+ processDirectives({ schema, creds }) {
99
+ const schemaTypeMap = schema.getTypeMap();
100
+ for (const scalarTypeName in graphql_scalars_1.resolvers) {
101
+ if (scalarTypeName in schemaTypeMap) {
102
+ (0, utils_js_1.addExecutionLogicToScalar)(schemaTypeMap[scalarTypeName], graphql_scalars_1.resolvers[scalarTypeName]);
103
+ }
104
+ }
105
+ if ('ObjMap' in schemaTypeMap) {
106
+ (0, utils_js_1.addExecutionLogicToScalar)(schemaTypeMap.ObjMap, transport_common_1.ObjMapScalar);
107
+ }
108
+ const queryType = schema.getQueryType();
109
+ const rootJsonAnnotations = (0, utils_1.getDirective)(schema, queryType, 'grpcRootJson');
110
+ const rootJsonMap = new Map();
111
+ const grpcObjectByRootJsonName = new Map();
112
+ for (let { name, rootJson, loadOptions } of rootJsonAnnotations) {
113
+ rootJson = typeof rootJson === 'string' ? JSON.parse(rootJson) : rootJson;
114
+ rootJsonMap.set(name, rootJson);
115
+ const rootLogger = this.logger.child(name);
116
+ grpcObjectByRootJsonName.set(name, this.getGrpcObject({ rootJson, loadOptions, rootLogger }));
117
+ }
118
+ const rootTypes = (0, utils_1.getRootTypes)(schema);
119
+ for (const rootType of rootTypes) {
120
+ const rootTypeFields = rootType.getFields();
121
+ for (const fieldName in rootTypeFields) {
122
+ const field = rootTypeFields[fieldName];
123
+ const directives = (0, utils_1.getDirectives)(schema, field);
124
+ if (directives?.length) {
125
+ for (const directiveObj of directives) {
126
+ switch (directiveObj.name) {
127
+ case 'grpcMethod': {
128
+ const { rootJsonName, objPath, methodName, responseStream } = directiveObj.args;
129
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
130
+ const client = this.getServiceClient({
131
+ grpcObject,
132
+ objPath,
133
+ creds,
134
+ });
135
+ if (rootType.name === 'Subscription') {
136
+ field.subscribe = this.getFieldResolver({
137
+ client,
138
+ methodName,
139
+ isResponseStream: responseStream,
140
+ });
141
+ field.resolve = function identityFn(root) {
142
+ console.log('geldi');
143
+ return root;
144
+ };
145
+ }
146
+ else {
147
+ field.resolve = this.getFieldResolver({
148
+ client,
149
+ methodName,
150
+ isResponseStream: responseStream,
151
+ });
152
+ }
153
+ break;
154
+ }
155
+ case 'grpcConnectivityState': {
156
+ const { rootJsonName, objPath } = directiveObj.args;
157
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
158
+ const client = this.getServiceClient({
159
+ grpcObject,
160
+ objPath,
161
+ creds,
162
+ });
163
+ field.resolve = this.getConnectivityStateResolver({ client });
164
+ break;
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ const typeMap = schema.getTypeMap();
172
+ for (const typeName in typeMap) {
173
+ const type = typeMap[typeName];
174
+ if ((0, graphql_1.isEnumType)(type)) {
175
+ const values = type.getValues();
176
+ for (const value of values) {
177
+ const enumAnnotations = (0, utils_1.getDirective)(schema, value, 'enum');
178
+ if (enumAnnotations?.length) {
179
+ for (const enumAnnotation of enumAnnotations) {
180
+ const enumSerializedValue = enumAnnotation.value;
181
+ if (enumSerializedValue) {
182
+ const serializedValue = JSON.parse(enumSerializedValue);
183
+ value.value = serializedValue;
184
+ let valueLookup = type._valueLookup;
185
+ if (!valueLookup) {
186
+ valueLookup = new Map(type.getValues().map(enumValue => [enumValue.value, enumValue]));
187
+ type._valueLookup = valueLookup;
188
+ }
189
+ type._valueLookup.set(serializedValue, value);
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }
198
+ exports.gRPCTransport = gRPCTransport;
199
+ exports.default = {
200
+ getSubgraphExecutor({ transportEntry, subgraph, cwd, logger }) {
201
+ const transport = new gRPCTransport(cwd, logger, transportEntry.location, transportEntry.options);
202
+ return (0, utils_2.mapMaybePromise)(transport.getCredentials(), creds => {
203
+ transport.processDirectives({ schema: subgraph, creds });
204
+ return (0, transport_common_1.createDefaultExecutor)(subgraph);
205
+ });
206
+ }
207
+ };
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const long_1 = tslib_1.__importDefault(require("long"));
5
+ function patchLongJs() {
6
+ const originalLongFromValue = long_1.default.fromValue.bind(long_1.default);
7
+ long_1.default.fromValue = (value) => {
8
+ if (typeof value === 'bigint') {
9
+ return long_1.default.fromValue(value.toString());
10
+ }
11
+ return originalLongFromValue(value);
12
+ };
13
+ }
14
+ patchLongJs();
package/cjs/utils.js ADDED
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addMetaDataToCall = addMetaDataToCall;
4
+ exports.addExecutionLogicToScalar = addExecutionLogicToScalar;
5
+ const tslib_1 = require("tslib");
6
+ const lodash_get_1 = tslib_1.__importDefault(require("lodash.get"));
7
+ const string_interpolation_1 = require("@graphql-mesh/string-interpolation");
8
+ const utils_1 = require("@graphql-mesh/utils");
9
+ const grpc_js_1 = require("@grpc/grpc-js");
10
+ function isBlob(input) {
11
+ return input != null && input.stream instanceof Function;
12
+ }
13
+ function addMetaDataToCall(callFn, input, resolverData, metaData, isResponseStream = false) {
14
+ const callFnArguments = [];
15
+ if (!isBlob(input)) {
16
+ callFnArguments.push(input);
17
+ }
18
+ if (metaData) {
19
+ const meta = new grpc_js_1.Metadata();
20
+ for (const [key, value] of Object.entries(metaData)) {
21
+ let metaValue = value;
22
+ if (Array.isArray(value)) {
23
+ // Extract data from context
24
+ metaValue = (0, lodash_get_1.default)(resolverData.context, value);
25
+ }
26
+ // Ensure that the metadata is compatible with what node-grpc expects
27
+ if (typeof metaValue !== 'string' && !(metaValue instanceof Buffer)) {
28
+ metaValue = JSON.stringify(metaValue);
29
+ }
30
+ if (typeof metaValue === 'string') {
31
+ metaValue = string_interpolation_1.stringInterpolator.parse(metaValue, resolverData);
32
+ }
33
+ meta.add(key, metaValue);
34
+ }
35
+ callFnArguments.push(meta);
36
+ }
37
+ return new Promise((resolve, reject) => {
38
+ const call = callFn(...callFnArguments, (error, response) => {
39
+ if (error) {
40
+ reject(error);
41
+ }
42
+ resolve(response);
43
+ });
44
+ if (isResponseStream) {
45
+ let isCancelled = false;
46
+ const responseStreamWithCancel = (0, utils_1.withCancel)(call, () => {
47
+ if (!isCancelled) {
48
+ call.call?.cancelWithStatus(0, 'Cancelled by GraphQL Mesh');
49
+ isCancelled = true;
50
+ }
51
+ });
52
+ resolve(responseStreamWithCancel);
53
+ if (isBlob(input)) {
54
+ const blobStream = input.stream();
55
+ blobStream.pipe(call);
56
+ }
57
+ }
58
+ });
59
+ }
60
+ function addExecutionLogicToScalar(nonExecutableScalar, actualScalar) {
61
+ Object.defineProperties(nonExecutableScalar, {
62
+ serialize: {
63
+ value: actualScalar.serialize,
64
+ },
65
+ parseValue: {
66
+ value: actualScalar.parseValue,
67
+ },
68
+ parseLiteral: {
69
+ value: actualScalar.parseLiteral,
70
+ },
71
+ extensions: {
72
+ value: {
73
+ ...actualScalar.extensions,
74
+ ...nonExecutableScalar.extensions,
75
+ },
76
+ },
77
+ });
78
+ }
package/esm/index.js ADDED
@@ -0,0 +1,202 @@
1
+ import { createDefaultExecutor, ObjMapScalar } from "@graphql-mesh/transport-common";
2
+ import { path, fs, process } from '@graphql-mesh/cross-helpers';
3
+ import { credentials, loadPackageDefinition } from '@grpc/grpc-js';
4
+ import { fromJSON } from '@grpc/proto-loader';
5
+ import lodashGet from 'lodash.get';
6
+ import { stringInterpolator } from '@graphql-mesh/string-interpolation';
7
+ import { DisposableStack } from '@whatwg-node/disposablestack';
8
+ import { isEnumType } from "graphql";
9
+ import { addExecutionLogicToScalar, addMetaDataToCall } from "./utils.js";
10
+ import { resolvers as scalarResolvers } from 'graphql-scalars';
11
+ import { getDirective, getDirectives, getRootTypes } from '@graphql-tools/utils';
12
+ import { mapMaybePromise } from "@graphql-mesh/utils";
13
+ import './patchLongJs.js';
14
+ export class gRPCTransport extends DisposableStack {
15
+ constructor(baseDir, logger, endpoint, config) {
16
+ super();
17
+ this.baseDir = baseDir;
18
+ this.logger = logger;
19
+ this.endpoint = endpoint;
20
+ this.config = config;
21
+ this.grpcObjectByserviceClientByObjPath = new WeakMap();
22
+ }
23
+ getCredentials() {
24
+ this.logger.debug(`Getting channel credentials`);
25
+ if (this.config.credentialsSsl) {
26
+ this.logger.debug(() => `Using SSL Connection with credentials at ${this.config.credentialsSsl.privateKey} & ${this.config.credentialsSsl.certChain}`);
27
+ const absolutePrivateKeyPath = path.isAbsolute(this.config.credentialsSsl.privateKey)
28
+ ? this.config.credentialsSsl.privateKey
29
+ : path.join(this.baseDir, this.config.credentialsSsl.privateKey);
30
+ const absoluteCertChainPath = path.isAbsolute(this.config.credentialsSsl.certChain)
31
+ ? this.config.credentialsSsl.certChain
32
+ : path.join(this.baseDir, this.config.credentialsSsl.certChain);
33
+ const sslFiles = [
34
+ fs.promises.readFile(absolutePrivateKeyPath),
35
+ fs.promises.readFile(absoluteCertChainPath),
36
+ ];
37
+ if (this.config.credentialsSsl.rootCA !== 'rootCA') {
38
+ const absoluteRootCAPath = path.isAbsolute(this.config.credentialsSsl.rootCA)
39
+ ? this.config.credentialsSsl.rootCA
40
+ : path.join(this.baseDir, this.config.credentialsSsl.rootCA);
41
+ sslFiles.unshift(fs.promises.readFile(absoluteRootCAPath));
42
+ }
43
+ return Promise.all(sslFiles).then(([rootCA, privateKey, certChain]) => credentials.createSsl(rootCA, privateKey, certChain));
44
+ }
45
+ else if (this.config.useHTTPS) {
46
+ this.logger.debug(`Using SSL Connection`);
47
+ return credentials.createSsl();
48
+ }
49
+ this.logger.debug(`Using insecure connection`);
50
+ return credentials.createInsecure();
51
+ }
52
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }) {
53
+ const packageDefinition = fromJSON(rootJson, loadOptions);
54
+ rootLogger.debug(`Creating service client for package definition`);
55
+ const grpcObject = loadPackageDefinition(packageDefinition);
56
+ return grpcObject;
57
+ }
58
+ getServiceClient({ grpcObject, objPath, creds, }) {
59
+ let serviceClientByObjPath = this.grpcObjectByserviceClientByObjPath.get(grpcObject);
60
+ if (!serviceClientByObjPath) {
61
+ serviceClientByObjPath = new Map();
62
+ this.grpcObjectByserviceClientByObjPath.set(grpcObject, serviceClientByObjPath);
63
+ }
64
+ let client = serviceClientByObjPath.get(objPath);
65
+ if (!client) {
66
+ const ServiceClient = lodashGet(grpcObject, objPath);
67
+ if (typeof ServiceClient !== 'function') {
68
+ throw new Error(`Object at path ${objPath} is not a Service constructor`);
69
+ }
70
+ client = new ServiceClient(stringInterpolator.parse(this.endpoint, { env: process.env }) ??
71
+ this.endpoint, creds);
72
+ this.defer(() => client.close());
73
+ serviceClientByObjPath.set(objPath, client);
74
+ }
75
+ return client;
76
+ }
77
+ getFieldResolver({ client, methodName, isResponseStream, }) {
78
+ const metaData = this.config.metaData;
79
+ const clientMethod = client[methodName].bind(client);
80
+ return function grpcFieldResolver(root, args, context) {
81
+ return addMetaDataToCall(clientMethod, args.input, {
82
+ root,
83
+ args,
84
+ context,
85
+ env: process.env,
86
+ }, metaData, isResponseStream);
87
+ };
88
+ }
89
+ getConnectivityStateResolver({ client, }) {
90
+ return function connectivityStateResolver(_, { tryToConnect }) {
91
+ return client.getChannel().getConnectivityState(tryToConnect);
92
+ };
93
+ }
94
+ processDirectives({ schema, creds }) {
95
+ const schemaTypeMap = schema.getTypeMap();
96
+ for (const scalarTypeName in scalarResolvers) {
97
+ if (scalarTypeName in schemaTypeMap) {
98
+ addExecutionLogicToScalar(schemaTypeMap[scalarTypeName], scalarResolvers[scalarTypeName]);
99
+ }
100
+ }
101
+ if ('ObjMap' in schemaTypeMap) {
102
+ addExecutionLogicToScalar(schemaTypeMap.ObjMap, ObjMapScalar);
103
+ }
104
+ const queryType = schema.getQueryType();
105
+ const rootJsonAnnotations = getDirective(schema, queryType, 'grpcRootJson');
106
+ const rootJsonMap = new Map();
107
+ const grpcObjectByRootJsonName = new Map();
108
+ for (let { name, rootJson, loadOptions } of rootJsonAnnotations) {
109
+ rootJson = typeof rootJson === 'string' ? JSON.parse(rootJson) : rootJson;
110
+ rootJsonMap.set(name, rootJson);
111
+ const rootLogger = this.logger.child(name);
112
+ grpcObjectByRootJsonName.set(name, this.getGrpcObject({ rootJson, loadOptions, rootLogger }));
113
+ }
114
+ const rootTypes = getRootTypes(schema);
115
+ for (const rootType of rootTypes) {
116
+ const rootTypeFields = rootType.getFields();
117
+ for (const fieldName in rootTypeFields) {
118
+ const field = rootTypeFields[fieldName];
119
+ const directives = getDirectives(schema, field);
120
+ if (directives?.length) {
121
+ for (const directiveObj of directives) {
122
+ switch (directiveObj.name) {
123
+ case 'grpcMethod': {
124
+ const { rootJsonName, objPath, methodName, responseStream } = directiveObj.args;
125
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
126
+ const client = this.getServiceClient({
127
+ grpcObject,
128
+ objPath,
129
+ creds,
130
+ });
131
+ if (rootType.name === 'Subscription') {
132
+ field.subscribe = this.getFieldResolver({
133
+ client,
134
+ methodName,
135
+ isResponseStream: responseStream,
136
+ });
137
+ field.resolve = function identityFn(root) {
138
+ console.log('geldi');
139
+ return root;
140
+ };
141
+ }
142
+ else {
143
+ field.resolve = this.getFieldResolver({
144
+ client,
145
+ methodName,
146
+ isResponseStream: responseStream,
147
+ });
148
+ }
149
+ break;
150
+ }
151
+ case 'grpcConnectivityState': {
152
+ const { rootJsonName, objPath } = directiveObj.args;
153
+ const grpcObject = grpcObjectByRootJsonName.get(rootJsonName);
154
+ const client = this.getServiceClient({
155
+ grpcObject,
156
+ objPath,
157
+ creds,
158
+ });
159
+ field.resolve = this.getConnectivityStateResolver({ client });
160
+ break;
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ const typeMap = schema.getTypeMap();
168
+ for (const typeName in typeMap) {
169
+ const type = typeMap[typeName];
170
+ if (isEnumType(type)) {
171
+ const values = type.getValues();
172
+ for (const value of values) {
173
+ const enumAnnotations = getDirective(schema, value, 'enum');
174
+ if (enumAnnotations?.length) {
175
+ for (const enumAnnotation of enumAnnotations) {
176
+ const enumSerializedValue = enumAnnotation.value;
177
+ if (enumSerializedValue) {
178
+ const serializedValue = JSON.parse(enumSerializedValue);
179
+ value.value = serializedValue;
180
+ let valueLookup = type._valueLookup;
181
+ if (!valueLookup) {
182
+ valueLookup = new Map(type.getValues().map(enumValue => [enumValue.value, enumValue]));
183
+ type._valueLookup = valueLookup;
184
+ }
185
+ type._valueLookup.set(serializedValue, value);
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ export default {
195
+ getSubgraphExecutor({ transportEntry, subgraph, cwd, logger }) {
196
+ const transport = new gRPCTransport(cwd, logger, transportEntry.location, transportEntry.options);
197
+ return mapMaybePromise(transport.getCredentials(), creds => {
198
+ transport.processDirectives({ schema: subgraph, creds });
199
+ return createDefaultExecutor(subgraph);
200
+ });
201
+ }
202
+ };
@@ -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/utils.js ADDED
@@ -0,0 +1,73 @@
1
+ import lodashGet from 'lodash.get';
2
+ import { stringInterpolator } from '@graphql-mesh/string-interpolation';
3
+ import { withCancel } from '@graphql-mesh/utils';
4
+ import { Metadata } from '@grpc/grpc-js';
5
+ function isBlob(input) {
6
+ return input != null && input.stream instanceof Function;
7
+ }
8
+ export function addMetaDataToCall(callFn, input, resolverData, metaData, isResponseStream = false) {
9
+ const callFnArguments = [];
10
+ if (!isBlob(input)) {
11
+ callFnArguments.push(input);
12
+ }
13
+ if (metaData) {
14
+ const meta = new Metadata();
15
+ for (const [key, value] of Object.entries(metaData)) {
16
+ let metaValue = value;
17
+ if (Array.isArray(value)) {
18
+ // Extract data from context
19
+ metaValue = lodashGet(resolverData.context, value);
20
+ }
21
+ // Ensure that the metadata is compatible with what node-grpc expects
22
+ if (typeof metaValue !== 'string' && !(metaValue instanceof Buffer)) {
23
+ metaValue = JSON.stringify(metaValue);
24
+ }
25
+ if (typeof metaValue === 'string') {
26
+ metaValue = stringInterpolator.parse(metaValue, resolverData);
27
+ }
28
+ meta.add(key, metaValue);
29
+ }
30
+ callFnArguments.push(meta);
31
+ }
32
+ return new Promise((resolve, reject) => {
33
+ const call = callFn(...callFnArguments, (error, response) => {
34
+ if (error) {
35
+ reject(error);
36
+ }
37
+ resolve(response);
38
+ });
39
+ if (isResponseStream) {
40
+ let isCancelled = false;
41
+ const responseStreamWithCancel = withCancel(call, () => {
42
+ if (!isCancelled) {
43
+ call.call?.cancelWithStatus(0, 'Cancelled by GraphQL Mesh');
44
+ isCancelled = true;
45
+ }
46
+ });
47
+ resolve(responseStreamWithCancel);
48
+ if (isBlob(input)) {
49
+ const blobStream = input.stream();
50
+ blobStream.pipe(call);
51
+ }
52
+ }
53
+ });
54
+ }
55
+ export function addExecutionLogicToScalar(nonExecutableScalar, actualScalar) {
56
+ Object.defineProperties(nonExecutableScalar, {
57
+ serialize: {
58
+ value: actualScalar.serialize,
59
+ },
60
+ parseValue: {
61
+ value: actualScalar.parseValue,
62
+ },
63
+ parseLiteral: {
64
+ value: actualScalar.parseLiteral,
65
+ },
66
+ extensions: {
67
+ value: {
68
+ ...actualScalar.extensions,
69
+ ...nonExecutableScalar.extensions,
70
+ },
71
+ },
72
+ });
73
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@graphql-mesh/transport-grpc",
3
+ "version": "0.0.0",
4
+ "sideEffects": false,
5
+ "peerDependencies": {
6
+ "@graphql-mesh/types": "^0.102.10",
7
+ "@graphql-mesh/utils": "^0.102.10",
8
+ "@graphql-tools/utils": "^10.5.5",
9
+ "graphql": "*",
10
+ "tslib": "^2.4.0"
11
+ },
12
+ "dependencies": {
13
+ "@graphql-mesh/string-interpolation": "^0.5.6",
14
+ "@graphql-mesh/transport-common": "^0.7.11",
15
+ "@grpc/grpc-js": "^1.1.7",
16
+ "@grpc/proto-loader": "^0.7.8",
17
+ "@whatwg-node/disposablestack": "^0.0.5",
18
+ "graphql-scalars": "^1.22.4",
19
+ "lodash.get": "^4.4.2",
20
+ "protobufjs": "^7.2.5"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "ardatan/graphql-mesh",
25
+ "directory": "packages/transports/grpc"
26
+ },
27
+ "license": "MIT",
28
+ "engines": {
29
+ "node": ">=16.0.0"
30
+ },
31
+ "main": "cjs/index.js",
32
+ "module": "esm/index.js",
33
+ "typings": "typings/index.d.ts",
34
+ "typescript": {
35
+ "definition": "typings/index.d.ts"
36
+ },
37
+ "type": "module",
38
+ "exports": {
39
+ ".": {
40
+ "require": {
41
+ "types": "./typings/index.d.cts",
42
+ "default": "./cjs/index.js"
43
+ },
44
+ "import": {
45
+ "types": "./typings/index.d.ts",
46
+ "default": "./esm/index.js"
47
+ },
48
+ "default": {
49
+ "types": "./typings/index.d.ts",
50
+ "default": "./esm/index.js"
51
+ }
52
+ },
53
+ "./package.json": "./package.json"
54
+ }
55
+ }
@@ -0,0 +1,73 @@
1
+ import type { Logger } from "@graphql-mesh/types";
2
+ import type { ChannelCredentials } from '@grpc/grpc-js';
3
+ import { loadPackageDefinition } from '@grpc/grpc-js';
4
+ import type { ServiceClient } from '@grpc/grpc-js/build/src/make-client.cjs';
5
+ import protobufjs from 'protobufjs';
6
+ import { DisposableStack } from '@whatwg-node/disposablestack';
7
+ import { type GraphQLFieldResolver, type GraphQLSchema } from "graphql";
8
+ import { type MaybePromise } from '@graphql-tools/utils';
9
+ import './patchLongJs.cjs';
10
+ /**
11
+ * SSL Credentials
12
+ */
13
+ interface GrpcCredentialsSsl {
14
+ rootCA?: string;
15
+ certChain?: string;
16
+ privateKey?: string;
17
+ }
18
+ export interface gRPCTransportOptions {
19
+ /**
20
+ * Request timeout in milliseconds
21
+ * Default: 200000
22
+ */
23
+ requestTimeout?: number;
24
+ credentialsSsl?: GrpcCredentialsSsl;
25
+ /**
26
+ * Use https instead of http for gRPC connection
27
+ */
28
+ useHTTPS?: boolean;
29
+ /**
30
+ * MetaData
31
+ */
32
+ metaData?: {
33
+ [k: string]: any;
34
+ };
35
+ }
36
+ interface LoadOptions {
37
+ includeDirs?: string[];
38
+ }
39
+ export declare class gRPCTransport extends DisposableStack {
40
+ private baseDir;
41
+ private logger;
42
+ private endpoint;
43
+ private config;
44
+ constructor(baseDir: string, logger: Logger, endpoint: string, config: gRPCTransportOptions);
45
+ getCredentials(): MaybePromise<ChannelCredentials>;
46
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }: {
47
+ rootJson: protobufjs.INamespace;
48
+ loadOptions: LoadOptions;
49
+ rootLogger: Logger;
50
+ }): import("@grpc/grpc-js").GrpcObject;
51
+ private grpcObjectByserviceClientByObjPath;
52
+ getServiceClient({ grpcObject, objPath, creds, }: {
53
+ grpcObject: ReturnType<typeof loadPackageDefinition>;
54
+ objPath: string;
55
+ creds: ChannelCredentials;
56
+ }): ServiceClient;
57
+ getFieldResolver({ client, methodName, isResponseStream, }: {
58
+ client: ServiceClient;
59
+ methodName: string;
60
+ isResponseStream: boolean;
61
+ }): GraphQLFieldResolver<any, any>;
62
+ getConnectivityStateResolver({ client, }: {
63
+ client: ServiceClient;
64
+ }): GraphQLFieldResolver<any, any>;
65
+ processDirectives({ schema, creds }: {
66
+ schema: GraphQLSchema;
67
+ creds: ChannelCredentials;
68
+ }): void;
69
+ }
70
+ declare const _default: {
71
+ getSubgraphExecutor({ transportEntry, subgraph, cwd, logger }: import("@graphql-mesh/transport-common").TransportGetSubgraphExecutorOptions<gRPCTransportOptions>): MaybePromise<import("@graphql-mesh/transport-common").Executor>;
72
+ };
73
+ export default _default;
@@ -0,0 +1,73 @@
1
+ import type { Logger } from "@graphql-mesh/types";
2
+ import type { ChannelCredentials } from '@grpc/grpc-js';
3
+ import { loadPackageDefinition } from '@grpc/grpc-js';
4
+ import type { ServiceClient } from '@grpc/grpc-js/build/src/make-client.js';
5
+ import protobufjs from 'protobufjs';
6
+ import { DisposableStack } from '@whatwg-node/disposablestack';
7
+ import { type GraphQLFieldResolver, type GraphQLSchema } from "graphql";
8
+ import { type MaybePromise } from '@graphql-tools/utils';
9
+ import './patchLongJs.js';
10
+ /**
11
+ * SSL Credentials
12
+ */
13
+ interface GrpcCredentialsSsl {
14
+ rootCA?: string;
15
+ certChain?: string;
16
+ privateKey?: string;
17
+ }
18
+ export interface gRPCTransportOptions {
19
+ /**
20
+ * Request timeout in milliseconds
21
+ * Default: 200000
22
+ */
23
+ requestTimeout?: number;
24
+ credentialsSsl?: GrpcCredentialsSsl;
25
+ /**
26
+ * Use https instead of http for gRPC connection
27
+ */
28
+ useHTTPS?: boolean;
29
+ /**
30
+ * MetaData
31
+ */
32
+ metaData?: {
33
+ [k: string]: any;
34
+ };
35
+ }
36
+ interface LoadOptions {
37
+ includeDirs?: string[];
38
+ }
39
+ export declare class gRPCTransport extends DisposableStack {
40
+ private baseDir;
41
+ private logger;
42
+ private endpoint;
43
+ private config;
44
+ constructor(baseDir: string, logger: Logger, endpoint: string, config: gRPCTransportOptions);
45
+ getCredentials(): MaybePromise<ChannelCredentials>;
46
+ getGrpcObject({ rootJson, loadOptions, rootLogger, }: {
47
+ rootJson: protobufjs.INamespace;
48
+ loadOptions: LoadOptions;
49
+ rootLogger: Logger;
50
+ }): import("@grpc/grpc-js").GrpcObject;
51
+ private grpcObjectByserviceClientByObjPath;
52
+ getServiceClient({ grpcObject, objPath, creds, }: {
53
+ grpcObject: ReturnType<typeof loadPackageDefinition>;
54
+ objPath: string;
55
+ creds: ChannelCredentials;
56
+ }): ServiceClient;
57
+ getFieldResolver({ client, methodName, isResponseStream, }: {
58
+ client: ServiceClient;
59
+ methodName: string;
60
+ isResponseStream: boolean;
61
+ }): GraphQLFieldResolver<any, any>;
62
+ getConnectivityStateResolver({ client, }: {
63
+ client: ServiceClient;
64
+ }): GraphQLFieldResolver<any, any>;
65
+ processDirectives({ schema, creds }: {
66
+ schema: GraphQLSchema;
67
+ creds: ChannelCredentials;
68
+ }): void;
69
+ }
70
+ declare const _default: {
71
+ getSubgraphExecutor({ transportEntry, subgraph, cwd, logger }: import("@graphql-mesh/transport-common").TransportGetSubgraphExecutorOptions<gRPCTransportOptions>): MaybePromise<import("@graphql-mesh/transport-common").Executor>;
72
+ };
73
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { ResolverData } from '@graphql-mesh/string-interpolation';
2
+ import type { GraphQLScalarType } from 'graphql';
3
+ export declare function addMetaDataToCall(callFn: any, input: any, resolverData: ResolverData, metaData: Record<string, string | string[] | Buffer>, isResponseStream?: boolean): Promise<unknown>;
4
+ export declare function addExecutionLogicToScalar(nonExecutableScalar: GraphQLScalarType, actualScalar: GraphQLScalarType): void;
@@ -0,0 +1,4 @@
1
+ import type { ResolverData } from '@graphql-mesh/string-interpolation';
2
+ import type { GraphQLScalarType } from 'graphql';
3
+ export declare function addMetaDataToCall(callFn: any, input: any, resolverData: ResolverData, metaData: Record<string, string | string[] | Buffer>, isResponseStream?: boolean): Promise<unknown>;
4
+ export declare function addExecutionLogicToScalar(nonExecutableScalar: GraphQLScalarType, actualScalar: GraphQLScalarType): void;