@grpc.ts/core
Version:
Core package for @grpc.ts
535 lines (486 loc) • 17.8 kB
JavaScript
;
var tls = require('tls');
var grpcJs = require('@grpc/grpc-js');
var util = require('util');
var protoLoader = require('@grpc/proto-loader');
var require$$0 = require('google-protobuf');
class GrpcTimestamp {
nanos;
seconds;
}
var compressionAlgorithms = {};
var hasRequiredCompressionAlgorithms;
function requireCompressionAlgorithms () {
if (hasRequiredCompressionAlgorithms) return compressionAlgorithms;
hasRequiredCompressionAlgorithms = 1;
/*
* Copyright 2021 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
Object.defineProperty(compressionAlgorithms, "__esModule", { value: true });
compressionAlgorithms.CompressionAlgorithms = void 0;
var CompressionAlgorithms;
(function (CompressionAlgorithms) {
CompressionAlgorithms[CompressionAlgorithms["identity"] = 0] = "identity";
CompressionAlgorithms[CompressionAlgorithms["deflate"] = 1] = "deflate";
CompressionAlgorithms[CompressionAlgorithms["gzip"] = 2] = "gzip";
})(CompressionAlgorithms || (compressionAlgorithms.CompressionAlgorithms = CompressionAlgorithms = {}));
return compressionAlgorithms;
}
var compressionAlgorithmsExports = requireCompressionAlgorithms();
function toSnakeCase(source) {
return source.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
}
function convertChannelOptions({ maxSessionMemory, defaultCompressionAlgorithm, ...options }) {
const opts = Object.entries(options).reduce((result, [key, value]) => {
result[`grpc.${toSnakeCase(key)}`] = value;
return result;
}, {});
return {
...opts,
'grpc-node.max_session_memory': maxSessionMemory,
'grpc.default_compression_algorithm': defaultCompressionAlgorithm
? compressionAlgorithmsExports.CompressionAlgorithms[defaultCompressionAlgorithm]
: undefined,
};
}
function extractPackage(grpcObject, packagePath) {
if (!packagePath) {
return grpcObject;
}
const paths = packagePath.split('.');
let object = grpcObject;
paths.forEach((p) => {
object = object[p];
});
return object;
}
function isGrpcService(obj) {
return (typeof obj == 'function' &&
Object.prototype.hasOwnProperty.call(obj, 'service') &&
Object.prototype.hasOwnProperty.call(obj, 'serviceName'));
}
async function loadPackage({ package: packageInfo, packageDefinitionOptions, }) {
if (!Array.isArray(packageInfo)) {
packageInfo = [packageInfo];
}
const packageDefinitions = await Promise.all(packageInfo.map(async ({ protoPath }) => {
return protoLoader.load(protoPath, packageDefinitionOptions);
}));
const packages = packageInfo; // to fix typescript typing for the code below
return packageDefinitions.reduce((result, packageDef, index) => {
const packageObject = grpcJs.loadPackageDefinition(packageDef);
const { packageName = '' } = packages[index];
const rawPackage = extractPackage(packageObject, packageName);
const packageServices = {
...result[packageName],
};
Object.entries(rawPackage).forEach(([k, v]) => {
if (!isGrpcService(v)) {
return;
}
packageServices[k] = v;
});
Object.assign(result, {
[packageName]: packageServices,
});
return result;
}, {});
}
function makeServiceClients({ url, options, packageDefs, credentials, }) {
const channelOptions = convertChannelOptions(options);
return Object.entries(packageDefs).reduce((result, [packageName, packageServices]) => {
const clientServices = Object.entries(packageServices).reduce((services, [serviceName, serviceClient]) => {
const client = new serviceClient(url, credentials, channelOptions);
services[serviceName] = client;
const methodNames = Object.keys(Object.getPrototypeOf(client)).filter((propertyName) => typeof client[propertyName] === 'function');
methodNames.forEach((methodName) => {
client[methodName] = util.promisify(client[methodName].bind(client));
});
return services;
}, {});
result[packageName] = clientServices;
return result;
}, {});
}
async function createClient({ url, options = {}, credentials: creds, package: packageInfo, packageDefinitionOptions, }) {
const packageDefs = await loadPackage({
package: packageInfo,
packageDefinitionOptions,
});
const clients = makeServiceClients({
url,
options,
packageDefs,
credentials: creds || grpcJs.credentials.createInsecure(),
});
const getService = (serviceName, options = {}) => {
const { packageName = '' } = options;
return clients[packageName]?.[serviceName]; // TODO: fix type
};
const close = () => {
Object.values(clients).forEach((client) => {
Object.values(client).forEach((sc) => {
sc.close();
});
});
};
const getPackages = () => {
return clients;
};
return {
close,
getService,
getPackages,
};
}
const serviceMethodTracking = {};
async function createServer({ url, options = {}, credentials: creds, package: packageInfo, packageDefinitionOptions, }) {
const packageDefs = await loadPackage({
package: packageInfo,
packageDefinitionOptions,
});
const server = new grpcJs.Server(convertChannelOptions(options));
const bindAsync = util.promisify(server.bindAsync.bind(server));
await bindAsync(url, creds || grpcJs.ServerCredentials.createInsecure());
const addUnaryHandler = (serviceName, rpcName, impl, opts = {}) => {
const { package: packageName = '' } = opts;
const pkg = packageDefs[packageName];
const { service } = pkg?.[serviceName] || {};
if (!service) {
throw `Cannot find service ${serviceName}`;
}
const key = `${packageName}::${serviceName}::${rpcName}`;
if (serviceMethodTracking[key]) {
return;
}
else {
serviceMethodTracking[key] = true;
}
const subName = rpcName.substring(1);
const rpcNameUpper = rpcName[0].toUpperCase() + subName;
const rpcNameLower = rpcName[0].toLowerCase() + subName;
if (!Object.prototype.hasOwnProperty.call(service, rpcNameLower) &&
!Object.prototype.hasOwnProperty.call(service, rpcNameUpper)) {
throw `${serviceName} service does not have ${rpcName} rpc method`;
}
const implFunc = async (call, callback) => {
let alreadyCalled = false;
const hofCallback = (err, value) => {
alreadyCalled = true;
callback(err, value);
};
const result = await impl(call.request, call.metadata, call, hofCallback);
if (alreadyCalled) {
return;
}
callback(null, result);
};
const attrs = service[rpcNameLower] || service[rpcNameUpper];
server.register(attrs.path, implFunc, attrs.responseSerialize, attrs.requestDeserialize, 'unary');
};
return {
server,
addUnaryHandler,
};
}
var timestamp_pb = {};
var hasRequiredTimestamp_pb;
function requireTimestamp_pb () {
if (hasRequiredTimestamp_pb) return timestamp_pb;
hasRequiredTimestamp_pb = 1;
(function (exports) {
// source: google/protobuf/timestamp.proto
/**
* @fileoverview
* @enhanceable
* @suppress {missingRequire} reports error on implicit type usages.
* @suppress {messageConventions} JS Compiler reports an error if a variable or
* field starts with 'MSG_' and isn't a translatable message.
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
/* eslint-disable */
// @ts-nocheck
var jspb = require$$0;
var goog = jspb;
var global =
(typeof globalThis !== 'undefined' && globalThis) ||
(typeof window !== 'undefined' && window) ||
(typeof global !== 'undefined' && global) ||
(typeof self !== 'undefined' && self) ||
(function () { return this; }).call(null) ||
Function('return this')();
goog.exportSymbol('proto.google.protobuf.Timestamp', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.google.protobuf.Timestamp = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.google.protobuf.Timestamp, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.google.protobuf.Timestamp.displayName = 'proto.google.protobuf.Timestamp';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.google.protobuf.Timestamp.prototype.toObject = function(opt_includeInstance) {
return proto.google.protobuf.Timestamp.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.google.protobuf.Timestamp} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.google.protobuf.Timestamp.toObject = function(includeInstance, msg) {
var obj = {
seconds: jspb.Message.getFieldWithDefault(msg, 1, 0),
nanos: jspb.Message.getFieldWithDefault(msg, 2, 0)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.google.protobuf.Timestamp}
*/
proto.google.protobuf.Timestamp.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.google.protobuf.Timestamp;
return proto.google.protobuf.Timestamp.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.google.protobuf.Timestamp} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.google.protobuf.Timestamp}
*/
proto.google.protobuf.Timestamp.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setSeconds(value);
break;
case 2:
var value = /** @type {number} */ (reader.readInt32());
msg.setNanos(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.google.protobuf.Timestamp.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.google.protobuf.Timestamp.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.google.protobuf.Timestamp} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.google.protobuf.Timestamp.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getSeconds();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
f = message.getNanos();
if (f !== 0) {
writer.writeInt32(
2,
f
);
}
};
/**
* optional int64 seconds = 1;
* @return {number}
*/
proto.google.protobuf.Timestamp.prototype.getSeconds = function() {
return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
};
/**
* @param {number} value
* @return {!proto.google.protobuf.Timestamp} returns this
*/
proto.google.protobuf.Timestamp.prototype.setSeconds = function(value) {
return jspb.Message.setProto3IntField(this, 1, value);
};
/**
* optional int32 nanos = 2;
* @return {number}
*/
proto.google.protobuf.Timestamp.prototype.getNanos = function() {
return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
};
/**
* @param {number} value
* @return {!proto.google.protobuf.Timestamp} returns this
*/
proto.google.protobuf.Timestamp.prototype.setNanos = function(value) {
return jspb.Message.setProto3IntField(this, 2, value);
};
goog.object.extend(exports, proto.google.protobuf);
/* This code will be inserted into generated code for
* google/protobuf/timestamp.proto. */
/**
* Returns a JavaScript 'Date' object corresponding to this Timestamp.
* @return {!Date}
*/
proto.google.protobuf.Timestamp.prototype.toDate = function() {
var seconds = this.getSeconds();
var nanos = this.getNanos();
return new Date((seconds * 1000) + (nanos / 1000000));
};
/**
* Sets the value of this Timestamp object to be the given Date.
* @param {!Date} value The value to set.
*/
proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {
this.setSeconds(Math.floor(value.getTime() / 1000));
this.setNanos(value.getMilliseconds() * 1000000);
};
/**
* Factory method that returns a Timestamp object with value equal to
* the given Date.
* @param {!Date} value The value to set.
* @return {!proto.google.protobuf.Timestamp}
*/
proto.google.protobuf.Timestamp.fromDate = function(value) {
var timestamp = new proto.google.protobuf.Timestamp();
timestamp.fromDate(value);
return timestamp;
};
} (timestamp_pb));
return timestamp_pb;
}
var timestamp_pbExports = requireTimestamp_pb();
function isDate(data) {
return data instanceof Date;
}
function createMetadata(params) {
const metadata = new grpcJs.Metadata();
Object.entries(params).forEach(([key, value]) => {
metadata.add(key, value);
});
return metadata;
}
function dateToGrpcTimestamp(data) {
if (!isDate(data)) {
data = new Date(data);
}
const { nanos, seconds } = timestamp_pbExports.Timestamp.fromDate(data).toObject();
const timestamp = new GrpcTimestamp();
timestamp.nanos = nanos;
timestamp.seconds = seconds;
return timestamp;
}
function grpcTimestampToDate(data) {
let low;
const { nanos, seconds } = data;
if (typeof seconds === 'string') {
low = parseInt(seconds, 10);
}
else {
low = seconds;
}
const timestamp = new timestamp_pbExports.Timestamp();
timestamp.setNanos(nanos);
timestamp.setSeconds(low);
return timestamp.toDate();
}
Object.defineProperty(exports, "createSecureContext", {
enumerable: true,
get: function () { return tls.createSecureContext; }
});
Object.defineProperty(exports, "ChannelCredentials", {
enumerable: true,
get: function () { return grpcJs.ChannelCredentials; }
});
Object.defineProperty(exports, "Metadata", {
enumerable: true,
get: function () { return grpcJs.Metadata; }
});
Object.defineProperty(exports, "ServerCredentials", {
enumerable: true,
get: function () { return grpcJs.ServerCredentials; }
});
Object.defineProperty(exports, "StatusBuilder", {
enumerable: true,
get: function () { return grpcJs.StatusBuilder; }
});
Object.defineProperty(exports, "credentials", {
enumerable: true,
get: function () { return grpcJs.credentials; }
});
Object.defineProperty(exports, "status", {
enumerable: true,
get: function () { return grpcJs.status; }
});
exports.GrpcTimestamp = GrpcTimestamp;
exports.createClient = createClient;
exports.createMetadata = createMetadata;
exports.createServer = createServer;
exports.dateToGrpcTimestamp = dateToGrpcTimestamp;
exports.grpcTimestampToDate = grpcTimestampToDate;