mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-25 13:45:52 +00:00
refactor: replace grpc-reflection-js with grpc-js-reflection-client in grpc-client implementation
rm: comment fix: type generation feat: implement reflection client support for gRPC v1 and v1alpha in grpc-client refactor: simplify reflection client handling in grpc-client by removing service list retrieval refactor: enhance reflection client return structure in grpc-client to include service list fix: lint
This commit is contained in:
53
package-lock.json
generated
53
package-lock.json
generated
@@ -8232,12 +8232,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/google-protobuf": {
|
||||
"version": "3.15.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.12.tgz",
|
||||
"integrity": "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/graceful-fs": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
|
||||
@@ -8373,9 +8367,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
|
||||
"integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==",
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash-es": {
|
||||
@@ -8388,15 +8382,6 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash.set": {
|
||||
"version": "4.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.set/-/lodash.set-4.3.9.tgz",
|
||||
"integrity": "sha512-KOxyNkZpbaggVmqbpr82N2tDVTx05/3/j0f50Es1prxrWB0XYf9p3QNxqcbWb7P1Q9wlvsUSlCFnwlPCIJ46PQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/markdown-it": {
|
||||
"version": "12.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
|
||||
@@ -15182,12 +15167,6 @@
|
||||
"csstype": "^3.0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/google-protobuf": {
|
||||
"version": "3.21.4",
|
||||
"resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz",
|
||||
"integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==",
|
||||
"license": "(BSD-3-Clause AND Apache-2.0)"
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
@@ -15312,20 +15291,18 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/grpc-reflection-js": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/grpc-reflection-js/-/grpc-reflection-js-0.3.0.tgz",
|
||||
"integrity": "sha512-3lhTlQluPxVgbowCXA3tAZC3RJW+GSOUkguLNYl1QffYRiutUB3RDfPkQFTcrCFJgNiIIxx+iJkr8s3uSp3zWA==",
|
||||
"node_modules/grpc-js-reflection-client": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/grpc-js-reflection-client/-/grpc-js-reflection-client-1.3.0.tgz",
|
||||
"integrity": "sha512-eJ5/m1pXpcheSjOGExktU69WPUKnL4Su3IxGJYYYjy3/w19vE8dH7Wi46G5T92bpM0eZWftjiM5HduX8CjPq9w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/google-protobuf": "^3.7.2",
|
||||
"@types/lodash.set": "^4.3.6",
|
||||
"google-protobuf": "^3.12.2",
|
||||
"lodash.set": "^4.3.2",
|
||||
"protobufjs": "^7.2.2"
|
||||
"@types/lodash": "^4.17.15",
|
||||
"lodash": "^4.17.21",
|
||||
"protobufjs": "^7.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@grpc/grpc-js": "^1.0.0"
|
||||
"@grpc/grpc-js": "^1.12.6"
|
||||
}
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
@@ -18634,12 +18611,6 @@
|
||||
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.set": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
|
||||
"integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
@@ -32129,7 +32100,7 @@
|
||||
"@types/qs": "^6.9.18",
|
||||
"axios": "^1.9.0",
|
||||
"debug": "^4.4.3",
|
||||
"grpc-reflection-js": "^0.3.0",
|
||||
"grpc-js-reflection-client": "^1.3.0",
|
||||
"is-ip": "^5.0.1",
|
||||
"system-ca": "^2.0.1",
|
||||
"tough-cookie": "^6.0.0",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@types/qs": "^6.9.18",
|
||||
"axios": "^1.9.0",
|
||||
"debug": "^4.4.3",
|
||||
"grpc-reflection-js": "^0.3.0",
|
||||
"grpc-js-reflection-client": "^1.3.0",
|
||||
"is-ip": "^5.0.1",
|
||||
"ws": "^8.18.3",
|
||||
"system-ca": "^2.0.1",
|
||||
@@ -53,4 +53,4 @@
|
||||
"overrides": {
|
||||
"rollup": "3.29.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { makeGenericClientConstructor, ChannelCredentials, Metadata } from '@grpc/grpc-js';
|
||||
import * as grpcReflection from 'grpc-reflection-js';
|
||||
import { makeGenericClientConstructor, ChannelCredentials, Metadata, status } from '@grpc/grpc-js';
|
||||
import { GrpcReflection } from 'grpc-js-reflection-client';
|
||||
import * as protoLoader from '@grpc/proto-loader';
|
||||
import { generateGrpcSampleMessage } from './grpcMessageGenerator';
|
||||
import * as tls from 'tls';
|
||||
@@ -34,6 +34,8 @@ const configOptions = {
|
||||
json: true
|
||||
};
|
||||
|
||||
const reflectionServices = ['grpc.reflection.v1alpha.ServerReflection', 'grpc.reflection.v1.ServerReflection'];
|
||||
|
||||
const replaceTabsWithSpaces = (str, numSpaces = 2) => {
|
||||
if (!str || !str.length || !isString(str)) {
|
||||
return '';
|
||||
@@ -172,6 +174,32 @@ class GrpcClient {
|
||||
this.eventCallback = eventCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reflection client that works for v1, v1alpha, or both.
|
||||
*
|
||||
* @param {string} host - host:port of the gRPC server
|
||||
* @param {grpc.ChannelCredentials} credentials - defaults to insecure
|
||||
* @param {grpc.ChannelOptions} options - channel options
|
||||
* @returns {Promise<{ client: GrpcReflection, version: 'v1' | 'v1alpha' }>}
|
||||
*/
|
||||
async #getReflectionClient(host, credentials = ChannelCredentials.createInsecure(), options = {}) {
|
||||
const makeClient = (version) => new GrpcReflection(host, credentials, options, version);
|
||||
let client;
|
||||
let services;
|
||||
|
||||
try {
|
||||
client = makeClient('v1');
|
||||
services = await client.listServices();
|
||||
return { client, services };
|
||||
} catch (e) {
|
||||
console.warn(`gRPC reflection v1 failed:`, e);
|
||||
}
|
||||
|
||||
client = makeClient('v1alpha');
|
||||
services = await client.listServices();
|
||||
return { client, services };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get method type based on streaming configuration
|
||||
*/
|
||||
@@ -582,31 +610,29 @@ class GrpcClient {
|
||||
});
|
||||
|
||||
try {
|
||||
const client = new grpcReflection.Client(host, credentials, {}, metadata);
|
||||
const { client, services } = await this.#getReflectionClient(host, credentials, {});
|
||||
const methods = [];
|
||||
|
||||
const declarations = await client.listServices();
|
||||
const methods = await Promise.all(
|
||||
declarations.map(async (declaration) => {
|
||||
const fileContainingSymbol = await client.fileContainingSymbol(declaration);
|
||||
const descriptor = fileContainingSymbol.toDescriptor('proto3');
|
||||
const protoDefinition = protoLoader.loadFileDescriptorSetFromObject(descriptor, configOptions);
|
||||
for (const service of services) {
|
||||
if (reflectionServices.includes(service)) {
|
||||
continue;
|
||||
}
|
||||
const m = await client.listMethods(service);
|
||||
methods.push(...m);
|
||||
}
|
||||
|
||||
const serviceDefinition = protoDefinition[declaration];
|
||||
if (!!serviceDefinition?.format) {
|
||||
return [];
|
||||
}
|
||||
const methods = Object.values(serviceDefinition);
|
||||
methods.forEach((method) => {
|
||||
this.methods.set(method.path, method);
|
||||
});
|
||||
return methods;
|
||||
})
|
||||
);
|
||||
|
||||
const methodsWithType = methods.flat().map((method) => ({
|
||||
...method,
|
||||
type: this.#getMethodType(method)
|
||||
}));
|
||||
const methodsWithType = methods.map((method) => {
|
||||
const { definition, ...rest } = method;
|
||||
const modifiedMethod = {
|
||||
...rest,
|
||||
...definition
|
||||
};
|
||||
modifiedMethod.type = this.#getMethodType(modifiedMethod);
|
||||
return modifiedMethod;
|
||||
});
|
||||
methodsWithType.forEach((method) => {
|
||||
this.methods.set(method.path, method);
|
||||
});
|
||||
return methodsWithType;
|
||||
} catch (error) {
|
||||
console.error('Error in gRPC reflection:', error);
|
||||
@@ -615,9 +641,6 @@ class GrpcClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load methods from proto file
|
||||
*/
|
||||
async loadMethodsFromProtoFile(filePath, includeDirs = []) {
|
||||
const protoDefinition = await protoLoader.load(filePath, { ...configOptions, includeDirs });
|
||||
const methods = Object.values(protoDefinition)
|
||||
|
||||
Reference in New Issue
Block a user