Socket
Socket
Sign inDemoInstall

@grpc/grpc-js

Package Overview
Dependencies
Maintainers
3
Versions
178
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@grpc/grpc-js - npm Package Compare versions

Comparing version 1.0.3 to 1.0.4

17

build/src/call-credentials.d.ts

@@ -6,2 +6,13 @@ import { Metadata } from './metadata';

export declare type CallMetadataGenerator = (options: CallMetadataOptions, cb: (err: Error | null, metadata?: Metadata) => void) => void;
export interface OldOAuth2Client {
getRequestMetadata: (url: string, callback: (err: Error | null, headers?: {
[index: string]: string;
}) => void) => void;
}
export interface CurrentOAuth2Client {
getRequestHeaders: (url?: string) => Promise<{
[index: string]: string;
}>;
}
export declare type OAuth2Client = OldOAuth2Client | CurrentOAuth2Client;
/**

@@ -39,3 +50,9 @@ * A class that represents a generic method of adding authentication-related

static createFromMetadataGenerator(metadataGenerator: CallMetadataGenerator): CallCredentials;
/**
* Create a gRPC credential from a Google credential object.
* @param googleCredentials The authentication client to use.
* @return The resulting CallCredentials object.
*/
static createFromGoogleCredential(googleCredentials: OAuth2Client): CallCredentials;
static createEmpty(): CallCredentials;
}

@@ -20,2 +20,6 @@ "use strict";

const metadata_1 = require("./metadata");
function isCurrentOauth2Client(client) {
return ('getRequestHeaders' in client &&
typeof client.getRequestHeaders === 'function');
}
/**

@@ -36,2 +40,35 @@ * A class that represents a generic method of adding authentication-related

}
/**
* Create a gRPC credential from a Google credential object.
* @param googleCredentials The authentication client to use.
* @return The resulting CallCredentials object.
*/
static createFromGoogleCredential(googleCredentials) {
return CallCredentials.createFromMetadataGenerator((options, callback) => {
let getHeaders;
if (isCurrentOauth2Client(googleCredentials)) {
getHeaders = googleCredentials.getRequestHeaders(options.service_url);
}
else {
getHeaders = new Promise((resolve, reject) => {
googleCredentials.getRequestMetadata(options.service_url, (err, headers) => {
if (err) {
reject(err);
return;
}
resolve(headers);
});
});
}
getHeaders.then((headers) => {
const metadata = new metadata_1.Metadata();
for (const key of Object.keys(headers)) {
metadata.add(key, headers[key]);
}
callback(null, metadata);
}, (err) => {
callback(err);
});
});
}
static createEmpty() {

@@ -38,0 +75,0 @@ return new EmptyCallCredentials();

4

build/src/call-stream.d.ts

@@ -5,3 +5,3 @@ /// <reference types="node" />

import { Status } from './constants';
import { Filter } from './filter';
import { Filter, FilterFactory } from './filter';
import { FilterStackFactory } from './filter-stack';

@@ -133,3 +133,3 @@ import { Metadata } from './metadata';

private handleTrailers;
attachHttp2Stream(stream: http2.ClientHttp2Stream, subchannel: Subchannel): void;
attachHttp2Stream(stream: http2.ClientHttp2Stream, subchannel: Subchannel, extraFilterFactory?: FilterFactory<Filter>): void;
start(metadata: Metadata, listener: InterceptingListener): void;

@@ -136,0 +136,0 @@ private destroyHttp2Stream;

@@ -21,2 +21,3 @@ "use strict";

const constants_1 = require("./constants");
const filter_stack_1 = require("./filter-stack");
const metadata_1 = require("./metadata");

@@ -268,3 +269,9 @@ const stream_decoder_1 = require("./stream-decoder");

}
attachHttp2Stream(stream, subchannel) {
attachHttp2Stream(stream, subchannel, extraFilterFactory) {
if (extraFilterFactory !== undefined) {
this.filterStack = new filter_stack_1.FilterStack([
this.filterStack,
extraFilterFactory.createFilter(this),
]);
}
if (this.finalStatus !== null) {

@@ -271,0 +278,0 @@ stream.close(NGHTTP2_CANCEL);

@@ -80,1 +80,2 @@ /// <reference types="node" />

}
export declare function createGoogleDefaultCredentials(): ChannelCredentials;

@@ -177,2 +177,10 @@ "use strict";

}
function createGoogleDefaultCredentials() {
const GoogleAuth = require('google-auth-library')
.GoogleAuth;
const sslCreds = ChannelCredentials.createSsl();
const googleAuthCreds = call_credentials_1.CallCredentials.createFromGoogleCredential(new GoogleAuth());
return sslCreds.compose(googleAuthCreds);
}
exports.createGoogleDefaultCredentials = createGoogleDefaultCredentials;
//# sourceMappingURL=channel-credentials.js.map

@@ -171,6 +171,10 @@ "use strict";

.then((finalMetadata) => {
var _a, _b;
const subchannelState = pickResult.subchannel.getConnectivityState();
if (subchannelState === ConnectivityState.READY) {
try {
pickResult.subchannel.startCallStream(finalMetadata, callStream);
pickResult.subchannel.startCallStream(finalMetadata, callStream, (_a = pickResult.extraFilterFactory) !== null && _a !== void 0 ? _a : undefined);
/* If we reach this point, the call stream has started
* successfully */
(_b = pickResult.onCallStarted) === null || _b === void 0 ? void 0 : _b.call(pickResult);
}

@@ -177,0 +181,0 @@ catch (error) {

@@ -267,3 +267,3 @@ "use strict";

catch (e) {
this.call.cancelWithStatus(constants_1.Status.INTERNAL, 'Serialization failure');
this.call.cancelWithStatus(constants_1.Status.INTERNAL, `Request message serialization failure: ${e.message}`);
}

@@ -293,3 +293,3 @@ }

code: constants_1.Status.INTERNAL,
details: 'Failed to parse server response',
details: `Response message parsing error: ${e.message}`,
metadata: new metadata_1.Metadata(),

@@ -296,0 +296,0 @@ };

/// <reference types="node" />
import { ClientDuplexStream, ClientReadableStream, ClientUnaryCall, ClientWritableStream, ServiceError } from './call';
import { CallCredentials } from './call-credentials';
import { CallCredentials, OAuth2Client } from './call-credentials';
import { Deadline, StatusObject } from './call-stream';

@@ -15,10 +15,3 @@ import { Channel, ConnectivityState, ChannelImplementation } from './channel';

import { handleBidiStreamingCall, handleServerStreamingCall, handleUnaryCall, sendUnaryData, ServerUnaryCall, ServerReadableStream, ServerWritableStream, ServerDuplexStream } from './server-call';
export interface OAuth2Client {
getRequestMetadata: (url: string, callback: (err: Error | null, headers?: {
[index: string]: string;
}) => void) => void;
getRequestHeaders: (url?: string) => Promise<{
[index: string]: string;
}>;
}
export { OAuth2Client };
/**** Client Credentials ****/

@@ -33,3 +26,3 @@ export declare const credentials: {

/**** Client ****/
export { Client, loadPackageDefinition, makeClientConstructor, makeClientConstructor as makeGenericClientConstructor, CallProperties, CallInvocationTransformer, ChannelImplementation as Channel, Channel as ChannelInterface, UnaryCallback as requestCallback };
export { Client, loadPackageDefinition, makeClientConstructor, makeClientConstructor as makeGenericClientConstructor, CallProperties, CallInvocationTransformer, ChannelImplementation as Channel, Channel as ChannelInterface, UnaryCallback as requestCallback, };
/**

@@ -36,0 +29,0 @@ * Close a Client object.

@@ -65,37 +65,2 @@ "use strict";

/**
* Create a gRPC credential from a Google credential object.
* @param googleCredentials The authentication client to use.
* @return The resulting CallCredentials object.
*/
createFromGoogleCredential: (googleCredentials) => {
return call_credentials_1.CallCredentials.createFromMetadataGenerator((options, callback) => {
// google-auth-library pre-v2.0.0 does not have getRequestHeaders
// but has getRequestMetadata, which is deprecated in v2.0.0
let getHeaders;
if (typeof googleCredentials.getRequestHeaders === 'function') {
getHeaders = googleCredentials.getRequestHeaders(options.service_url);
}
else {
getHeaders = new Promise((resolve, reject) => {
googleCredentials.getRequestMetadata(options.service_url, (err, headers) => {
if (err) {
reject(err);
return;
}
resolve(headers);
});
});
}
getHeaders.then((headers) => {
const metadata = new metadata_1.Metadata();
for (const key of Object.keys(headers)) {
metadata.add(key, headers[key]);
}
callback(null, metadata);
}, (err) => {
callback(err);
});
});
},
/**
* Combine a ChannelCredentials with any number of CallCredentials into a

@@ -102,0 +67,0 @@ * single ChannelCredentials object.

@@ -48,2 +48,4 @@ "use strict";

status: null,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -87,3 +89,2 @@ }

this.triedAllSubchannels = false;
this.updateState(channel_1.ConnectivityState.IDLE, new picker_1.QueuePicker(this));
this.subchannelStateCounts = {

@@ -119,2 +120,4 @@ [channel_1.ConnectivityState.CONNECTING]: 0,

this.resetSubchannelList();
this.updateState(channel_1.ConnectivityState.IDLE, new picker_1.QueuePicker(this));
return;
}

@@ -121,0 +124,0 @@ if (this.currentPick === null) {

@@ -42,2 +42,4 @@ "use strict";

status: null,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -60,3 +62,2 @@ }

this.currentReadyPicker = null;
this.updateState(channel_1.ConnectivityState.IDLE, new picker_1.QueuePicker(this));
this.subchannelStateCounts = {

@@ -63,0 +64,0 @@ [channel_1.ConnectivityState.CONNECTING]: 0,

@@ -44,3 +44,5 @@ import { ChannelOptions } from './channel-options';

*/
updateAddressList(addressList: SubchannelAddress[], lbConfig: LoadBalancingConfig | null): void;
updateAddressList(addressList: SubchannelAddress[], lbConfig: LoadBalancingConfig | null, attributes: {
[key: string]: unknown;
}): void;
/**

@@ -47,0 +49,0 @@ * If the load balancer is currently in the IDLE state, start connecting.

@@ -236,8 +236,3 @@ "use strict";

else if (values !== undefined) {
if (isCustomMetadata(key)) {
values.split(',').forEach((v) => result.add(key, v.trim()));
}
else {
result.add(key, values);
}
result.add(key, values);
}

@@ -244,0 +239,0 @@ }

@@ -5,2 +5,3 @@ import { Subchannel } from './subchannel';

import { LoadBalancer } from './load-balancer';
import { FilterFactory, Filter } from './filter';
export declare enum PickResultType {

@@ -24,2 +25,9 @@ COMPLETE = 0,

status: StatusObject | null;
/**
* Extra FilterFactory (can be multiple encapsulated in a FilterStackFactory)
* provided by the load balancer to be used with the call. For technical
* reasons filters from this factory will not see sendMetadata events.
*/
extraFilterFactory: FilterFactory<Filter> | null;
onCallStarted: (() => void) | null;
}

@@ -30,2 +38,4 @@ export interface CompletePickResult extends PickResult {

status: null;
extraFilterFactory: FilterFactory<Filter> | null;
onCallStarted: (() => void) | null;
}

@@ -36,2 +46,4 @@ export interface QueuePickResult extends PickResult {

status: null;
extraFilterFactory: null;
onCallStarted: null;
}

@@ -42,2 +54,4 @@ export interface TransientFailurePickResult extends PickResult {

status: StatusObject;
extraFilterFactory: null;
onCallStarted: null;
}

@@ -44,0 +58,0 @@ export interface PickArgs {

@@ -49,2 +49,4 @@ "use strict";

status: this.status,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -78,2 +80,4 @@ }

status: null,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -80,0 +84,0 @@ }

@@ -106,3 +106,3 @@ "use strict";

setImmediate(() => {
this.listener.onSuccessfulResolution(this.ipResult, null, null);
this.listener.onSuccessfulResolution(this.ipResult, null, null, {});
});

@@ -156,3 +156,3 @@ return;

* can update the service config by using the same address list */
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError);
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError, {});
}, (err) => {

@@ -190,3 +190,3 @@ trace('Resolution error for target ' +

* should result in a fast and seamless switchover. */
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError);
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError, {});
}

@@ -200,3 +200,3 @@ }, (err) => {

if (this.latestLookupResult !== null) {
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError);
this.listener.onSuccessfulResolution(this.latestLookupResult, this.latestServiceConfig, this.latestServiceConfigError, {});
}

@@ -203,0 +203,0 @@ });

@@ -33,3 +33,3 @@ "use strict";

updateResolution() {
process.nextTick(this.listener.onSuccessfulResolution, this.addresses, null, null);
process.nextTick(this.listener.onSuccessfulResolution, this.addresses, null, null, {});
}

@@ -36,0 +36,0 @@ static getDefaultAuthority(target) {

@@ -19,3 +19,5 @@ import { ServiceConfig } from './service-config';

*/
onSuccessfulResolution(addressList: SubchannelAddress[], serviceConfig: ServiceConfig | null, serviceConfigError: StatusObject | null): void;
onSuccessfulResolution(addressList: SubchannelAddress[], serviceConfig: ServiceConfig | null, serviceConfigError: StatusObject | null, attributes: {
[key: string]: unknown;
}): void;
/**

@@ -22,0 +24,0 @@ * Called whenever a name resolution attempt fails.

@@ -79,3 +79,3 @@ "use strict";

authority: undefined,
path: uri_parser_1.uriToString(target)
path: uri_parser_1.uriToString(target),
};

@@ -82,0 +82,0 @@ }

@@ -99,3 +99,3 @@ "use strict";

this.innerResolver = resolver_1.createResolver(target, {
onSuccessfulResolution: (addressList, serviceConfig, serviceConfigError) => {
onSuccessfulResolution: (addressList, serviceConfig, serviceConfigError, attributes) => {
let workingServiceConfig = null;

@@ -171,6 +171,6 @@ /* This first group of conditionals implements the algorithm described

this.innerLoadBalancer = load_balancer_1.createLoadBalancer(loadBalancerName, this.innerChannelControlHelper);
this.innerLoadBalancer.updateAddressList(addressList, loadBalancingConfig);
this.innerLoadBalancer.updateAddressList(addressList, loadBalancingConfig, attributes);
}
else if (this.innerLoadBalancer.getTypeName() === loadBalancerName) {
this.innerLoadBalancer.updateAddressList(addressList, loadBalancingConfig);
this.innerLoadBalancer.updateAddressList(addressList, loadBalancingConfig, attributes);
}

@@ -186,3 +186,3 @@ else {

}
this.pendingReplacementLoadBalancer.updateAddressList(addressList, loadBalancingConfig);
this.pendingReplacementLoadBalancer.updateAddressList(addressList, loadBalancingConfig, attributes);
}

@@ -189,0 +189,0 @@ },

@@ -81,2 +81,3 @@ /// <reference types="node" />

type: HandlerType;
path: string;
}

@@ -88,2 +89,3 @@ export interface ClientStreamingHandler<RequestType, ResponseType> {

type: HandlerType;
path: string;
}

@@ -95,2 +97,3 @@ export interface ServerStreamingHandler<RequestType, ResponseType> {

type: HandlerType;
path: string;
}

@@ -102,2 +105,3 @@ export interface BidiStreamingHandler<RequestType, ResponseType> {

type: HandlerType;
path: string;
}

@@ -104,0 +108,0 @@ export declare type Handler<RequestType, ResponseType> = UnaryHandler<RequestType, ResponseType> | ClientStreamingHandler<RequestType, ResponseType> | ServerStreamingHandler<RequestType, ResponseType> | BidiStreamingHandler<RequestType, ResponseType>;

@@ -25,2 +25,7 @@ "use strict";

const stream_decoder_1 = require("./stream-decoder");
const logging = require("./logging");
const TRACER_NAME = 'server_call';
function trace(text) {
logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, text);
}
const GRPC_ACCEPT_ENCODING_HEADER = 'grpc-accept-encoding';

@@ -273,6 +278,7 @@ const GRPC_ENCODING_HEADER = 'grpc-encoding';

const requestBytes = Buffer.concat(chunks, totalLength);
if (this.maxReceiveMessageSize !== -1 && requestBytes.length > this.maxReceiveMessageSize) {
if (this.maxReceiveMessageSize !== -1 &&
requestBytes.length > this.maxReceiveMessageSize) {
this.sendError({
code: constants_1.Status.RESOURCE_EXHAUSTED,
details: `Received message larger than max (${requestBytes.length} vs. ${this.maxReceiveMessageSize})`
details: `Received message larger than max (${requestBytes.length} vs. ${this.maxReceiveMessageSize})`,
});

@@ -331,5 +337,11 @@ resolve();

sendStatus(statusObj) {
var _a;
if (this.checkCancelled()) {
return;
}
trace('Request to method ' + ((_a = this.handler) === null || _a === void 0 ? void 0 : _a.path) +
' ended with status code: ' +
constants_1.Status[statusObj.code] +
' details: ' +
statusObj.details);
clearTimeout(this.deadline);

@@ -374,6 +386,7 @@ if (!this.wantTrailers) {

}
if (this.maxSendMessageSize !== -1 && chunk.length > this.maxSendMessageSize) {
if (this.maxSendMessageSize !== -1 &&
chunk.length > this.maxSendMessageSize) {
this.sendError({
code: constants_1.Status.RESOURCE_EXHAUSTED,
details: `Sent message larger than max (${chunk.length} vs. ${this.maxSendMessageSize})`
details: `Sent message larger than max (${chunk.length} vs. ${this.maxSendMessageSize})`,
});

@@ -399,6 +412,7 @@ return;

for (const message of messages) {
if (this.maxReceiveMessageSize !== -1 && message.length > this.maxReceiveMessageSize) {
if (this.maxReceiveMessageSize !== -1 &&
message.length > this.maxReceiveMessageSize) {
this.sendError({
code: constants_1.Status.RESOURCE_EXHAUSTED,
details: `Received message larger than max (${message.length} vs. ${this.maxReceiveMessageSize})`
details: `Received message larger than max (${message.length} vs. ${this.maxReceiveMessageSize})`,
});

@@ -405,0 +419,0 @@ return;

@@ -24,5 +24,9 @@ "use strict";

const resolver_1 = require("./resolver");
const logging_1 = require("./logging");
const logging = require("./logging");
const subchannel_1 = require("./subchannel");
const uri_parser_1 = require("./uri-parser");
const TRACER_NAME = 'server';
function trace(text) {
logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, text);
}
function noop() { }

@@ -168,2 +172,3 @@ function getUnimplementedStatusResponse(methodName) {

return Promise.all(addressList.map((address) => {
trace('Attempting to bind ' + subchannel_1.subchannelAddressToString(address));
let addr;

@@ -186,2 +191,3 @@ if (subchannel_1.isTcpSubchannelAddress(address)) {

http2Server.listen(addr, () => {
trace('Successfully bound ' + subchannel_1.subchannelAddressToString(address));
this.http2ServerList.push(http2Server);

@@ -256,3 +262,3 @@ const boundAddress = http2Server.address();

const errorString = `No address added out of total ${addressList.length} resolved`;
logging_1.log(constants_1.LogVerbosity.ERROR, errorString);
logging.log(constants_1.LogVerbosity.ERROR, errorString);
callback(new Error(errorString), 0);

@@ -262,3 +268,3 @@ }

if (bindResult.count < addressList.length) {
logging_1.log(constants_1.LogVerbosity.INFO, `WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved`);
logging.log(constants_1.LogVerbosity.INFO, `WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved`);
}

@@ -269,3 +275,3 @@ callback(null, bindResult.port);

const errorString = `No address added out of total ${addressList.length} resolved`;
logging_1.log(constants_1.LogVerbosity.ERROR, errorString);
logging.log(constants_1.LogVerbosity.ERROR, errorString);
callback(new Error(errorString), 0);

@@ -308,2 +314,3 @@ });

type,
path: name,
});

@@ -355,2 +362,3 @@ return true;

http2Server.on('stream', (stream, headers) => {
var _a;
const contentType = headers[http2.constants.HTTP2_HEADER_CONTENT_TYPE];

@@ -366,4 +374,10 @@ if (typeof contentType !== 'string' ||

const path = headers[http2.constants.HTTP2_HEADER_PATH];
trace('Received call to method ' +
path +
' at address ' + ((_a = http2Server.address()) === null || _a === void 0 ? void 0 : _a.toString()));
const handler = this.handlers.get(path);
if (handler === undefined) {
trace('No handler registered for method ' +
path +
'. Sending UNIMPLEMENTED status.');
throw getUnimplementedStatusResponse(path);

@@ -370,0 +384,0 @@ }

@@ -7,2 +7,3 @@ import { ChannelCredentials } from './channel-credentials';

import { GrpcUri } from './uri-parser';
import { FilterFactory, Filter } from './filter';
export declare type ConnectivityStateListener = (subchannel: Subchannel, previousState: ConnectivityState, newState: ConnectivityState) => void;

@@ -136,3 +137,3 @@ export interface TcpSubchannelAddress {

*/
startCallStream(metadata: Metadata, callStream: Http2CallStream): void;
startCallStream(metadata: Metadata, callStream: Http2CallStream, extraFilterFactory?: FilterFactory<Filter>): void;
/**

@@ -139,0 +140,0 @@ * If the subchannel is currently IDLE, start connecting and switch to the

@@ -453,3 +453,3 @@ "use strict";

*/
startCallStream(metadata, callStream) {
startCallStream(metadata, callStream, extraFilterFactory) {
const headers = metadata.toHttp2Headers();

@@ -468,3 +468,3 @@ headers[HTTP2_HEADER_AUTHORITY] = callStream.getHost();

trace('Starting stream with headers\n' + headersString);
callStream.attachHttp2Stream(http2Stream, this);
callStream.attachHttp2Stream(http2Stream, this, extraFilterFactory);
}

@@ -471,0 +471,0 @@ /**

{
"name": "@grpc/grpc-js",
"version": "1.0.3",
"version": "1.0.4",
"description": "gRPC Library for Node - pure JS implementation",

@@ -36,2 +36,3 @@ "homepage": "https://grpc.io/",

"pify": "^4.0.1",
"rimraf": "^3.0.2",
"ts-node": "^8.3.0",

@@ -47,3 +48,3 @@ "typescript": "^3.7.2"

"build": "npm run compile",
"clean": "gts clean",
"clean": "node -e 'require(\"rimraf\")(\"./build\", () => {})'",
"compile": "tsc -p .",

@@ -60,2 +61,3 @@ "format": "clang-format -i -style=\"{Language: JavaScript, BasedOnStyle: Google, ColumnLimit: 80}\" src/*.ts test/*.ts",

"dependencies": {
"google-auth-library": "^6.0.0",
"semver": "^6.2.0"

@@ -62,0 +64,0 @@ },

@@ -13,22 +13,22 @@ # Pure JavaScript gRPC Client

- Clients
- Automatic reconnection
- Servers
- Streaming
- Metadata
- Partial compression support: clients can decompress response messages
- Pick first and round robin load balancing policies
- Client Interceptors
- Connection Keepalives
- HTTP Connect support (proxies)
- Clients
- Automatic reconnection
- Servers
- Streaming
- Metadata
- Partial compression support: clients can decompress response messages
- Pick first and round robin load balancing policies
- Client Interceptors
- Connection Keepalives
- HTTP Connect support (proxies)
This library does not directly handle `.proto` files. To use `.proto` files with this library we recommend using the `@grpc/proto-loader` package.
## Migrating from [`grpc`](https://www.npmjs.com/package/grpc)
## Migrating from [`grpc`](https://www.npmjs.com/package/grpc)
`@grpc/grpc-js` is almost a drop-in replacement for `grpc`, but you may need to make a few code changes to use it:
`@grpc/grpc-js` is almost a drop-in replacement for `grpc`, but you may need to make a few code changes to use it:
- If you are currently loading `.proto` files using `grpc.load`, that function is not available in this library. You should instead load your `.proto` files using `@grpc/proto-loader` and load the resulting package definition objects into `@grpc/grpc-js` using `grpc.loadPackageDefinition`.
- If you are currently loading packages generated by `grpc-tools`, you should instead generate your files using the `--generate_package_definitions` option in `grpc-tools`, then load the object exported by the generated file into `@grpc/grpc-js` using `grpc.loadPackageDefinition`.
- If you have a server and you are using `Server#bind` to bind ports, you will need to use `Server#bindAsync` instead.
- If you are currently loading `.proto` files using `grpc.load`, that function is not available in this library. You should instead load your `.proto` files using `@grpc/proto-loader` and load the resulting package definition objects into `@grpc/grpc-js` using `grpc.loadPackageDefinition`.
- If you are currently loading packages generated by `grpc-tools`, you should instead generate your files using the `--generate_package_definitions` option in `grpc-tools`, then load the object exported by the generated file into `@grpc/grpc-js` using `grpc.loadPackageDefinition`.
- If you have a server and you are using `Server#bind` to bind ports, you will need to use `Server#bindAsync` instead.

@@ -39,4 +39,4 @@ ## Some Notes on API Guarantees

- Some methods are prefixed with an underscore. These methods are internal and should not be considered part of the public API.
- The class `Call` is only exposed due to limitations of TypeScript. It should not be considered part of the public API.
- In general, any API that is exposed by this library but is not exposed by the `grpc` library is likely an error and should not be considered part of the public API.
- Some methods are prefixed with an underscore. These methods are internal and should not be considered part of the public API.
- The class `Call` is only exposed due to limitations of TypeScript. It should not be considered part of the public API.
- In general, any API that is exposed by this library but is not exposed by the `grpc` library is likely an error and should not be considered part of the public API.

@@ -29,2 +29,31 @@ /*

// google-auth-library pre-v2.0.0 does not have getRequestHeaders
// but has getRequestMetadata, which is deprecated in v2.0.0
export interface OldOAuth2Client {
getRequestMetadata: (
url: string,
callback: (
err: Error | null,
headers?: {
[index: string]: string;
}
) => void
) => void;
}
export interface CurrentOAuth2Client {
getRequestHeaders: (url?: string) => Promise<{ [index: string]: string }>;
}
export type OAuth2Client = OldOAuth2Client | CurrentOAuth2Client;
function isCurrentOauth2Client(
client: OAuth2Client
): client is CurrentOAuth2Client {
return (
'getRequestHeaders' in client &&
typeof client.getRequestHeaders === 'function'
);
}
/**

@@ -69,2 +98,43 @@ * A class that represents a generic method of adding authentication-related

/**
* Create a gRPC credential from a Google credential object.
* @param googleCredentials The authentication client to use.
* @return The resulting CallCredentials object.
*/
static createFromGoogleCredential(
googleCredentials: OAuth2Client
): CallCredentials {
return CallCredentials.createFromMetadataGenerator((options, callback) => {
let getHeaders: Promise<{ [index: string]: string }>;
if (isCurrentOauth2Client(googleCredentials)) {
getHeaders = googleCredentials.getRequestHeaders(options.service_url);
} else {
getHeaders = new Promise((resolve, reject) => {
googleCredentials.getRequestMetadata(
options.service_url,
(err, headers) => {
if (err) {
reject(err);
return;
}
resolve(headers);
}
);
});
}
getHeaders.then(
(headers) => {
const metadata = new Metadata();
for (const key of Object.keys(headers)) {
metadata.add(key, headers[key]);
}
callback(null, metadata);
},
(err) => {
callback(err);
}
);
});
}
static createEmpty(): CallCredentials {

@@ -71,0 +141,0 @@ return new EmptyCallCredentials();

@@ -22,4 +22,4 @@ /*

import { Status } from './constants';
import { Filter } from './filter';
import { FilterStackFactory } from './filter-stack';
import { Filter, FilterFactory } from './filter';
import { FilterStackFactory, FilterStack } from './filter-stack';
import { Metadata } from './metadata';

@@ -411,4 +411,11 @@ import { StreamDecoder } from './stream-decoder';

stream: http2.ClientHttp2Stream,
subchannel: Subchannel
subchannel: Subchannel,
extraFilterFactory?: FilterFactory<Filter>
): void {
if (extraFilterFactory !== undefined) {
this.filterStack = new FilterStack([
this.filterStack,
extraFilterFactory.createFilter(this),
]);
}
if (this.finalStatus !== null) {

@@ -415,0 +422,0 @@ stream.close(NGHTTP2_CANCEL);

@@ -22,2 +22,3 @@ /*

import { CIPHER_SUITES, getDefaultRootsData } from './tls-helpers';
import { GoogleAuth as GoogleAuthType } from 'google-auth-library';

@@ -282,1 +283,11 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any

}
export function createGoogleDefaultCredentials(): ChannelCredentials {
const GoogleAuth = require('google-auth-library')
.GoogleAuth as typeof GoogleAuthType;
const sslCreds = ChannelCredentials.createSsl();
const googleAuthCreds = CallCredentials.createFromGoogleCredential(
new GoogleAuth()
);
return sslCreds.compose(googleAuthCreds);
}

@@ -177,3 +177,5 @@ /*

if (defaultSchemeMapResult === null) {
throw new Error(`Could not find a default scheme for target name "${target}"`);
throw new Error(
`Could not find a default scheme for target name "${target}"`
);
}

@@ -304,4 +306,8 @@ if (this.options['grpc.default_authority']) {

finalMetadata,
callStream
callStream,
pickResult.extraFilterFactory ?? undefined
);
/* If we reach this point, the call stream has started
* successfully */
pickResult.onCallStarted?.();
} catch (error) {

@@ -308,0 +314,0 @@ if (

@@ -362,3 +362,3 @@ /*

} catch (e) {
this.call.cancelWithStatus(Status.INTERNAL, 'Serialization failure');
this.call.cancelWithStatus(Status.INTERNAL, `Request message serialization failure: ${e.message}`);
}

@@ -388,3 +388,3 @@ }

code: Status.INTERNAL,
details: 'Failed to parse server response',
details: `Response message parsing error: ${e.message}`,
metadata: new Metadata(),

@@ -391,0 +391,0 @@ };

@@ -27,3 +27,3 @@ /*

} from './call';
import { CallCredentials } from './call-credentials';
import { CallCredentials, OAuth2Client } from './call-credentials';
import { Deadline, StatusObject } from './call-stream';

@@ -37,3 +37,3 @@ import { Channel, ConnectivityState, ChannelImplementation } from './channel';

CallProperties,
UnaryCallback
UnaryCallback,
} from './client';

@@ -92,14 +92,3 @@ import { LogVerbosity, Status } from './constants';

export interface OAuth2Client {
getRequestMetadata: (
url: string,
callback: (
err: Error | null,
headers?: {
[index: string]: string;
}
) => void
) => void;
getRequestHeaders: (url?: string) => Promise<{ [index: string]: string }>;
}
export { OAuth2Client };

@@ -112,49 +101,2 @@ /**** Client Credentials ****/

/**
* Create a gRPC credential from a Google credential object.
* @param googleCredentials The authentication client to use.
* @return The resulting CallCredentials object.
*/
createFromGoogleCredential: (
googleCredentials: OAuth2Client
): CallCredentials => {
return CallCredentials.createFromMetadataGenerator(
(options, callback) => {
// google-auth-library pre-v2.0.0 does not have getRequestHeaders
// but has getRequestMetadata, which is deprecated in v2.0.0
let getHeaders: Promise<{ [index: string]: string }>;
if (typeof googleCredentials.getRequestHeaders === 'function') {
getHeaders = googleCredentials.getRequestHeaders(
options.service_url
);
} else {
getHeaders = new Promise((resolve, reject) => {
googleCredentials.getRequestMetadata(
options.service_url,
(err, headers) => {
if (err) {
reject(err);
return;
}
resolve(headers);
}
);
});
}
getHeaders.then(
(headers) => {
const metadata = new Metadata();
for (const key of Object.keys(headers)) {
metadata.add(key, headers[key]);
}
callback(null, metadata);
},
(err) => {
callback(err);
}
);
}
);
},
/**
* Combine a ChannelCredentials with any number of CallCredentials into a

@@ -218,3 +160,3 @@ * single ChannelCredentials object.

Channel as ChannelInterface,
UnaryCallback as requestCallback
UnaryCallback as requestCallback,
};

@@ -221,0 +163,0 @@

@@ -68,2 +68,4 @@ /*

status: null,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -132,3 +134,2 @@ }

constructor(private channelControlHelper: ChannelControlHelper) {
this.updateState(ConnectivityState.IDLE, new QueuePicker(this));
this.subchannelStateCounts = {

@@ -171,2 +172,4 @@ [ConnectivityState.CONNECTING]: 0,

this.resetSubchannelList();
this.updateState(ConnectivityState.IDLE, new QueuePicker(this));
return;
}

@@ -173,0 +176,0 @@ if (this.currentPick === null) {

@@ -63,2 +63,4 @@ /*

status: null,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -97,3 +99,2 @@ }

constructor(private channelControlHelper: ChannelControlHelper) {
this.updateState(ConnectivityState.IDLE, new QueuePicker(this));
this.subchannelStateCounts = {

@@ -100,0 +101,0 @@ [ConnectivityState.CONNECTING]: 0,

@@ -70,3 +70,4 @@ /*

addressList: SubchannelAddress[],
lbConfig: LoadBalancingConfig | null
lbConfig: LoadBalancingConfig | null,
attributes: { [key: string]: unknown }
): void;

@@ -73,0 +74,0 @@ /**

@@ -281,7 +281,3 @@ /*

} else if (values !== undefined) {
if (isCustomMetadata(key)) {
values.split(',').forEach((v) => result.add(key, v.trim()));
} else {
result.add(key, values);
}
result.add(key, values);
}

@@ -288,0 +284,0 @@ }

@@ -23,2 +23,3 @@ /*

import { LoadBalancer } from './load-balancer';
import { FilterFactory, Filter } from './filter';

@@ -44,2 +45,9 @@ export enum PickResultType {

status: StatusObject | null;
/**
* Extra FilterFactory (can be multiple encapsulated in a FilterStackFactory)
* provided by the load balancer to be used with the call. For technical
* reasons filters from this factory will not see sendMetadata events.
*/
extraFilterFactory: FilterFactory<Filter> | null;
onCallStarted: (() => void) | null;
}

@@ -51,2 +59,4 @@

status: null;
extraFilterFactory: FilterFactory<Filter> | null;
onCallStarted: (() => void) | null;
}

@@ -58,2 +68,4 @@

status: null;
extraFilterFactory: null;
onCallStarted: null;
}

@@ -65,2 +77,4 @@

status: StatusObject;
extraFilterFactory: null;
onCallStarted: null;
}

@@ -103,2 +117,4 @@

status: this.status,
extraFilterFactory: null,
onCallStarted: null,
};

@@ -131,4 +147,6 @@ }

status: null,
extraFilterFactory: null,
onCallStarted: null,
};
}
}

@@ -127,3 +127,3 @@ /*

setImmediate(() => {
this.listener.onSuccessfulResolution(this.ipResult!, null, null);
this.listener.onSuccessfulResolution(this.ipResult!, null, null, {});
});

@@ -190,3 +190,4 @@ return;

this.latestServiceConfig,
this.latestServiceConfigError
this.latestServiceConfigError,
{}
);

@@ -235,3 +236,4 @@ },

this.latestServiceConfig,
this.latestServiceConfigError
this.latestServiceConfigError,
{}
);

@@ -250,3 +252,4 @@ }

this.latestServiceConfig,
this.latestServiceConfigError
this.latestServiceConfigError,
{}
);

@@ -253,0 +256,0 @@ }

@@ -17,7 +17,3 @@ /*

import {
Resolver,
ResolverListener,
registerResolver,
} from './resolver';
import { Resolver, ResolverListener, registerResolver } from './resolver';
import { SubchannelAddress } from './subchannel';

@@ -42,3 +38,4 @@ import { GrpcUri } from './uri-parser';

null,
null
null,
{}
);

@@ -45,0 +42,0 @@ }

@@ -42,3 +42,4 @@ /*

serviceConfig: ServiceConfig | null,
serviceConfigError: StatusObject | null
serviceConfigError: StatusObject | null,
attributes: { [key: string]: unknown }
): void;

@@ -141,3 +142,3 @@ /**

authority: undefined,
path: uriToString(target)
path: uriToString(target),
};

@@ -144,0 +145,0 @@ } else {

@@ -139,3 +139,4 @@ /*

serviceConfig: ServiceConfig | null,
serviceConfigError: ServiceError | null
serviceConfigError: ServiceError | null,
attributes: { [key: string]: unknown }
) => {

@@ -215,3 +216,4 @@ let workingServiceConfig: ServiceConfig | null = null;

addressList,
loadBalancingConfig
loadBalancingConfig,
attributes
);

@@ -221,3 +223,4 @@ } else if (this.innerLoadBalancer.getTypeName() === loadBalancerName) {

addressList,
loadBalancingConfig
loadBalancingConfig,
attributes
);

@@ -240,3 +243,4 @@ } else {

addressList,
loadBalancingConfig
loadBalancingConfig,
attributes
);

@@ -243,0 +247,0 @@ }

@@ -23,3 +23,8 @@ /*

import { StatusObject } from './call-stream';
import { Status, DEFAULT_MAX_SEND_MESSAGE_LENGTH, DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH } from './constants';
import {
Status,
DEFAULT_MAX_SEND_MESSAGE_LENGTH,
DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH,
LogVerbosity,
} from './constants';
import { Deserialize, Serialize } from './make-client';

@@ -30,3 +35,10 @@ import { Metadata } from './metadata';

import { ChannelOptions } from './channel-options';
import * as logging from './logging';
const TRACER_NAME = 'server_call';
function trace(text: string): void {
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text);
}
interface DeadlineUnitIndexSignature {

@@ -68,3 +80,3 @@ [name: string]: number;

cancelled: boolean;
readonly metadata: Metadata
readonly metadata: Metadata;
getPeer(): string;

@@ -300,2 +312,3 @@ sendMetadata(responseMetadata: Metadata): void;

type: HandlerType;
path: string;
}

@@ -308,2 +321,3 @@

type: HandlerType;
path: string;
}

@@ -316,2 +330,3 @@

type: HandlerType;
path: string;
}

@@ -324,2 +339,3 @@

type: HandlerType;
path: string;
}

@@ -457,6 +473,9 @@

const requestBytes = Buffer.concat(chunks, totalLength);
if (this.maxReceiveMessageSize !== -1 && requestBytes.length > this.maxReceiveMessageSize) {
if (
this.maxReceiveMessageSize !== -1 &&
requestBytes.length > this.maxReceiveMessageSize
) {
this.sendError({
code: Status.RESOURCE_EXHAUSTED,
details: `Received message larger than max (${requestBytes.length} vs. ${this.maxReceiveMessageSize})`
details: `Received message larger than max (${requestBytes.length} vs. ${this.maxReceiveMessageSize})`,
});

@@ -532,2 +551,11 @@ resolve();

trace(
'Request to method ' +
this.handler?.path +
' ended with status code: ' +
Status[statusObj.code] +
' details: ' +
statusObj.details
);
clearTimeout(this.deadline);

@@ -586,6 +614,9 @@

if (this.maxSendMessageSize !== -1 && chunk.length > this.maxSendMessageSize) {
if (
this.maxSendMessageSize !== -1 &&
chunk.length > this.maxSendMessageSize
) {
this.sendError({
code: Status.RESOURCE_EXHAUSTED,
details: `Sent message larger than max (${chunk.length} vs. ${this.maxSendMessageSize})`
code: Status.RESOURCE_EXHAUSTED,
details: `Sent message larger than max (${chunk.length} vs. ${this.maxSendMessageSize})`,
});

@@ -621,6 +652,9 @@ return;

for (const message of messages) {
if (this.maxReceiveMessageSize !== -1 && message.length > this.maxReceiveMessageSize) {
if (
this.maxReceiveMessageSize !== -1 &&
message.length > this.maxReceiveMessageSize
) {
this.sendError({
code: Status.RESOURCE_EXHAUSTED,
details: `Received message larger than max (${message.length} vs. ${this.maxReceiveMessageSize})`
details: `Received message larger than max (${message.length} vs. ${this.maxReceiveMessageSize})`,
});

@@ -627,0 +661,0 @@ return;

@@ -48,11 +48,22 @@ /*

import { ChannelOptions } from './channel-options';
import { createResolver, ResolverListener, mapUriDefaultScheme } from './resolver';
import { log } from './logging';
import {
createResolver,
ResolverListener,
mapUriDefaultScheme,
} from './resolver';
import * as logging from './logging';
import {
SubchannelAddress,
TcpSubchannelAddress,
isTcpSubchannelAddress,
subchannelAddressToString,
} from './subchannel';
import { parseUri } from './uri-parser';
const TRACER_NAME = 'server';
function trace(text: string): void {
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text);
}
interface BindResult {

@@ -273,2 +284,3 @@ port: number;

addressList.map((address) => {
trace('Attempting to bind ' + subchannelAddressToString(address));
let addr: SubchannelAddress;

@@ -293,2 +305,3 @@ if (isTcpSubchannelAddress(address)) {

http2Server.listen(addr, () => {
trace('Successfully bound ' + subchannelAddressToString(address));
this.http2ServerList.push(http2Server);

@@ -384,7 +397,7 @@ const boundAddress = http2Server.address()!;

const errorString = `No address added out of total ${addressList.length} resolved`;
log(LogVerbosity.ERROR, errorString);
logging.log(LogVerbosity.ERROR, errorString);
callback(new Error(errorString), 0);
} else {
if (bindResult.count < addressList.length) {
log(
logging.log(
LogVerbosity.INFO,

@@ -399,3 +412,3 @@ `WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved`

const errorString = `No address added out of total ${addressList.length} resolved`;
log(LogVerbosity.ERROR, errorString);
logging.log(LogVerbosity.ERROR, errorString);
callback(new Error(errorString), 0);

@@ -452,2 +465,3 @@ }

type,
path: name,
} as UntypedHandler);

@@ -537,5 +551,16 @@ return true;

const path = headers[http2.constants.HTTP2_HEADER_PATH] as string;
trace(
'Received call to method ' +
path +
' at address ' +
http2Server.address()?.toString()
);
const handler = this.handlers.get(path);
if (handler === undefined) {
trace(
'No handler registered for method ' +
path +
'. Sending UNIMPLEMENTED status.'
);
throw getUnimplementedStatusResponse(path);

@@ -542,0 +567,0 @@ }

@@ -33,2 +33,3 @@ /*

import { ConnectionOptions } from 'tls';
import { FilterFactory, Filter } from './filter';

@@ -623,3 +624,7 @@ const clientVersion = require('../../package.json').version;

*/
startCallStream(metadata: Metadata, callStream: Http2CallStream) {
startCallStream(
metadata: Metadata,
callStream: Http2CallStream,
extraFilterFactory?: FilterFactory<Filter>
) {
const headers = metadata.toHttp2Headers();

@@ -638,3 +643,3 @@ headers[HTTP2_HEADER_AUTHORITY] = callStream.getHost();

trace('Starting stream with headers\n' + headersString);
callStream.attachHttp2Stream(http2Stream, this);
callStream.attachHttp2Stream(http2Stream, this, extraFilterFactory);
}

@@ -641,0 +646,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc