From 48817ceaeafc121d767def8f059c2bff9125a5a6 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 5 Apr 2018 14:21:12 -0700 Subject: [PATCH 01/30] Improve proto-loader package.json and documentation to prepare to publish it --- packages/grpc-protobufjs/README.md | 34 ++++++++++++++++++++++++++- packages/grpc-protobufjs/package.json | 18 ++++++++++---- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/packages/grpc-protobufjs/README.md b/packages/grpc-protobufjs/README.md index 972d5d63..4e57faf4 100644 --- a/packages/grpc-protobufjs/README.md +++ b/packages/grpc-protobufjs/README.md @@ -1,5 +1,7 @@ # gRPC Protobuf Loader +A utility package for loading `.proto` files for use with gRPC, using the latest Protobuf.js package. + ## Installation ```sh @@ -13,7 +15,37 @@ const protoLoader = require('@grpc/proto-loader'); const grpcLibrary = require('grpc'); // OR const grpcLibrary = require('@grpc/grpc-js'); -protoLoader.load(protoFile, options).then(packageDefinition => { + +protoLoader.load(protoFileName, options).then(packageDefinition => { const package = grpcLibrary.loadPackageDefinition(packageDefinition); }); +// OR +const packageDefinition = protoLoader.loadSync(protoFileName, options); +const package = grpcLibrary.loadPackageDefinition(packageDefinition); +``` + +The options parameter is an object that can have the following optional properties: + +| Field name | Valid values | Description +|------------|--------------|------------ +| `keepCase` | `true` or `false` | Preserve field names. The default is to change them to camel case. +| `longs` | `String` or `Number` | The type to use to represent `long` values. Defaults to a `Long` object type. +| `enums` | `String` | The type to use to represent `enum` values. Defaults to the numeric value. +| `bytes` | `Array` or `String` | The type to use to represent `bytes` values. Defaults to `Buffer`. +| `defaults` | `true` or `false` | Set default values on output objects. Defaults to `false`. +| `arrays` | `true` or `false` | Set empty arrays for missing array values even if `defaults` is `false` Defaults to `false`. +| `objects` | `true` or `false` | Set empty objects for missing object values even if `defaults` is `false` Defaults to `false`. +| `oneofs` | `true` or `false` | Set virtual oneof properties to the present field's name. Defaults to `false`. +| `include` | An array of strings | A list of search paths for imported `.proto` files. + +The following options object closely approximates the existing behavior of `grpc.load`: + +```js +const options = { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true +} ``` diff --git a/packages/grpc-protobufjs/package.json b/packages/grpc-protobufjs/package.json index ed02d6a8..e15c31f0 100644 --- a/packages/grpc-protobufjs/package.json +++ b/packages/grpc-protobufjs/package.json @@ -1,8 +1,17 @@ { "name": "@grpc/proto-loader", "version": "0.1.0", - "description": "", + "author": "Google Inc.", + "contributors": [ + { + "name": "Michael Lumish", + "email": "mlumish@google.com" + } + ], + "description": "gRPC utility library for loading .proto files", + "homepage": "https://grpc.io/", "main": "build/src/index.js", + "typings": "build/src/index.d.ts", "scripts": { "build": "npm run compile", "clean": "gts clean", @@ -20,7 +29,6 @@ "type": "git", "url": "https://github.com/grpc/grpc-node.git" }, - "author": "", "license": "Apache-2.0", "bugs": { "url": "https://github.com/grpc/grpc-node/issues" @@ -32,10 +40,12 @@ "dependencies": { "@types/lodash": "^4.14.104", "@types/node": "^9.4.6", + "lodash": "^4.17.5", + "protobufjs": "^6.8.5" + }, + "devDependencies": { "clang-format": "^1.2.2", "gts": "^0.5.3", - "lodash": "^4.17.5", - "protobufjs": "^6.8.5", "typescript": "~2.7.2" } } From 55106fa154cd73d9b81fdc3062fa2f0d07e544de Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 6 Apr 2018 11:57:44 -0700 Subject: [PATCH 02/30] Update v1.11.x to v1.11.0-pre1 for real this time with bugfixes --- packages/grpc-native-core/deps/grpc | 2 +- packages/grpc-native-core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/grpc-native-core/deps/grpc b/packages/grpc-native-core/deps/grpc index 98c1017f..1834a628 160000 --- a/packages/grpc-native-core/deps/grpc +++ b/packages/grpc-native-core/deps/grpc @@ -1 +1 @@ -Subproject commit 98c1017fd9f155aad13c3b86e8f17a456c9512e8 +Subproject commit 1834a628782ec867279622644a5953987aa96d38 diff --git a/packages/grpc-native-core/package.json b/packages/grpc-native-core/package.json index db5fb5a0..41ded0b1 100644 --- a/packages/grpc-native-core/package.json +++ b/packages/grpc-native-core/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.11.0-dev", + "version": "1.11.0-pre1", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "https://grpc.io/", From 37a811b630e1cf86aef6a84ddade26aa2c6c8b77 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 5 Apr 2018 00:45:39 +0200 Subject: [PATCH 03/30] Removing zdefs. --- packages/grpc-native-core/binding.gyp | 1 - packages/grpc-native-core/templates/binding.gyp.template | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/grpc-native-core/binding.gyp b/packages/grpc-native-core/binding.gyp index d2a41511..a7cbb8b7 100644 --- a/packages/grpc-native-core/binding.gyp +++ b/packages/grpc-native-core/binding.gyp @@ -932,7 +932,6 @@ ], 'cflags': [ '-pthread', - '-zdefs', '-Wno-error=deprecated-declarations' ], "conditions": [ diff --git a/packages/grpc-native-core/templates/binding.gyp.template b/packages/grpc-native-core/templates/binding.gyp.template index 11eb8e60..85ddbe65 100644 --- a/packages/grpc-native-core/templates/binding.gyp.template +++ b/packages/grpc-native-core/templates/binding.gyp.template @@ -312,7 +312,6 @@ ], 'cflags': [ '-pthread', - '-zdefs', '-Wno-error=deprecated-declarations' ], "conditions": [ From 27cc80adac93f0cd5128ddf28a9d5ca82a8fa13d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 11 Apr 2018 13:29:49 -0700 Subject: [PATCH 04/30] Add note about @grpc/grpc-js alpha status --- packages/grpc-js-core/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/grpc-js-core/README.md b/packages/grpc-js-core/README.md index 054986ca..9393ffc1 100644 --- a/packages/grpc-js-core/README.md +++ b/packages/grpc-js-core/README.md @@ -1,5 +1,7 @@ # Pure JavaScript gRPC Client +**Note: This is an alpha-level release. Some APIs may not yet be present and there may be bugs. Please report any that you encounter** + ## Installation Node 9.x or greater is required. From 2bab8dc02bbfaa17b81043e1557db67fe03ad40b Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 16 Mar 2018 01:25:19 +0100 Subject: [PATCH 05/30] Changing to the powershell version of nvm for better support. --- install-nvm-windows.ps1 | 29 ----------------------------- run-tests.bat | 16 ++++++---------- 2 files changed, 6 insertions(+), 39 deletions(-) delete mode 100644 install-nvm-windows.ps1 diff --git a/install-nvm-windows.ps1 b/install-nvm-windows.ps1 deleted file mode 100644 index b3794055..00000000 --- a/install-nvm-windows.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2017 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. - -# We're going to store nvm-windows in the .\nvm directory. -$env:NVM_HOME = (Get-Item -Path ".\" -Verbose).FullName + "\nvm" - -# Switching to TLS/1.2 - see https://githubengineering.com/crypto-removal-notice/ -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - -# Downloading and unpacking nvm-windows -Invoke-WebRequest -Uri https://github.com/coreybutler/nvm-windows/releases/download/1.1.5/nvm-noinstall.zip -OutFile nvm-noinstall.zip -Add-Type -AssemblyName System.IO.Compression.FileSystem -[System.IO.Compression.ZipFile]::ExtractToDirectory("nvm-noinstall.zip", "nvm") - -$env:Path = $env:NVM_HOME + ";" + $env:Path -Out-File -Encoding "OEM" nvm\settings.txt -nvm root $env:NVM_HOME -"%*" | Out-File -Encoding "OEM" nvm\elevate.cmd diff --git a/run-tests.bat b/run-tests.bat index 547899e7..baf21778 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -15,26 +15,22 @@ SET ROOT=%~dp0 cd /d %~dp0 -PowerShell -Command .\install-nvm-windows.ps1 +powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" -SET NVM_HOME=%ROOT%nvm -SET NVM_SYMLINK=%ROOT%nvm\nodejs -SET PATH=%NVM_HOME%;%NVM_SYMLINK%;%PATH% +SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% SET JOBS=8 -nvm version +call nvm version -nvm install 8.5.0 -nvm use 8.5.0 +call nvm install 8 call npm install || goto :error SET JUNIT_REPORT_STACK=1 SET FAILED=0 -for %%v in (4.8.4 6.11.3 7.9.0 8.5.0) do ( - nvm install %%v - nvm use %%v +for %%v in (4 6 7 8) do ( + call nvm install %%v call npm install -g npm node -e "console.log(process.versions)" From dc071f906bd818039c98e95acf26a853e99d8ee4 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 16 Mar 2018 01:33:46 +0100 Subject: [PATCH 06/30] Debugging info. --- run-tests.bat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run-tests.bat b/run-tests.bat index baf21778..81de8d25 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -15,6 +15,8 @@ SET ROOT=%~dp0 cd /d %~dp0 +powershell -c "Get-Host" +powershell -c "$PSVersionTable" powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% From 8c92bdbc33443762e308e744f2e25bc882e1438c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 5 Apr 2018 01:41:23 +0200 Subject: [PATCH 07/30] Adding more environment details. --- run-tests.bat | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/run-tests.bat b/run-tests.bat index 81de8d25..3f3aa4f1 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -17,6 +17,10 @@ cd /d %~dp0 powershell -c "Get-Host" powershell -c "$PSVersionTable" +powershell -c "[System.Environment]::OSVersion" +powershell -c "Get-WmiObject -Class Win32_ComputerSystem" +powershell -c "(Get-WmiObject -Class Win32_ComputerSystem).SystemType" + powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% From aaf8696d4289312bbde74a85b2f9fc216b32eb42 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 10 Apr 2018 00:08:43 +0200 Subject: [PATCH 08/30] Workarounding node-gyp issue. --- run-tests.bat | 6 +++++- run-tests.sh | 5 ++++- tools/release/kokoro.bat | 3 +++ tools/release/kokoro.sh | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/run-tests.bat b/run-tests.bat index 3f3aa4f1..5aeaa700 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -29,15 +29,19 @@ SET JOBS=8 call nvm version call nvm install 8 +call nvm use 8 call npm install || goto :error SET JUNIT_REPORT_STACK=1 SET FAILED=0 -for %%v in (4 6 7 8) do ( +for %%v in (4 6 7 8 9) do ( call nvm install %%v + call nvm use %%v call npm install -g npm + @rem https://github.com/mapbox/node-pre-gyp/issues/362 + call npm install -g node-gyp node -e "console.log(process.versions)" mkdir reports\node%%v diff --git a/run-tests.sh b/run-tests.sh index 1444158b..bfc0ff71 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -26,7 +26,7 @@ set -ex cd $ROOT if [ ! -n "$node_versions" ] ; then - node_versions="4 5 6 7 8" + node_versions="4 5 6 7 8 9" fi set +ex @@ -51,6 +51,9 @@ do nvm use $version set -ex + # https://github.com/mapbox/node-pre-gyp/issues/362 + npm install -g node-gyp + mkdir -p "reports/node$version" node -e 'process.exit(process.version.startsWith("v'$version'") ? 0 : -1)' diff --git a/tools/release/kokoro.bat b/tools/release/kokoro.bat index 2726d338..1fde63b5 100644 --- a/tools/release/kokoro.bat +++ b/tools/release/kokoro.bat @@ -14,6 +14,9 @@ @echo "Starting Windows build" +@rem https://github.com/mapbox/node-pre-gyp/issues/362 +call npm install -g node-gyp + cd /d %~dp0 cd ..\.. diff --git a/tools/release/kokoro.sh b/tools/release/kokoro.sh index e5b578f7..b89504a9 100755 --- a/tools/release/kokoro.sh +++ b/tools/release/kokoro.sh @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +# https://github.com/mapbox/node-pre-gyp/issues/362 +npm install -g node-gyp + set -ex cd $(dirname $0)/../.. base_dir=$(pwd) From eabda8118a5e9d4a74ccd29ee4f07eb0c765364f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Apr 2018 10:29:11 -0700 Subject: [PATCH 09/30] Switch grpc submodule to v1.10.x --- packages/grpc-native-core/binding.gyp | 95 ++++++-------------------- packages/grpc-native-core/build.yaml | 1 + packages/grpc-native-core/deps/grpc | 2 +- packages/grpc-native-core/package.json | 2 +- 4 files changed, 24 insertions(+), 76 deletions(-) diff --git a/packages/grpc-native-core/binding.gyp b/packages/grpc-native-core/binding.gyp index a7cbb8b7..8c55d963 100644 --- a/packages/grpc-native-core/binding.gyp +++ b/packages/grpc-native-core/binding.gyp @@ -40,7 +40,6 @@ 'Release': { 'cflags': [ '-O2', - '-Wframe-larger-than=16384', ], 'defines': [ 'NDEBUG', @@ -583,6 +582,9 @@ 'deps/grpc/src/core/lib/gpr/sync.cc', 'deps/grpc/src/core/lib/gpr/sync_posix.cc', 'deps/grpc/src/core/lib/gpr/sync_windows.cc', + 'deps/grpc/src/core/lib/gpr/thd.cc', + 'deps/grpc/src/core/lib/gpr/thd_posix.cc', + 'deps/grpc/src/core/lib/gpr/thd_windows.cc', 'deps/grpc/src/core/lib/gpr/time.cc', 'deps/grpc/src/core/lib/gpr/time_posix.cc', 'deps/grpc/src/core/lib/gpr/time_precise.cc', @@ -592,8 +594,6 @@ 'deps/grpc/src/core/lib/gpr/tmpfile_posix.cc', 'deps/grpc/src/core/lib/gpr/tmpfile_windows.cc', 'deps/grpc/src/core/lib/gpr/wrap_memcpy.cc', - 'deps/grpc/src/core/lib/gprpp/thd_posix.cc', - 'deps/grpc/src/core/lib/gprpp/thd_windows.cc', 'deps/grpc/src/core/lib/profiling/basic_timers.cc', 'deps/grpc/src/core/lib/profiling/stap_timers.cc', ], @@ -619,13 +619,10 @@ 'deps/grpc/src/core/lib/channel/channel_args.cc', 'deps/grpc/src/core/lib/channel/channel_stack.cc', 'deps/grpc/src/core/lib/channel/channel_stack_builder.cc', - 'deps/grpc/src/core/lib/channel/channel_trace.cc', - 'deps/grpc/src/core/lib/channel/channel_trace_registry.cc', 'deps/grpc/src/core/lib/channel/connected_channel.cc', 'deps/grpc/src/core/lib/channel/handshaker.cc', 'deps/grpc/src/core/lib/channel/handshaker_factory.cc', 'deps/grpc/src/core/lib/channel/handshaker_registry.cc', - 'deps/grpc/src/core/lib/channel/status_util.cc', 'deps/grpc/src/core/lib/compression/compression.cc', 'deps/grpc/src/core/lib/compression/compression_internal.cc', 'deps/grpc/src/core/lib/compression/message_compress.cc', @@ -659,8 +656,6 @@ 'deps/grpc/src/core/lib/iomgr/gethostname_sysconf.cc', 'deps/grpc/src/core/lib/iomgr/iocp_windows.cc', 'deps/grpc/src/core/lib/iomgr/iomgr.cc', - 'deps/grpc/src/core/lib/iomgr/iomgr_custom.cc', - 'deps/grpc/src/core/lib/iomgr/iomgr_internal.cc', 'deps/grpc/src/core/lib/iomgr/iomgr_posix.cc', 'deps/grpc/src/core/lib/iomgr/iomgr_uv.cc', 'deps/grpc/src/core/lib/iomgr/iomgr_windows.cc', @@ -669,16 +664,12 @@ 'deps/grpc/src/core/lib/iomgr/lockfree_event.cc', 'deps/grpc/src/core/lib/iomgr/network_status_tracker.cc', 'deps/grpc/src/core/lib/iomgr/polling_entity.cc', - 'deps/grpc/src/core/lib/iomgr/pollset.cc', - 'deps/grpc/src/core/lib/iomgr/pollset_custom.cc', - 'deps/grpc/src/core/lib/iomgr/pollset_set.cc', - 'deps/grpc/src/core/lib/iomgr/pollset_set_custom.cc', + 'deps/grpc/src/core/lib/iomgr/pollset_set_uv.cc', 'deps/grpc/src/core/lib/iomgr/pollset_set_windows.cc', 'deps/grpc/src/core/lib/iomgr/pollset_uv.cc', 'deps/grpc/src/core/lib/iomgr/pollset_windows.cc', - 'deps/grpc/src/core/lib/iomgr/resolve_address.cc', - 'deps/grpc/src/core/lib/iomgr/resolve_address_custom.cc', 'deps/grpc/src/core/lib/iomgr/resolve_address_posix.cc', + 'deps/grpc/src/core/lib/iomgr/resolve_address_uv.cc', 'deps/grpc/src/core/lib/iomgr/resolve_address_windows.cc', 'deps/grpc/src/core/lib/iomgr/resource_quota.cc', 'deps/grpc/src/core/lib/iomgr/sockaddr_utils.cc', @@ -690,24 +681,19 @@ 'deps/grpc/src/core/lib/iomgr/socket_utils_uv.cc', 'deps/grpc/src/core/lib/iomgr/socket_utils_windows.cc', 'deps/grpc/src/core/lib/iomgr/socket_windows.cc', - 'deps/grpc/src/core/lib/iomgr/tcp_client.cc', - 'deps/grpc/src/core/lib/iomgr/tcp_client_custom.cc', 'deps/grpc/src/core/lib/iomgr/tcp_client_posix.cc', + 'deps/grpc/src/core/lib/iomgr/tcp_client_uv.cc', 'deps/grpc/src/core/lib/iomgr/tcp_client_windows.cc', - 'deps/grpc/src/core/lib/iomgr/tcp_custom.cc', 'deps/grpc/src/core/lib/iomgr/tcp_posix.cc', - 'deps/grpc/src/core/lib/iomgr/tcp_server.cc', - 'deps/grpc/src/core/lib/iomgr/tcp_server_custom.cc', 'deps/grpc/src/core/lib/iomgr/tcp_server_posix.cc', 'deps/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc', 'deps/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc', 'deps/grpc/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc', + 'deps/grpc/src/core/lib/iomgr/tcp_server_uv.cc', 'deps/grpc/src/core/lib/iomgr/tcp_server_windows.cc', 'deps/grpc/src/core/lib/iomgr/tcp_uv.cc', 'deps/grpc/src/core/lib/iomgr/tcp_windows.cc', 'deps/grpc/src/core/lib/iomgr/time_averaged_stats.cc', - 'deps/grpc/src/core/lib/iomgr/timer.cc', - 'deps/grpc/src/core/lib/iomgr/timer_custom.cc', 'deps/grpc/src/core/lib/iomgr/timer_generic.cc', 'deps/grpc/src/core/lib/iomgr/timer_heap.cc', 'deps/grpc/src/core/lib/iomgr/timer_manager.cc', @@ -728,6 +714,7 @@ 'deps/grpc/src/core/lib/slice/percent_encoding.cc', 'deps/grpc/src/core/lib/slice/slice.cc', 'deps/grpc/src/core/lib/slice/slice_buffer.cc', + 'deps/grpc/src/core/lib/slice/slice_hash_table.cc', 'deps/grpc/src/core/lib/slice/slice_intern.cc', 'deps/grpc/src/core/lib/slice/slice_string_helpers.cc', 'deps/grpc/src/core/lib/surface/api_trace.cc', @@ -758,7 +745,6 @@ 'deps/grpc/src/core/lib/transport/service_config.cc', 'deps/grpc/src/core/lib/transport/static_metadata.cc', 'deps/grpc/src/core/lib/transport/status_conversion.cc', - 'deps/grpc/src/core/lib/transport/status_metadata.cc', 'deps/grpc/src/core/lib/transport/timeout_encoding.cc', 'deps/grpc/src/core/lib/transport/transport.cc', 'deps/grpc/src/core/lib/transport/transport_op_string.cc', @@ -793,7 +779,6 @@ 'deps/grpc/src/core/ext/filters/http/server/http_server_filter.cc', 'deps/grpc/src/core/lib/http/httpcli_security_connector.cc', 'deps/grpc/src/core/lib/security/context/security_context.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/alts_credentials.cc', 'deps/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc', 'deps/grpc/src/core/lib/security/credentials/credentials.cc', 'deps/grpc/src/core/lib/security/credentials/credentials_metadata.cc', @@ -807,56 +792,23 @@ 'deps/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'deps/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'deps/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc', - 'deps/grpc/src/core/lib/security/security_connector/alts_security_connector.cc', 'deps/grpc/src/core/lib/security/security_connector/security_connector.cc', 'deps/grpc/src/core/lib/security/transport/client_auth_filter.cc', + 'deps/grpc/src/core/lib/security/transport/lb_targets_info.cc', 'deps/grpc/src/core/lib/security/transport/secure_endpoint.cc', 'deps/grpc/src/core/lib/security/transport/security_handshaker.cc', 'deps/grpc/src/core/lib/security/transport/server_auth_filter.cc', - 'deps/grpc/src/core/lib/security/transport/target_authority_table.cc', 'deps/grpc/src/core/lib/security/transport/tsi_error.cc', 'deps/grpc/src/core/lib/security/util/json_util.cc', 'deps/grpc/src/core/lib/surface/init_secure.cc', - 'deps/grpc/src/core/tsi/alts/crypt/aes_gcm.cc', - 'deps/grpc/src/core/tsi/alts/crypt/gsec.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_counter.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_crypter.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc', - 'deps/grpc/src/core/tsi/alts/frame_protector/frame_handler.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_tsi_event.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc', - 'deps/grpc/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc', - 'deps/grpc/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc', - 'deps/grpc/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc', - 'deps/grpc/src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc', - 'deps/grpc/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/check_gcp_environment.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc', - 'deps/grpc/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/alts_tsi_utils.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/transport_security_common_api.cc', - 'deps/grpc/src/core/tsi/alts/handshaker/altscontext.pb.c', - 'deps/grpc/src/core/tsi/alts/handshaker/handshaker.pb.c', - 'deps/grpc/src/core/tsi/alts/handshaker/transport_security_common.pb.c', - 'deps/grpc/third_party/nanopb/pb_common.c', - 'deps/grpc/third_party/nanopb/pb_decode.c', - 'deps/grpc/third_party/nanopb/pb_encode.c', + 'deps/grpc/src/core/tsi/alts_transport_security.cc', + 'deps/grpc/src/core/tsi/fake_transport_security.cc', + 'deps/grpc/src/core/tsi/ssl_transport_security.cc', + 'deps/grpc/src/core/tsi/transport_security_grpc.cc', 'deps/grpc/src/core/tsi/transport_security.cc', 'deps/grpc/src/core/tsi/transport_security_adapter.cc', - 'deps/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc', - 'deps/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc', - 'deps/grpc/src/core/ext/transport/chttp2/client/authority.cc', - 'deps/grpc/src/core/ext/transport/chttp2/client/chttp2_connector.cc', + 'deps/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc', + 'deps/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc', 'deps/grpc/src/core/ext/filters/client_channel/backup_poller.cc', 'deps/grpc/src/core/ext/filters/client_channel/channel_connectivity.cc', 'deps/grpc/src/core/ext/filters/client_channel/client_channel.cc', @@ -868,7 +820,6 @@ 'deps/grpc/src/core/ext/filters/client_channel/lb_policy.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy_factory.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy_registry.cc', - 'deps/grpc/src/core/ext/filters/client_channel/method_params.cc', 'deps/grpc/src/core/ext/filters/client_channel/parse_address.cc', 'deps/grpc/src/core/ext/filters/client_channel/proxy_mapper.cc', 'deps/grpc/src/core/ext/filters/client_channel/proxy_mapper_registry.cc', @@ -879,17 +830,11 @@ 'deps/grpc/src/core/ext/filters/client_channel/subchannel_index.cc', 'deps/grpc/src/core/ext/filters/client_channel/uri_parser.cc', 'deps/grpc/src/core/ext/filters/deadline/deadline_filter.cc', - 'deps/grpc/src/core/tsi/alts_transport_security.cc', - 'deps/grpc/src/core/tsi/fake_transport_security.cc', - 'deps/grpc/src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc', - 'deps/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.cc', - 'deps/grpc/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc', - 'deps/grpc/src/core/tsi/ssl_transport_security.cc', - 'deps/grpc/src/core/tsi/transport_security_grpc.cc', - 'deps/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc', - 'deps/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc', + 'deps/grpc/src/core/ext/transport/chttp2/client/chttp2_connector.cc', 'deps/grpc/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc', 'deps/grpc/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc', + 'deps/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc', + 'deps/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc', 'deps/grpc/src/core/ext/transport/inproc/inproc_plugin.cc', 'deps/grpc/src/core/ext/transport/inproc/inproc_transport.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc', @@ -898,6 +843,9 @@ 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', + 'deps/grpc/third_party/nanopb/pb_common.c', + 'deps/grpc/third_party/nanopb/pb_decode.c', + 'deps/grpc/third_party/nanopb/pb_encode.c', 'deps/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc', 'deps/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc', @@ -913,7 +861,6 @@ 'deps/grpc/src/core/ext/census/grpc_context.cc', 'deps/grpc/src/core/ext/filters/max_age/max_age_filter.cc', 'deps/grpc/src/core/ext/filters/message_size/message_size_filter.cc', - 'deps/grpc/src/core/ext/filters/http/client_authority_filter.cc', 'deps/grpc/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc', 'deps/grpc/src/core/ext/filters/workarounds/workaround_utils.cc', 'deps/grpc/src/core/plugin_registry/grpc_plugin_registry.cc', diff --git a/packages/grpc-native-core/build.yaml b/packages/grpc-native-core/build.yaml index 49e36fdf..5703b3c8 100644 --- a/packages/grpc-native-core/build.yaml +++ b/packages/grpc-native-core/build.yaml @@ -1,2 +1,3 @@ settings: '#': It's possible to have node_version here as a key to override the core's version. + 'node_version': 1.11.0-pre2 diff --git a/packages/grpc-native-core/deps/grpc b/packages/grpc-native-core/deps/grpc index 1834a628..29e71eed 160000 --- a/packages/grpc-native-core/deps/grpc +++ b/packages/grpc-native-core/deps/grpc @@ -1 +1 @@ -Subproject commit 1834a628782ec867279622644a5953987aa96d38 +Subproject commit 29e71eede587132278accc184de2e6b2f49ee58d diff --git a/packages/grpc-native-core/package.json b/packages/grpc-native-core/package.json index 41ded0b1..c53db230 100644 --- a/packages/grpc-native-core/package.json +++ b/packages/grpc-native-core/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.11.0-pre1", + "version": "1.11.0-pre2", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "https://grpc.io/", From dd3eb9e0f81c9d8c834d0dc15acaef0f64824ad9 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 17 Apr 2018 14:06:52 -0700 Subject: [PATCH 10/30] Add unimplemented errors for several API functions --- packages/grpc-js-core/src/index.ts | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/grpc-js-core/src/index.ts b/packages/grpc-js-core/src/index.ts index 5a3f6025..8c9cb32c 100644 --- a/packages/grpc-js-core/src/index.ts +++ b/packages/grpc-js-core/src/index.ts @@ -85,3 +85,48 @@ export { * @param client The client to close. */ export const closeClient = (client: Client) => client.close(); + +export const waitForClientReady = (client: Client, deadline: Date|number, callback: (error: Error | null) => void) => client.waitForReady(deadline, callback); + +/**** Unimplemented function stubs ****/ + +export const loadObject = (value: any, options: any) => { + throw new Error('Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); +} + +export const load = (filename: any, format: any, options: any) => { + throw new Error('Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); +} + +export const setLogger = (logger: any) => { + throw new Error('Not yet implemented'); +} + +export const setLogVerbosity = (verbosity: any) => { + throw new Error('Not yet implemented'); +} + +export const Server = (options: any) => { + throw new Error('Not yet implemented'); +} + +export const ServerCredentials = { + createSsl: (rootCerts: any, keyCertPairs: any, checkClientCertificate: any) => { + throw new Error('Not yet implemented'); + }, + createInsecure: () => { + throw new Error('Not yet implemented'); + } +} + +export const getClientChannel = (client: any) => { + throw new Error('Not available in this library'); +} + +export const StatusBuilder = () => { throw new Error('Not yet implemented'); } + +export const ListenerBuilder = () => { throw new Error('Not yet implemented'); } + +export const InterceptorBuilder = () => { throw new Error('Not yet implemented'); } + +export const InterceptingCall = () => { throw new Error('Not yet implemented'); } From 9112ac194b99224dced664d5d8c9df9d12d1af3a Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Thu, 12 Apr 2018 11:59:34 -0700 Subject: [PATCH 11/30] js: only listen for channel connect event once --- packages/grpc-js-core/src/call.ts | 2 +- packages/grpc-js-core/src/channel.ts | 40 +++++++++++++++++++++++----- packages/grpc-js-core/src/client.ts | 6 +++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/grpc-js-core/src/call.ts b/packages/grpc-js-core/src/call.ts index af305b24..4344dfeb 100644 --- a/packages/grpc-js-core/src/call.ts +++ b/packages/grpc-js-core/src/call.ts @@ -87,13 +87,13 @@ function setUpReadableStream( stream.push(null); }); call.on('status', (status: StatusObject) => { - stream.emit('status', status); if (status.code !== Status.OK) { const statusName = _.invert(Status)[status.code]; const message: string = `${status.code} ${statusName}: ${status.details}`; const error: ServiceError = Object.assign(new Error(status.details), status); stream.emit('error', error); } + stream.emit('status', status); }); call.pause(); } diff --git a/packages/grpc-js-core/src/channel.ts b/packages/grpc-js-core/src/channel.ts index 8e8e38e7..e710b733 100644 --- a/packages/grpc-js-core/src/channel.ts +++ b/packages/grpc-js-core/src/channel.ts @@ -85,6 +85,8 @@ export class Http2Channel extends EventEmitter implements Channel { private readonly target: url.URL; private readonly defaultAuthority: string; private connectivityState: ConnectivityState = ConnectivityState.IDLE; + // Helper Promise object only used in the implementation of connect(). + private connecting: Promise|null = null; /* For now, we have up to one subchannel, which will exist as long as we are * connecting or trying to connect */ private subChannel: http2.ClientHttp2Session|null = null; @@ -127,6 +129,7 @@ export class Http2Channel extends EventEmitter implements Channel { this.subChannel.removeListener('connect', this.subChannelConnectCallback); this.subChannel.removeListener('close', this.subChannelCloseCallback); this.subChannel = null; + this.emit('shutdown'); clearTimeout(this.backoffTimerId); } break; @@ -279,15 +282,38 @@ export class Http2Channel extends EventEmitter implements Channel { return stream; } + /** + * Attempts to connect, returning a Promise that resolves when the connection + * is successful, or rejects if the channel is shut down. + */ connect(): Promise { - return new Promise((resolve) => { - this.transitionToState([ConnectivityState.IDLE], ConnectivityState.CONNECTING); - if (this.connectivityState === ConnectivityState.READY) { - setImmediate(resolve); - } else { - this.once('connect', resolve); + if (this.connectivityState === ConnectivityState.READY) { + return Promise.resolve(); + } else if (this.connectivityState === ConnectivityState.SHUTDOWN) { + return Promise.reject(new Error('Channel has been shut down')); + } else { + // In effect, this.connecting is only assigned upon the first attempt to + // transition from IDLE to CONNECTING, so this condition could have also + // been (connectivityState === IDLE). + if (!this.connecting) { + this.connecting = new Promise((resolve, reject) => { + this.transitionToState([ConnectivityState.IDLE], ConnectivityState.CONNECTING); + const onConnect = () => { + this.connecting = null; + this.removeListener('shutdown', onShutdown); + resolve(); + }; + const onShutdown = () => { + this.connecting = null; + this.removeListener('connect', onConnect); + reject(new Error('Channel has been shut down')); + }; + this.once('connect', onConnect); + this.once('shutdown', onShutdown); + }); } - }); + return this.connecting; + } } getConnectivityState(): ConnectivityState { diff --git a/packages/grpc-js-core/src/client.ts b/packages/grpc-js-core/src/client.ts index 25fa7bc8..b120fcc7 100644 --- a/packages/grpc-js-core/src/client.ts +++ b/packages/grpc-js-core/src/client.ts @@ -42,6 +42,12 @@ export class Client { clearTimeout(timer); } cb(null); + }, (err: Error) => { + // Rejection occurs if channel is shut down first. + if (timer) { + clearTimeout(timer); + } + cb(err); }); if (deadline !== Infinity) { let timeout: number; From 881b82d50c744cb7798fa60f5165986c3f3a4bbf Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 18 Apr 2018 11:32:46 -0700 Subject: [PATCH 12/30] Fix lint errors and formatting --- .../src/call-credentials-filter.ts | 17 +- packages/grpc-js-core/src/call-credentials.ts | 68 ++--- packages/grpc-js-core/src/call-stream.ts | 63 +++-- packages/grpc-js-core/src/call.ts | 38 +-- .../grpc-js-core/src/channel-credentials.ts | 149 +++++----- packages/grpc-js-core/src/channel.ts | 227 ++++++++------- packages/grpc-js-core/src/client.ts | 43 +-- packages/grpc-js-core/src/deadline-filter.ts | 16 +- packages/grpc-js-core/src/events.ts | 6 +- packages/grpc-js-core/src/filter-stack.ts | 2 +- packages/grpc-js-core/src/index.ts | 164 ++++++----- packages/grpc-js-core/src/make-client.ts | 72 +++-- .../src/metadata-status-filter.ts | 13 +- packages/grpc-js-core/src/metadata.ts | 18 +- packages/grpc-js-core/src/object-stream.ts | 7 +- packages/grpc-js-core/test/common.ts | 10 +- .../test/test-call-credentials.ts | 10 +- .../grpc-js-core/test/test-call-stream.ts | 263 +++++++++--------- .../test/test-channel-credentials.ts | 1 + 19 files changed, 618 insertions(+), 569 deletions(-) diff --git a/packages/grpc-js-core/src/call-credentials-filter.ts b/packages/grpc-js-core/src/call-credentials-filter.ts index 73759410..f25d70bc 100644 --- a/packages/grpc-js-core/src/call-credentials-filter.ts +++ b/packages/grpc-js-core/src/call-credentials-filter.ts @@ -10,11 +10,10 @@ export class CallCredentialsFilter extends BaseFilter implements Filter { private serviceUrl: string; constructor( private readonly credentials: CallCredentials, - private readonly host: string, - private readonly path: string) { + private readonly host: string, private readonly path: string) { super(); - let splitPath: string[] = path.split('/'); - let serviceName: string = ''; + const splitPath: string[] = path.split('/'); + let serviceName = ''; /* The standard path format is "/{serviceName}/{methodName}", so if we split * by '/', the first item should be empty and the second should be the * service name */ @@ -27,8 +26,9 @@ export class CallCredentialsFilter extends BaseFilter implements Filter { } async sendMetadata(metadata: Promise): Promise { - let credsMetadata = this.credentials.generateMetadata({ service_url: this.serviceUrl }); - let resultMetadata = await metadata; + const credsMetadata = + this.credentials.generateMetadata({service_url: this.serviceUrl}); + const resultMetadata = await metadata; resultMetadata.merge(await credsMetadata); return resultMetadata; } @@ -43,8 +43,7 @@ export class CallCredentialsFilterFactory implements createFilter(callStream: CallStream): CallCredentialsFilter { return new CallCredentialsFilter( - this.credentials.compose(callStream.getCredentials()), - callStream.getHost(), - callStream.getMethod()); + this.credentials.compose(callStream.getCredentials()), + callStream.getHost(), callStream.getMethod()); } } diff --git a/packages/grpc-js-core/src/call-credentials.ts b/packages/grpc-js-core/src/call-credentials.ts index 0c0f6d53..7d5bd332 100644 --- a/packages/grpc-js-core/src/call-credentials.ts +++ b/packages/grpc-js-core/src/call-credentials.ts @@ -2,39 +2,59 @@ import {map, reduce} from 'lodash'; import {Metadata} from './metadata'; -export type CallMetadataOptions = { service_url: string; }; +export type CallMetadataOptions = { + service_url: string; +}; export type CallMetadataGenerator = - (options: CallMetadataOptions, cb: (err: Error|null, metadata?: Metadata) => void) => - void; + (options: CallMetadataOptions, + cb: (err: Error|null, metadata?: Metadata) => void) => void; /** * A class that represents a generic method of adding authentication-related * metadata on a per-request basis. */ -export interface CallCredentials { +export abstract class CallCredentials { /** * Asynchronously generates a new Metadata object. * @param options Options used in generating the Metadata object. */ - generateMetadata(options: CallMetadataOptions): Promise; + abstract generateMetadata(options: CallMetadataOptions): Promise; /** * Creates a new CallCredentials object from properties of both this and * another CallCredentials object. This object's metadata generator will be * called first. * @param callCredentials The other CallCredentials object. */ - compose(callCredentials: CallCredentials): CallCredentials; + abstract compose(callCredentials: CallCredentials): CallCredentials; + + /** + * Creates a new CallCredentials object from a given function that generates + * Metadata objects. + * @param metadataGenerator A function that accepts a set of options, and + * generates a Metadata object based on these options, which is passed back + * to the caller via a supplied (err, metadata) callback. + */ + static createFromMetadataGenerator(metadataGenerator: CallMetadataGenerator): + CallCredentials { + return new SingleCallCredentials(metadataGenerator); + } + + static createEmpty(): CallCredentials { + return new EmptyCallCredentials(); + } } -class ComposedCallCredentials implements CallCredentials { - constructor(private creds: CallCredentials[]) {} +class ComposedCallCredentials extends CallCredentials { + constructor(private creds: CallCredentials[]) { + super(); + } async generateMetadata(options: CallMetadataOptions): Promise { - let base: Metadata = new Metadata(); - let generated: Metadata[] = await Promise.all( + const base: Metadata = new Metadata(); + const generated: Metadata[] = await Promise.all( map(this.creds, (cred) => cred.generateMetadata(options))); - for (let gen of generated) { + for (const gen of generated) { base.merge(gen); } return base; @@ -45,8 +65,10 @@ class ComposedCallCredentials implements CallCredentials { } } -class SingleCallCredentials implements CallCredentials { - constructor(private metadataGenerator: CallMetadataGenerator) {} +class SingleCallCredentials extends CallCredentials { + constructor(private metadataGenerator: CallMetadataGenerator) { + super(); + } generateMetadata(options: CallMetadataOptions): Promise { return new Promise((resolve, reject) => { @@ -65,7 +87,7 @@ class SingleCallCredentials implements CallCredentials { } } -class EmptyCallCredentials implements CallCredentials { +class EmptyCallCredentials extends CallCredentials { generateMetadata(options: CallMetadataOptions): Promise { return Promise.resolve(new Metadata()); } @@ -74,21 +96,3 @@ class EmptyCallCredentials implements CallCredentials { return other; } } - -export namespace CallCredentials { - /** - * Creates a new CallCredentials object from a given function that generates - * Metadata objects. - * @param metadataGenerator A function that accepts a set of options, and - * generates a Metadata object based on these options, which is passed back - * to the caller via a supplied (err, metadata) callback. - */ - export function createFromMetadataGenerator( - metadataGenerator: CallMetadataGenerator): CallCredentials { - return new SingleCallCredentials(metadataGenerator); - } - - export function createEmpty(): CallCredentials { - return new EmptyCallCredentials(); - } -} diff --git a/packages/grpc-js-core/src/call-stream.ts b/packages/grpc-js-core/src/call-stream.ts index 80962008..eb6b743e 100644 --- a/packages/grpc-js-core/src/call-stream.ts +++ b/packages/grpc-js-core/src/call-stream.ts @@ -9,9 +9,10 @@ import {FilterStackFactory} from './filter-stack'; import {Metadata} from './metadata'; import {ObjectDuplex} from './object-stream'; -const {HTTP2_HEADER_STATUS, HTTP2_HEADER_CONTENT_TYPE, NGHTTP2_CANCEL} = http2.constants; +const {HTTP2_HEADER_STATUS, HTTP2_HEADER_CONTENT_TYPE, NGHTTP2_CANCEL} = + http2.constants; -export type Deadline = Date | number; +export type Deadline = Date|number; export interface CallStreamOptions { deadline: Deadline; @@ -36,20 +37,19 @@ export interface WriteObject { /** * This interface represents a duplex stream associated with a single gRPC call. */ -export type CallStream = { - cancelWithStatus(status: Status, details: string): void; - getPeer(): string; +export type CallStream = { + cancelWithStatus(status: Status, details: string): void; getPeer(): string; getDeadline(): Deadline; getCredentials(): CallCredentials; /* If the return value is null, the call has not ended yet. Otherwise, it has * ended with the specified status */ - getStatus(): StatusObject|null; + getStatus(): StatusObject | null; getMethod(): string; getHost(): string; -} & EmitterAugmentation1<'metadata', Metadata> - & EmitterAugmentation1<'status', StatusObject> - & ObjectDuplex; +}&EmitterAugmentation1<'metadata', Metadata>& + EmitterAugmentation1<'status', StatusObject>& + ObjectDuplex; enum ReadState { NO_DATA, @@ -60,7 +60,7 @@ enum ReadState { const emptyBuffer = Buffer.alloc(0); export class Http2CallStream extends Duplex implements CallStream { - public filterStack: Filter; + filterStack: Filter; private statusEmitted = false; private http2Stream: http2.ClientHttp2Stream|null = null; private pendingRead = false; @@ -76,7 +76,7 @@ export class Http2CallStream extends Duplex implements CallStream { private readPartialMessage: Buffer[] = []; private readMessageRemaining = 0; - private unpushedReadMessages: (Buffer|null)[] = []; + private unpushedReadMessages: Array = []; // Status code mapped from :status. To be used if grpc-status is not received private mappedStatusCode: Status = Status.UNKNOWN; @@ -124,20 +124,21 @@ export class Http2CallStream extends Duplex implements CallStream { } private handleTrailers(headers: http2.IncomingHttpHeaders) { - let code: Status = this.mappedStatusCode; - let details = ''; + const code: Status = this.mappedStatusCode; + const details = ''; let metadata: Metadata; try { metadata = Metadata.fromHttp2Headers(headers); } catch (e) { metadata = new Metadata(); } - let status: StatusObject = {code, details, metadata}; + const status: StatusObject = {code, details, metadata}; this.handlingTrailers = (async () => { let finalStatus; try { // Attempt to assign final status. - finalStatus = await this.filterStack.receiveTrailers(Promise.resolve(status)); + finalStatus = + await this.filterStack.receiveTrailers(Promise.resolve(status)); } catch (error) { await this.handlingHeaders; // This is a no-op if the call was already ended when handling headers. @@ -195,17 +196,26 @@ export class Http2CallStream extends Duplex implements CallStream { try { metadata = Metadata.fromHttp2Headers(headers); } catch (error) { - this.endCall({code: Status.UNKNOWN, details: error.message, metadata: new Metadata()}); + this.endCall({ + code: Status.UNKNOWN, + details: error.message, + metadata: new Metadata() + }); return; } this.handlingHeaders = - this.filterStack.receiveMetadata(Promise.resolve(metadata)) - .then((finalMetadata) => { - this.emit('metadata', finalMetadata); - }).catch((error) => { - this.destroyHttp2Stream(); - this.endCall({code: Status.UNKNOWN, details: error.message, metadata: new Metadata()}); - }); + this.filterStack.receiveMetadata(Promise.resolve(metadata)) + .then((finalMetadata) => { + this.emit('metadata', finalMetadata); + }) + .catch((error) => { + this.destroyHttp2Stream(); + this.endCall({ + code: Status.UNKNOWN, + details: error.message, + metadata: new Metadata() + }); + }); } }); stream.on('trailers', this.handleTrailers.bind(this)); @@ -260,6 +270,9 @@ export class Http2CallStream extends Duplex implements CallStream { canPush = this.tryPush(messageBytes, canPush); this.readState = ReadState.NO_DATA; } + break; + default: + throw new Error('This should never happen'); } } }); @@ -298,7 +311,7 @@ export class Http2CallStream extends Duplex implements CallStream { // This is OK, because status codes emitted here correspond to more // catastrophic issues that prevent us from receiving trailers in the // first place. - this.endCall({code: code, details: details, metadata: new Metadata()}); + this.endCall({code, details, metadata: new Metadata()}); }); stream.on('error', (err: Error) => { this.endCall({ @@ -338,7 +351,7 @@ export class Http2CallStream extends Duplex implements CallStream { // If trailers are currently being processed, the call should be ended // by handleTrailers instead. await this.handlingTrailers; - this.endCall({code: status, details: details, metadata: new Metadata()}); + this.endCall({code: status, details, metadata: new Metadata()}); })(); } diff --git a/packages/grpc-js-core/src/call.ts b/packages/grpc-js-core/src/call.ts index 4344dfeb..fc72d358 100644 --- a/packages/grpc-js-core/src/call.ts +++ b/packages/grpc-js-core/src/call.ts @@ -1,27 +1,25 @@ import {EventEmitter} from 'events'; -import {EmitterAugmentation1} from './events'; +import * as _ from 'lodash'; import {Duplex, Readable, Writable} from 'stream'; import {CallStream, StatusObject, WriteObject} from './call-stream'; import {Status} from './constants'; +import {EmitterAugmentation1} from './events'; import {Metadata} from './metadata'; import {ObjectReadable, ObjectWritable} from './object-stream'; -import * as _ from 'lodash'; /** * A type extending the built-in Error object with additional fields. */ -export type ServiceError = StatusObject & Error; +export type ServiceError = StatusObject&Error; /** * A base type for all user-facing values returned by client-side method calls. */ export type Call = { - cancel(): void; - getPeer(): string; -} & EmitterAugmentation1<'metadata', Metadata> - & EmitterAugmentation1<'status', StatusObject> - & EventEmitter; + cancel(): void; getPeer(): string; +}&EmitterAugmentation1<'metadata', Metadata>& + EmitterAugmentation1<'status', StatusObject>&EventEmitter; /** * A type representing the return value of a unary method call. @@ -33,22 +31,23 @@ export type ClientUnaryCall = Call; */ export type ClientReadableStream = { deserialize: (chunk: Buffer) => ResponseType; -} & Call & ObjectReadable; +}&Call&ObjectReadable; /** * A type representing the return value of a client stream method call. */ export type ClientWritableStream = { serialize: (value: RequestType) => Buffer; -} & Call & ObjectWritable; +}&Call&ObjectWritable; /** * A type representing the return value of a bidirectional stream method call. */ export type ClientDuplexStream = - ClientWritableStream & ClientReadableStream; + ClientWritableStream&ClientReadableStream; -export class ClientUnaryCallImpl extends EventEmitter implements ClientUnaryCall { +export class ClientUnaryCallImpl extends EventEmitter implements + ClientUnaryCall { constructor(private readonly call: CallStream) { super(); call.on('metadata', (metadata: Metadata) => { @@ -89,8 +88,9 @@ function setUpReadableStream( call.on('status', (status: StatusObject) => { if (status.code !== Status.OK) { const statusName = _.invert(Status)[status.code]; - const message: string = `${status.code} ${statusName}: ${status.details}`; - const error: ServiceError = Object.assign(new Error(status.details), status); + const message = `${status.code} ${statusName}: ${status.details}`; + const error: ServiceError = + Object.assign(new Error(status.details), status); stream.emit('error', error); } stream.emit('status', status); @@ -102,7 +102,7 @@ export class ClientReadableStreamImpl extends Readable implements ClientReadableStream { constructor( private readonly call: CallStream, - public readonly deserialize: (chunk: Buffer) => ResponseType) { + readonly deserialize: (chunk: Buffer) => ResponseType) { super({objectMode: true}); call.on('metadata', (metadata: Metadata) => { this.emit('metadata', metadata); @@ -135,7 +135,7 @@ function tryWrite( cb(e); return; } - const writeObj: WriteObject = {message: message}; + const writeObj: WriteObject = {message}; if (!Number.isNaN(flags)) { writeObj.flags = flags; } @@ -146,7 +146,7 @@ export class ClientWritableStreamImpl extends Writable implements ClientWritableStream { constructor( private readonly call: CallStream, - public readonly serialize: (value: RequestType) => Buffer) { + readonly serialize: (value: RequestType) => Buffer) { super({objectMode: true}); call.on('metadata', (metadata: Metadata) => { this.emit('metadata', metadata); @@ -178,8 +178,8 @@ export class ClientDuplexStreamImpl extends Duplex implements ClientDuplexStream { constructor( private readonly call: CallStream, - public readonly serialize: (value: RequestType) => Buffer, - public readonly deserialize: (chunk: Buffer) => ResponseType) { + readonly serialize: (value: RequestType) => Buffer, + readonly deserialize: (chunk: Buffer) => ResponseType) { super({objectMode: true}); call.on('metadata', (metadata: Metadata) => { this.emit('metadata', metadata); diff --git a/packages/grpc-js-core/src/channel-credentials.ts b/packages/grpc-js-core/src/channel-credentials.ts index 419e3d17..5a5c9037 100644 --- a/packages/grpc-js-core/src/channel-credentials.ts +++ b/packages/grpc-js-core/src/channel-credentials.ts @@ -2,90 +2,45 @@ import {createSecureContext, SecureContext} from 'tls'; import {CallCredentials} from './call-credentials'; -/** - * A class that contains credentials for communicating over a channel, as well - * as a set of per-call credentials, which are applied to every method call made - * over a channel initialized with an instance of this class. - */ -export interface ChannelCredentials { - /** - * Returns a copy of this object with the included set of per-call credentials - * expanded to include callCredentials. - * @param callCredentials A CallCredentials object to associate with this - * instance. - */ - compose(callCredentials: CallCredentials): ChannelCredentials; - - /** - * Gets the set of per-call credentials associated with this instance. - */ - getCallCredentials(): CallCredentials; - - /** - * Gets a SecureContext object generated from input parameters if this - * instance was created with createSsl, or null if this instance was created - * with createInsecure. - */ - getSecureContext(): SecureContext|null; -} - -abstract class ChannelCredentialsImpl implements ChannelCredentials { - protected callCredentials: CallCredentials; - - protected constructor(callCredentials?: CallCredentials) { - this.callCredentials = callCredentials || CallCredentials.createEmpty(); - } - - abstract compose(callCredentials: CallCredentials): ChannelCredentialsImpl; - - getCallCredentials(): CallCredentials { - return this.callCredentials; - } - - abstract getSecureContext(): SecureContext|null; -} - -class InsecureChannelCredentialsImpl extends ChannelCredentialsImpl { - constructor(callCredentials?: CallCredentials) { - super(callCredentials); - } - - compose(callCredentials: CallCredentials): ChannelCredentialsImpl { - throw new Error('Cannot compose insecure credentials'); - } - - getSecureContext(): SecureContext|null { - return null; - } -} - -class SecureChannelCredentialsImpl extends ChannelCredentialsImpl { - secureContext: SecureContext; - - constructor(secureContext: SecureContext, callCredentials?: CallCredentials) { - super(callCredentials); - this.secureContext = secureContext; - } - - compose(callCredentials: CallCredentials): ChannelCredentialsImpl { - const combinedCallCredentials = - this.callCredentials.compose(callCredentials); - return new SecureChannelCredentialsImpl( - this.secureContext, combinedCallCredentials); - } - - getSecureContext(): SecureContext|null { - return this.secureContext; - } -} - +// tslint:disable-next-line:no-any function verifyIsBufferOrNull(obj: any, friendlyName: string): void { if (obj && !(obj instanceof Buffer)) { throw new TypeError(`${friendlyName}, if provided, must be a Buffer.`); } } -export namespace ChannelCredentials { +/** + * A class that contains credentials for communicating over a channel, as well + * as a set of per-call credentials, which are applied to every method call made + * over a channel initialized with an instance of this class. + */ +export abstract class ChannelCredentials { + protected callCredentials: CallCredentials; + + protected constructor(callCredentials?: CallCredentials) { + this.callCredentials = callCredentials || CallCredentials.createEmpty(); + } + /** + * Returns a copy of this object with the included set of per-call credentials + * expanded to include callCredentials. + * @param callCredentials A CallCredentials object to associate with this + * instance. + */ + abstract compose(callCredentials: CallCredentials): ChannelCredentials; + + /** + * Gets the set of per-call credentials associated with this instance. + */ + getCallCredentials(): CallCredentials { + return this.callCredentials; + } + + /** + * Gets a SecureContext object generated from input parameters if this + * instance was created with createSsl, or null if this instance was created + * with createInsecure. + */ + abstract getSecureContext(): SecureContext|null; /** * Return a new ChannelCredentials instance with a given set of credentials. @@ -95,7 +50,7 @@ export namespace ChannelCredentials { * @param privateKey The client certificate private key, if available. * @param certChain The client certificate key chain, if available. */ - export function createSsl( + static createSsl( rootCerts?: Buffer|null, privateKey?: Buffer|null, certChain?: Buffer|null): ChannelCredentials { verifyIsBufferOrNull(rootCerts, 'Root certificate'); @@ -120,7 +75,41 @@ export namespace ChannelCredentials { /** * Return a new ChannelCredentials instance with no credentials. */ - export function createInsecure(): ChannelCredentials { + static createInsecure(): ChannelCredentials { return new InsecureChannelCredentialsImpl(); } } + +class InsecureChannelCredentialsImpl extends ChannelCredentials { + constructor(callCredentials?: CallCredentials) { + super(callCredentials); + } + + compose(callCredentials: CallCredentials): ChannelCredentials { + throw new Error('Cannot compose insecure credentials'); + } + + getSecureContext(): SecureContext|null { + return null; + } +} + +class SecureChannelCredentialsImpl extends ChannelCredentials { + secureContext: SecureContext; + + constructor(secureContext: SecureContext, callCredentials?: CallCredentials) { + super(callCredentials); + this.secureContext = secureContext; + } + + compose(callCredentials: CallCredentials): ChannelCredentials { + const combinedCallCredentials = + this.callCredentials.compose(callCredentials); + return new SecureChannelCredentialsImpl( + this.secureContext, combinedCallCredentials); + } + + getSecureContext(): SecureContext|null { + return this.secureContext; + } +} diff --git a/packages/grpc-js-core/src/channel.ts b/packages/grpc-js-core/src/channel.ts index e710b733..18ab8ec7 100644 --- a/packages/grpc-js-core/src/channel.ts +++ b/packages/grpc-js-core/src/channel.ts @@ -1,6 +1,6 @@ import {EventEmitter} from 'events'; import * as http2 from 'http2'; -import {checkServerIdentity, SecureContext, PeerCertificate} from 'tls'; +import {checkServerIdentity, PeerCertificate, SecureContext} from 'tls'; import * as url from 'url'; import {CallCredentials} from './call-credentials'; @@ -12,9 +12,9 @@ import {Status} from './constants'; import {DeadlineFilterFactory} from './deadline-filter'; import {FilterStackFactory} from './filter-stack'; import {Metadata, MetadataObject} from './metadata'; -import { MetadataStatusFilterFactory } from './metadata-status-filter'; +import {MetadataStatusFilterFactory} from './metadata-status-filter'; -const { version: clientVersion } = require('../../package'); +const {version: clientVersion} = require('../../package'); const IDLE_TIMEOUT_MS = 300000; @@ -42,7 +42,7 @@ export interface ChannelOptions { 'grpc.primary_user_agent': string; 'grpc.secondary_user_agent': string; 'grpc.default_authority': string; - [key: string]: string | number; + [key: string]: string|number; } export enum ConnectivityState { @@ -53,7 +53,7 @@ export enum ConnectivityState { SHUTDOWN } -function uniformRandom(min:number, max: number) { +function uniformRandom(min: number, max: number) { return Math.random() * (max - min) + min; } @@ -71,6 +71,7 @@ export interface Channel extends EventEmitter { getConnectivityState(): ConnectivityState; close(): void; + /* tslint:disable:no-any */ addListener(event: string, listener: Function): this; emit(event: string|symbol, ...args: any[]): boolean; on(event: string, listener: Function): this; @@ -78,6 +79,7 @@ export interface Channel extends EventEmitter { prependListener(event: string, listener: Function): this; prependOnceListener(event: string, listener: Function): this; removeListener(event: string, listener: Function): this; + /* tslint:enable:no-any */ } export class Http2Channel extends EventEmitter implements Channel { @@ -92,54 +94,65 @@ export class Http2Channel extends EventEmitter implements Channel { private subChannel: http2.ClientHttp2Session|null = null; private filterStackFactory: FilterStackFactory; - private subChannelConnectCallback: ()=>void = () => {}; - private subChannelCloseCallback: ()=>void = () => {}; + private subChannelConnectCallback: () => void = () => {}; + private subChannelCloseCallback: () => void = () => {}; private backoffTimerId: NodeJS.Timer; private currentBackoff: number = INITIAL_BACKOFF_MS; private currentBackoffDeadline: Date; - private handleStateChange(oldState: ConnectivityState, newState: ConnectivityState): void { - let now: Date = new Date(); - switch(newState) { - case ConnectivityState.CONNECTING: - if (oldState === ConnectivityState.IDLE) { - this.currentBackoff = INITIAL_BACKOFF_MS; - this.currentBackoffDeadline = new Date(now.getTime() + INITIAL_BACKOFF_MS); - } else if (oldState === ConnectivityState.TRANSIENT_FAILURE) { - this.currentBackoff = Math.min(this.currentBackoff * BACKOFF_MULTIPLIER, MAX_BACKOFF_MS); - let jitterMagnitude: number = BACKOFF_JITTER * this.currentBackoff; - this.currentBackoffDeadline = new Date(now.getTime() + this.currentBackoff + uniformRandom(-jitterMagnitude, jitterMagnitude)); - } - this.startConnecting(); - break; - case ConnectivityState.READY: - this.emit('connect'); - break; - case ConnectivityState.TRANSIENT_FAILURE: - this.subChannel = null; - this.backoffTimerId = setTimeout(() => { - this.transitionToState([ConnectivityState.TRANSIENT_FAILURE], ConnectivityState.CONNECTING); - }, this.currentBackoffDeadline.getTime() - now.getTime()); - break; - case ConnectivityState.IDLE: - case ConnectivityState.SHUTDOWN: - if (this.subChannel) { - this.subChannel.close(); - this.subChannel.removeListener('connect', this.subChannelConnectCallback); - this.subChannel.removeListener('close', this.subChannelCloseCallback); + private handleStateChange( + oldState: ConnectivityState, newState: ConnectivityState): void { + const now: Date = new Date(); + switch (newState) { + case ConnectivityState.CONNECTING: + if (oldState === ConnectivityState.IDLE) { + this.currentBackoff = INITIAL_BACKOFF_MS; + this.currentBackoffDeadline = + new Date(now.getTime() + INITIAL_BACKOFF_MS); + } else if (oldState === ConnectivityState.TRANSIENT_FAILURE) { + this.currentBackoff = Math.min( + this.currentBackoff * BACKOFF_MULTIPLIER, MAX_BACKOFF_MS); + const jitterMagnitude: number = BACKOFF_JITTER * this.currentBackoff; + this.currentBackoffDeadline = new Date( + now.getTime() + this.currentBackoff + + uniformRandom(-jitterMagnitude, jitterMagnitude)); + } + this.startConnecting(); + break; + case ConnectivityState.READY: + this.emit('connect'); + break; + case ConnectivityState.TRANSIENT_FAILURE: this.subChannel = null; - this.emit('shutdown'); - clearTimeout(this.backoffTimerId); - } - break; + this.backoffTimerId = setTimeout(() => { + this.transitionToState( + [ConnectivityState.TRANSIENT_FAILURE], + ConnectivityState.CONNECTING); + }, this.currentBackoffDeadline.getTime() - now.getTime()); + break; + case ConnectivityState.IDLE: + case ConnectivityState.SHUTDOWN: + if (this.subChannel) { + this.subChannel.close(); + this.subChannel.removeListener( + 'connect', this.subChannelConnectCallback); + this.subChannel.removeListener('close', this.subChannelCloseCallback); + this.subChannel = null; + this.emit('shutdown'); + clearTimeout(this.backoffTimerId); + } + break; + default: + throw new Error('This should never happen'); } } // Transition from any of a set of oldStates to a specific newState - private transitionToState(oldStates: ConnectivityState[], newState: ConnectivityState): void { + private transitionToState( + oldStates: ConnectivityState[], newState: ConnectivityState): void { if (oldStates.indexOf(this.connectivityState) > -1) { - let oldState: ConnectivityState = this.connectivityState; + const oldState: ConnectivityState = this.connectivityState; this.connectivityState = newState; this.handleStateChange(oldState, newState); this.emit('connectivityStateChanged', newState); @@ -148,54 +161,58 @@ export class Http2Channel extends EventEmitter implements Channel { private startConnecting(): void { let subChannel: http2.ClientHttp2Session; - let secureContext = this.credentials.getSecureContext(); + const secureContext = this.credentials.getSecureContext(); if (secureContext === null) { subChannel = http2.connect(this.target); } else { const connectionOptions: http2.SecureClientSessionOptions = { secureContext, - } + }; // If provided, the value of grpc.ssl_target_name_override should be used // to override the target hostname when checking server identity. // This option is used for testing only. if (this.options['grpc.ssl_target_name_override']) { - const sslTargetNameOverride = this.options['grpc.ssl_target_name_override']!; - connectionOptions.checkServerIdentity = (host: string, cert: PeerCertificate): Error | undefined => { - return checkServerIdentity(sslTargetNameOverride, cert); - } + const sslTargetNameOverride = + this.options['grpc.ssl_target_name_override']!; + connectionOptions.checkServerIdentity = + (host: string, cert: PeerCertificate): Error|undefined => { + return checkServerIdentity(sslTargetNameOverride, cert); + }; connectionOptions.servername = sslTargetNameOverride; } subChannel = http2.connect(this.target, connectionOptions); } this.subChannel = subChannel; - let now = new Date(); - let connectionTimeout: number = Math.max( - this.currentBackoffDeadline.getTime() - now.getTime(), - MIN_CONNECT_TIMEOUT_MS); - let connectionTimerId: NodeJS.Timer = setTimeout(() => { - // This should trigger the 'close' event, which will send us back to TRANSIENT_FAILURE + const now = new Date(); + const connectionTimeout: number = Math.max( + this.currentBackoffDeadline.getTime() - now.getTime(), + MIN_CONNECT_TIMEOUT_MS); + const connectionTimerId: NodeJS.Timer = setTimeout(() => { + // This should trigger the 'close' event, which will send us back to + // TRANSIENT_FAILURE subChannel.close(); }, connectionTimeout); this.subChannelConnectCallback = () => { // Connection succeeded clearTimeout(connectionTimerId); - this.transitionToState([ConnectivityState.CONNECTING], ConnectivityState.READY); + this.transitionToState( + [ConnectivityState.CONNECTING], ConnectivityState.READY); }; subChannel.once('connect', this.subChannelConnectCallback); this.subChannelCloseCallback = () => { // Connection failed clearTimeout(connectionTimerId); - /* TODO(murgatroid99): verify that this works for CONNECTING->TRANSITIVE_FAILURE - * see nodejs/node#16645 */ - this.transitionToState([ConnectivityState.CONNECTING, ConnectivityState.READY], - ConnectivityState.TRANSIENT_FAILURE); + /* TODO(murgatroid99): verify that this works for + * CONNECTING->TRANSITIVE_FAILURE see nodejs/node#16645 */ + this.transitionToState( + [ConnectivityState.CONNECTING, ConnectivityState.READY], + ConnectivityState.TRANSIENT_FAILURE); }; subChannel.once('close', this.subChannelCloseCallback); } constructor( - address: string, - public readonly credentials: ChannelCredentials, + address: string, readonly credentials: ChannelCredentials, private readonly options: Partial) { super(); if (credentials.getSecureContext() === null) { @@ -211,8 +228,7 @@ export class Http2Channel extends EventEmitter implements Channel { } this.filterStackFactory = new FilterStackFactory([ new CompressionFilterFactory(this), - new CallCredentialsFilterFactory(this), - new DeadlineFilterFactory(this), + new CallCredentialsFilterFactory(this), new DeadlineFilterFactory(this), new MetadataStatusFilterFactory(this) ]); this.currentBackoffDeadline = new Date(); @@ -223,60 +239,60 @@ export class Http2Channel extends EventEmitter implements Channel { // Build user-agent string. this.userAgent = [ - options['grpc.primary_user_agent'], - `grpc-node-js/${clientVersion}`, + options['grpc.primary_user_agent'], `grpc-node-js/${clientVersion}`, options['grpc.secondary_user_agent'] - ].filter(e => e).join(' '); // remove falsey values first + ].filter(e => e).join(' '); // remove falsey values first } private startHttp2Stream( - authority: string, - methodName: string, - stream: Http2CallStream, + authority: string, methodName: string, stream: Http2CallStream, metadata: Metadata) { - let finalMetadata: Promise = + const finalMetadata: Promise = stream.filterStack.sendMetadata(Promise.resolve(metadata.clone())); Promise.all([finalMetadata, this.connect()]) - .then(([metadataValue]) => { - let headers = metadataValue.toHttp2Headers(); - headers[HTTP2_HEADER_AUTHORITY] = authority; - headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; - headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; - headers[HTTP2_HEADER_METHOD] = 'POST'; - headers[HTTP2_HEADER_PATH] = methodName; - headers[HTTP2_HEADER_TE] = 'trailers'; - if (this.connectivityState === ConnectivityState.READY) { - const session: http2.ClientHttp2Session = this.subChannel!; - // Prevent the HTTP/2 session from keeping the process alive. - // Note: this function is only available in Node 9 - session.unref(); - stream.attachHttp2Stream(session.request(headers)); - } else { - /* In this case, we lost the connection while finalizing - * metadata. That should be very unusual */ - setImmediate(() => { - this.startHttp2Stream(authority, methodName, stream, metadata); - }); - } - }).catch((error: Error & { code: number }) => { - // We assume the error code isn't 0 (Status.OK) - stream.cancelWithStatus(error.code || Status.UNKNOWN, - `Getting metadata from plugin failed with error: ${error.message}`); - }); + .then(([metadataValue]) => { + const headers = metadataValue.toHttp2Headers(); + headers[HTTP2_HEADER_AUTHORITY] = authority; + headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; + headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; + headers[HTTP2_HEADER_METHOD] = 'POST'; + headers[HTTP2_HEADER_PATH] = methodName; + headers[HTTP2_HEADER_TE] = 'trailers'; + if (this.connectivityState === ConnectivityState.READY) { + const session: http2.ClientHttp2Session = this.subChannel!; + // Prevent the HTTP/2 session from keeping the process alive. + // Note: this function is only available in Node 9 + session.unref(); + stream.attachHttp2Stream(session.request(headers)); + } else { + /* In this case, we lost the connection while finalizing + * metadata. That should be very unusual */ + setImmediate(() => { + this.startHttp2Stream(authority, methodName, stream, metadata); + }); + } + }) + .catch((error: Error&{code: number}) => { + // We assume the error code isn't 0 (Status.OK) + stream.cancelWithStatus( + error.code || Status.UNKNOWN, + `Getting metadata from plugin failed with error: ${ + error.message}`); + }); } createStream(methodName: string, metadata: Metadata, options: CallOptions): - CallStream { + CallStream { if (this.connectivityState === ConnectivityState.SHUTDOWN) { throw new Error('Channel has been shut down'); } - let finalOptions: CallStreamOptions = { + const finalOptions: CallStreamOptions = { deadline: options.deadline === undefined ? Infinity : options.deadline, credentials: options.credentials || CallCredentials.createEmpty(), flags: options.flags || 0, host: options.host || this.defaultAuthority }; - let stream: Http2CallStream = + const stream: Http2CallStream = new Http2CallStream(methodName, finalOptions, this.filterStackFactory); this.startHttp2Stream(finalOptions.host, methodName, stream, metadata); return stream; @@ -297,7 +313,8 @@ export class Http2Channel extends EventEmitter implements Channel { // been (connectivityState === IDLE). if (!this.connecting) { this.connecting = new Promise((resolve, reject) => { - this.transitionToState([ConnectivityState.IDLE], ConnectivityState.CONNECTING); + this.transitionToState( + [ConnectivityState.IDLE], ConnectivityState.CONNECTING); const onConnect = () => { this.connecting = null; this.removeListener('shutdown', onShutdown); @@ -324,9 +341,11 @@ export class Http2Channel extends EventEmitter implements Channel { if (this.connectivityState === ConnectivityState.SHUTDOWN) { throw new Error('Channel has been shut down'); } - this.transitionToState([ConnectivityState.CONNECTING, - ConnectivityState.READY, - ConnectivityState.TRANSIENT_FAILURE, - ConnectivityState.IDLE], ConnectivityState.SHUTDOWN); + this.transitionToState( + [ + ConnectivityState.CONNECTING, ConnectivityState.READY, + ConnectivityState.TRANSIENT_FAILURE, ConnectivityState.IDLE + ], + ConnectivityState.SHUTDOWN); } } diff --git a/packages/grpc-js-core/src/client.ts b/packages/grpc-js-core/src/client.ts index b120fcc7..39ff9fd9 100644 --- a/packages/grpc-js-core/src/client.ts +++ b/packages/grpc-js-core/src/client.ts @@ -21,7 +21,7 @@ export interface UnaryCallback { * clients. */ export class Client { - private readonly [kChannel]: Channel; + private readonly[kChannel]: Channel; constructor( address: string, credentials: ChannelCredentials, options: Partial = {}) { @@ -34,24 +34,26 @@ export class Client { waitForReady(deadline: Date|number, callback: (error: Error|null) => void): void { - let cb: (error: Error|null) => void = once(callback); - let callbackCalled = false; - let timer: NodeJS.Timer | null = null; - this[kChannel].connect().then(() => { - if (timer) { - clearTimeout(timer); - } - cb(null); - }, (err: Error) => { - // Rejection occurs if channel is shut down first. - if (timer) { - clearTimeout(timer); - } - cb(err); - }); + const cb: (error: Error|null) => void = once(callback); + const callbackCalled = false; + let timer: NodeJS.Timer|null = null; + this[kChannel].connect().then( + () => { + if (timer) { + clearTimeout(timer); + } + cb(null); + }, + (err: Error) => { + // Rejection occurs if channel is shut down first. + if (timer) { + clearTimeout(timer); + } + cb(err); + }); if (deadline !== Infinity) { let timeout: number; - let now: number = (new Date).getTime(); + const now: number = (new Date()).getTime(); if (deadline instanceof Date) { timeout = deadline.getTime() - now; } else { @@ -94,7 +96,8 @@ export class Client { if (status.code === Status.OK) { callback(null, responseMessage as ResponseType); } else { - const error: ServiceError = Object.assign(new Error(status.details), status); + const error: ServiceError = + Object.assign(new Error(status.details), status); callback(error); } }); @@ -156,7 +159,7 @@ export class Client { const call: CallStream = this[kChannel].createStream(method, metadata, options); const message: Buffer = serialize(argument); - const writeObj: WriteObject = {message: message}; + const writeObj: WriteObject = {message}; writeObj.flags = options.flags; call.write(writeObj); call.end(); @@ -238,7 +241,7 @@ export class Client { const call: CallStream = this[kChannel].createStream(method, metadata, options); const message: Buffer = serialize(argument); - const writeObj: WriteObject = {message: message}; + const writeObj: WriteObject = {message}; writeObj.flags = options.flags; call.write(writeObj); call.end(); diff --git a/packages/grpc-js-core/src/deadline-filter.ts b/packages/grpc-js-core/src/deadline-filter.ts index 428ed8a9..2424039e 100644 --- a/packages/grpc-js-core/src/deadline-filter.ts +++ b/packages/grpc-js-core/src/deadline-filter.ts @@ -4,14 +4,14 @@ import {Status} from './constants'; import {BaseFilter, Filter, FilterFactory} from './filter'; import {Metadata} from './metadata'; -const units: [string, number][] = +const units: Array<[string, number]> = [['m', 1], ['S', 1000], ['M', 60 * 1000], ['H', 60 * 60 * 1000]]; function getDeadline(deadline: number) { - let now = (new Date()).getTime(); - let timeoutMs = Math.max(deadline - now, 0); - for (let [unit, factor] of units) { - let amount = timeoutMs / factor; + const now = (new Date()).getTime(); + const timeoutMs = Math.max(deadline - now, 0); + for (const [unit, factor] of units) { + const amount = timeoutMs / factor; if (amount < 1e8) { return String(Math.ceil(amount)) + unit; } @@ -20,19 +20,19 @@ function getDeadline(deadline: number) { } export class DeadlineFilter extends BaseFilter implements Filter { - private timer: NodeJS.Timer | null = null; + private timer: NodeJS.Timer|null = null; private deadline: number; constructor( private readonly channel: Http2Channel, private readonly callStream: CallStream) { super(); - let callDeadline = callStream.getDeadline(); + const callDeadline = callStream.getDeadline(); if (callDeadline instanceof Date) { this.deadline = callDeadline.getTime(); } else { this.deadline = callDeadline; } - let now: number = (new Date()).getTime(); + const now: number = (new Date()).getTime(); let timeout = this.deadline - now; if (timeout < 0) { timeout = 0; diff --git a/packages/grpc-js-core/src/events.ts b/packages/grpc-js-core/src/events.ts index 591120d1..ad96efd5 100644 --- a/packages/grpc-js-core/src/events.ts +++ b/packages/grpc-js-core/src/events.ts @@ -23,7 +23,9 @@ export interface EmitterAugmentation2 { emit(event: Name, arg1: Arg1, arg2: Arg2): boolean; on(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): this; once(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): this; - prependListener(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): this; - prependOnceListener(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): this; + prependListener(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): + this; + prependOnceListener(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): + this; removeListener(event: Name, listener: (arg1: Arg1, arg2: Arg2) => void): this; } diff --git a/packages/grpc-js-core/src/filter-stack.ts b/packages/grpc-js-core/src/filter-stack.ts index 7a661692..66337c3a 100644 --- a/packages/grpc-js-core/src/filter-stack.ts +++ b/packages/grpc-js-core/src/filter-stack.ts @@ -25,7 +25,7 @@ export class FilterStack implements Filter { } export class FilterStackFactory implements FilterFactory { - constructor(private readonly factories: FilterFactory[]) {} + constructor(private readonly factories: Array>) {} createFilter(callStream: CallStream): FilterStack { return new FilterStack( diff --git a/packages/grpc-js-core/src/index.ts b/packages/grpc-js-core/src/index.ts index 8c9cb32c..9b6cea51 100644 --- a/packages/grpc-js-core/src/index.ts +++ b/packages/grpc-js-core/src/index.ts @@ -1,68 +1,78 @@ -import { CallCredentials } from './call-credentials'; -import { ChannelCredentials } from './channel-credentials'; -import { Client } from './client'; -import { Status} from './constants'; -import { makeClientConstructor, loadPackageDefinition } from './make-client'; -import { Metadata } from './metadata'; -import { IncomingHttpHeaders } from 'http'; +import {IncomingHttpHeaders} from 'http'; + +import {CallCredentials} from './call-credentials'; +import {ChannelCredentials} from './channel-credentials'; +import {Client} from './client'; +import {Status} from './constants'; +import {loadPackageDefinition, makeClientConstructor} from './make-client'; +import {Metadata} from './metadata'; export interface OAuth2Client { - getRequestMetadata: (url: string, callback: (err: Error|null, headers?: { Authorization: string }) => void) => void; + getRequestMetadata: (url: string, callback: (err: Error|null, headers?: { + Authorization: string + }) => void) => void; } /**** Client Credentials ****/ // Using assign only copies enumerable properties, which is what we want -export const credentials = Object.assign({ - /** - * 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) => { - googleCredentials.getRequestMetadata(options.service_url, (err, headers) => { - if (err) { - callback(err); - return; - } - const metadata = new Metadata(); - metadata.add('authorization', headers!.Authorization); - callback(null, metadata); - }); - }); - }, +export const credentials = Object.assign( + { + /** + * 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) => { + googleCredentials.getRequestMetadata( + options.service_url, (err, headers) => { + if (err) { + callback(err); + return; + } + const metadata = new Metadata(); + metadata.add('authorization', headers!.Authorization); + callback(null, metadata); + }); + }); + }, - /** - * Combine a ChannelCredentials with any number of CallCredentials into a - * single ChannelCredentials object. - * @param channelCredentials The ChannelCredentials object. - * @param callCredentials Any number of CallCredentials objects. - * @return The resulting ChannelCredentials object. - */ - combineChannelCredentials: ( - channelCredentials: ChannelCredentials, - ...callCredentials: CallCredentials[]): ChannelCredentials => { - return callCredentials.reduce((acc, other) => acc.compose(other), channelCredentials); - }, + /** + * Combine a ChannelCredentials with any number of CallCredentials into a + * single ChannelCredentials object. + * @param channelCredentials The ChannelCredentials object. + * @param callCredentials Any number of CallCredentials objects. + * @return The resulting ChannelCredentials object. + */ + combineChannelCredentials: + (channelCredentials: ChannelCredentials, + ...callCredentials: CallCredentials[]): ChannelCredentials => { + return callCredentials.reduce( + (acc, other) => acc.compose(other), channelCredentials); + }, - /** - * Combine any number of CallCredentials into a single CallCredentials object. - * @param first The first CallCredentials object. - * @param additional Any number of additional CallCredentials objects. - * @return The resulting CallCredentials object. - */ - combineCallCredentials: ( - first: CallCredentials, - ...additional: CallCredentials[]): CallCredentials => { - return additional.reduce((acc, other) => acc.compose(other), first); - } -}, ChannelCredentials, CallCredentials); + /** + * Combine any number of CallCredentials into a single CallCredentials + * object. + * @param first The first CallCredentials object. + * @param additional Any number of additional CallCredentials objects. + * @return The resulting CallCredentials object. + */ + combineCallCredentials: ( + first: CallCredentials, ...additional: CallCredentials[]): + CallCredentials => { + return additional.reduce((acc, other) => acc.compose(other), first); + } + }, + ChannelCredentials, CallCredentials); /**** Metadata ****/ -export { Metadata }; +export {Metadata}; /**** Constants ****/ @@ -86,47 +96,63 @@ export { */ export const closeClient = (client: Client) => client.close(); -export const waitForClientReady = (client: Client, deadline: Date|number, callback: (error: Error | null) => void) => client.waitForReady(deadline, callback); +export const waitForClientReady = + (client: Client, deadline: Date|number, + callback: (error: Error|null) => void) => + client.waitForReady(deadline, callback); /**** Unimplemented function stubs ****/ +/* tslint:disable:no-any variable-name */ + export const loadObject = (value: any, options: any) => { - throw new Error('Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); -} + throw new Error( + 'Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); +}; export const load = (filename: any, format: any, options: any) => { - throw new Error('Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); -} + throw new Error( + 'Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead'); +}; export const setLogger = (logger: any) => { throw new Error('Not yet implemented'); -} +}; export const setLogVerbosity = (verbosity: any) => { throw new Error('Not yet implemented'); -} +}; export const Server = (options: any) => { throw new Error('Not yet implemented'); -} +}; export const ServerCredentials = { - createSsl: (rootCerts: any, keyCertPairs: any, checkClientCertificate: any) => { - throw new Error('Not yet implemented'); - }, + createSsl: + (rootCerts: any, keyCertPairs: any, checkClientCertificate: any) => { + throw new Error('Not yet implemented'); + }, createInsecure: () => { throw new Error('Not yet implemented'); } -} +}; export const getClientChannel = (client: any) => { throw new Error('Not available in this library'); -} +}; -export const StatusBuilder = () => { throw new Error('Not yet implemented'); } +export const StatusBuilder = () => { + throw new Error('Not yet implemented'); +}; -export const ListenerBuilder = () => { throw new Error('Not yet implemented'); } +export const ListenerBuilder = () => { + throw new Error('Not yet implemented'); +}; -export const InterceptorBuilder = () => { throw new Error('Not yet implemented'); } +export const InterceptorBuilder = () => { + throw new Error('Not yet implemented'); +}; -export const InterceptingCall = () => { throw new Error('Not yet implemented'); } +export const InterceptingCall = () => { + throw new Error('Not yet implemented'); +}; diff --git a/packages/grpc-js-core/src/make-client.ts b/packages/grpc-js-core/src/make-client.ts index f5433f57..7d82444f 100644 --- a/packages/grpc-js-core/src/make-client.ts +++ b/packages/grpc-js-core/src/make-client.ts @@ -1,17 +1,14 @@ -import { Metadata } from "./metadata"; -import { Client, UnaryCallback } from "./client"; -import { CallOptions } from "./call-stream"; import * as _ from 'lodash'; -import { ChannelCredentials } from "./channel-credentials"; -import { ChannelOptions } from "./channel"; -export interface Serialize { - (value: T): Buffer; -} +import {CallOptions} from './call-stream'; +import {ChannelOptions} from './channel'; +import {ChannelCredentials} from './channel-credentials'; +import {Client, UnaryCallback} from './client'; +import {Metadata} from './metadata'; -export interface Deserialize { - (bytes: Buffer): T; -} +export interface Serialize { (value: T): Buffer; } + +export interface Deserialize { (bytes: Buffer): T; } export interface MethodDefinition { path: string; @@ -28,18 +25,11 @@ export interface ServiceDefinition { [index: string]: MethodDefinition; } -export interface PackageDefinition { - [index: string]: ServiceDefinition; -} +export interface PackageDefinition { [index: string]: ServiceDefinition; } -function getDefaultValues(metadata?: Metadata, options?: T): { - metadata: Metadata; - options: Partial; -} { - return { - metadata: metadata || new Metadata(), - options: options || {} - }; +function getDefaultValues(metadata?: Metadata, options?: T): + {metadata: Metadata; options: Partial;} { + return {metadata: metadata || new Metadata(), options: options || {}}; } /** @@ -60,9 +50,9 @@ export interface ServiceClient extends Client { export interface ServiceClientConstructor { new(address: string, credentials: ChannelCredentials, - options?: Partial): ServiceClient; + options?: Partial): ServiceClient; service: ServiceDefinition; -}; +} /** * Creates a constructor for a client with the given methods, as specified in @@ -111,23 +101,24 @@ export function makeClientConstructor( } const serialize = attrs.requestSerialize; const deserialize = attrs.responseDeserialize; - const methodFunc = _.partial(requesterFuncs[methodType], attrs.path, - serialize, deserialize); + const methodFunc = _.partial( + requesterFuncs[methodType], attrs.path, serialize, deserialize); ServiceClientImpl.prototype[name] = methodFunc; // Associate all provided attributes with the method _.assign(ServiceClientImpl.prototype[name], attrs); if (attrs.originalName) { - ServiceClientImpl.prototype[attrs.originalName] = ServiceClientImpl.prototype[name]; + ServiceClientImpl.prototype[attrs.originalName] = + ServiceClientImpl.prototype[name]; } }); ServiceClientImpl.service = methods; return ServiceClientImpl; -}; +} export type GrpcObject = { - [index: string]: GrpcObject | ServiceClientConstructor; + [index: string]: GrpcObject|ServiceClientConstructor; }; /** @@ -135,20 +126,23 @@ export type GrpcObject = { * @param packageDef The package definition object. * @return The resulting gRPC object. */ -export function loadPackageDefinition(packageDef: PackageDefinition): GrpcObject { +export function loadPackageDefinition(packageDef: PackageDefinition): + GrpcObject { const result: GrpcObject = {}; for (const serviceFqn in packageDef) { - const service = packageDef[serviceFqn]; - const nameComponents = serviceFqn.split('.'); - const serviceName = nameComponents[nameComponents.length-1]; - let current = result; - for (const packageName of nameComponents.slice(0, -1)) { - if (!current[packageName]) { - current[packageName] = {}; + if (packageDef.hasOwnProperty(serviceFqn)) { + const service = packageDef[serviceFqn]; + const nameComponents = serviceFqn.split('.'); + const serviceName = nameComponents[nameComponents.length - 1]; + let current = result; + for (const packageName of nameComponents.slice(0, -1)) { + if (!current[packageName]) { + current[packageName] = {}; + } + current = current[packageName] as GrpcObject; } - current = current[packageName] as GrpcObject; + current[serviceName] = makeClientConstructor(service, serviceName, {}); } - current[serviceName] = makeClientConstructor(service, serviceName, {}); } return result; } diff --git a/packages/grpc-js-core/src/metadata-status-filter.ts b/packages/grpc-js-core/src/metadata-status-filter.ts index 43d42ea6..4bb869b7 100644 --- a/packages/grpc-js-core/src/metadata-status-filter.ts +++ b/packages/grpc-js-core/src/metadata-status-filter.ts @@ -1,19 +1,20 @@ import {CallStream} from './call-stream'; -import {Channel} from './channel'; -import {BaseFilter, Filter, FilterFactory} from './filter'; import {StatusObject} from './call-stream'; +import {Channel} from './channel'; import {Status} from './constants'; +import {BaseFilter, Filter, FilterFactory} from './filter'; export class MetadataStatusFilter extends BaseFilter implements Filter { async receiveTrailers(status: Promise): Promise { - let { code, details, metadata } = await status; + // tslint:disable-next-line:prefer-const + let {code, details, metadata} = await status; if (code !== Status.UNKNOWN) { // we already have a known status, so don't assign a new one. - return { code, details, metadata }; + return {code, details, metadata}; } const metadataMap = metadata.getMap(); if (typeof metadataMap['grpc-status'] === 'string') { - let receivedCode = Number(metadataMap['grpc-status']); + const receivedCode = Number(metadataMap['grpc-status']); if (receivedCode in Status) { code = receivedCode; } @@ -23,7 +24,7 @@ export class MetadataStatusFilter extends BaseFilter implements Filter { details = decodeURI(metadataMap['grpc-message'] as string); metadata.remove('grpc-message'); } - return { code, details, metadata }; + return {code, details, metadata}; } } diff --git a/packages/grpc-js-core/src/metadata.ts b/packages/grpc-js-core/src/metadata.ts index 84e9160e..3f4b19d0 100644 --- a/packages/grpc-js-core/src/metadata.ts +++ b/packages/grpc-js-core/src/metadata.ts @@ -1,9 +1,9 @@ import * as http2 from 'http2'; import {forOwn} from 'lodash'; -export type MetadataValue = string | Buffer; +export type MetadataValue = string|Buffer; -export interface MetadataObject { [key: string]: Array; } +export interface MetadataObject { [key: string]: MetadataValue[]; } function cloneMetadataObject(repr: MetadataObject): MetadataObject { const result: MetadataObject = {}; @@ -113,7 +113,7 @@ export class Metadata { * @param key The key whose value should be retrieved. * @return A list of values associated with the given key. */ - get(key: string): Array { + get(key: string): MetadataValue[] { key = normalizeKey(key); validate(key); if (Object.prototype.hasOwnProperty.call(this.internalRepr, key)) { @@ -144,7 +144,7 @@ export class Metadata { * @return The newly cloned object. */ clone(): Metadata { - let newMetadata = new Metadata(); + const newMetadata = new Metadata(); newMetadata.internalRepr = cloneMetadataObject(this.internalRepr); return newMetadata; } @@ -181,7 +181,7 @@ export class Metadata { }); return result; } - + // For compatibility with the other Metadata implementation private _getCoreRepresentation() { return this.internalRepr; @@ -201,8 +201,9 @@ export class Metadata { result.add(key, Buffer.from(value, 'base64')); }); } else if (values !== undefined) { - values.split(',').map(v => v.trim()).forEach(v => - result.add(key, Buffer.from(v, 'base64'))); + values.split(',') + .map(v => v.trim()) + .forEach(v => result.add(key, Buffer.from(v, 'base64'))); } } else { if (Array.isArray(values)) { @@ -210,8 +211,7 @@ export class Metadata { result.add(key, value); }); } else if (values !== undefined) { - values.split(',').map(v => v.trim()).forEach(v => - result.add(key, v)); + values.split(',').map(v => v.trim()).forEach(v => result.add(key, v)); } } }); diff --git a/packages/grpc-js-core/src/object-stream.ts b/packages/grpc-js-core/src/object-stream.ts index 48988daa..556883c6 100644 --- a/packages/grpc-js-core/src/object-stream.ts +++ b/packages/grpc-js-core/src/object-stream.ts @@ -1,14 +1,15 @@ import {Duplex, Readable, Writable} from 'stream'; import {EmitterAugmentation1} from './events'; +// tslint:disable:no-any + export interface IntermediateObjectReadable extends Readable { read(size?: number): any&T; } export type ObjectReadable = { read(size?: number): T; -} & EmitterAugmentation1<'data', T> - & IntermediateObjectReadable; +}&EmitterAugmentation1<'data', T>&IntermediateObjectReadable; export interface IntermediateObjectWritable extends Writable { _write(chunk: any&T, encoding: string, callback: Function): void; @@ -39,4 +40,4 @@ export type ObjectDuplex = { end(): void; end(chunk: T, cb?: Function): void; end(chunk: T, encoding?: any, cb?: Function): void; -} & Duplex & ObjectWritable & ObjectReadable; +}&Duplex&ObjectWritable&ObjectReadable; diff --git a/packages/grpc-js-core/test/common.ts b/packages/grpc-js-core/test/common.ts index 487ced1f..c36d6fc4 100644 --- a/packages/grpc-js-core/test/common.ts +++ b/packages/grpc-js-core/test/common.ts @@ -4,6 +4,7 @@ export function mockFunction(): never { throw new Error('Not implemented'); } +// tslint:disable-next-line:no-namespace export namespace assert2 { const toCall = new Map<() => void, number>(); const afterCallsQueue: Array<() => void> = []; @@ -17,7 +18,9 @@ export namespace assert2 { try { return fn(); } catch (e) { - assert.throws(() => {throw e}); + assert.throws(() => { + throw e; + }); throw e; // for type safety only } } @@ -42,7 +45,9 @@ export namespace assert2 { * Wraps a function to keep track of whether it was called or not. * @param fn The function to wrap. */ - export function mustCall(fn: (...args: any[]) => T): (...args: any[]) => T { + // tslint:disable:no-any + export function mustCall(fn: (...args: any[]) => T): + (...args: any[]) => T { const existingValue = toCall.get(fn); if (existingValue !== undefined) { toCall.set(fn, existingValue + 1); @@ -62,6 +67,7 @@ export namespace assert2 { return result; }; } + // tslint:enable:no-any /** * Calls the given function when every function that was wrapped with diff --git a/packages/grpc-js-core/test/test-call-credentials.ts b/packages/grpc-js-core/test/test-call-credentials.ts index 64cfe140..fffe5a19 100644 --- a/packages/grpc-js-core/test/test-call-credentials.ts +++ b/packages/grpc-js-core/test/test-call-credentials.ts @@ -27,7 +27,8 @@ describe('CallCredentials', () => { describe('createFromMetadataGenerator', () => { it('should accept a metadata generator', () => { assert.doesNotThrow( - () => CallCredentials.createFromMetadataGenerator(generateFromServiceURL)); + () => CallCredentials.createFromMetadataGenerator( + generateFromServiceURL)); }); }); @@ -58,11 +59,12 @@ describe('CallCredentials', () => { describe('generateMetadata', () => { it('should call the function passed to createFromMetadataGenerator', async () => { - const callCredentials = - CallCredentials.createFromMetadataGenerator(generateFromServiceURL); + const callCredentials = CallCredentials.createFromMetadataGenerator( + generateFromServiceURL); let metadata: Metadata; try { - metadata = await callCredentials.generateMetadata({service_url: 'foo'}); + metadata = + await callCredentials.generateMetadata({service_url: 'foo'}); } catch (err) { throw err; } diff --git a/packages/grpc-js-core/test/test-call-stream.ts b/packages/grpc-js-core/test/test-call-stream.ts index f3a4f617..aff6ed63 100644 --- a/packages/grpc-js-core/test/test-call-stream.ts +++ b/packages/grpc-js-core/test/test-call-stream.ts @@ -1,32 +1,33 @@ import * as assert from 'assert'; -import { CallCredentials } from '../src/call-credentials'; -import { Http2CallStream } from '../src/call-stream'; -import { mockFunction, assert2 } from './common'; -import { Status } from '../src/constants'; -import { EventEmitter } from 'events'; -import { FilterStackFactory } from '../src/filter-stack'; +import {EventEmitter} from 'events'; import * as http2 from 'http2'; -import { forOwn, range } from 'lodash'; -import { Metadata } from '../src/metadata'; +import {forOwn, range} from 'lodash'; import * as stream from 'stream'; +import {CallCredentials} from '../src/call-credentials'; +import {Http2CallStream} from '../src/call-stream'; +import {Status} from '../src/constants'; +import {FilterStackFactory} from '../src/filter-stack'; +import {Metadata} from '../src/metadata'; + +import {assert2, mockFunction} from './common'; + interface DataFrames { - payload: Buffer, - frameLengths: number[] + payload: Buffer; + frameLengths: number[]; } -const { - HTTP2_HEADER_STATUS -} = http2.constants; +const {HTTP2_HEADER_STATUS} = http2.constants; function serialize(data: string): Buffer { const header: Buffer = Buffer.alloc(5); - header.writeUInt8(0, 0); // TODO: Uncompressed only + header.writeUInt8(0, 0); // TODO: Uncompressed only header.writeInt32BE(data.length, 1); return Buffer.concat([header, Buffer.from(data, 'utf8')]); } -class ClientHttp2StreamMock extends stream.Duplex implements http2.ClientHttp2Stream { +class ClientHttp2StreamMock extends stream.Duplex implements + http2.ClientHttp2Stream { constructor(private readonly dataFrames: DataFrames) { super(); } @@ -38,13 +39,15 @@ class ClientHttp2StreamMock extends stream.Duplex implements http2.ClientHttp2St } bytesRead = 0; dataFrame = 0; - aborted: boolean = false; - closed: boolean = false; - destroyed: boolean = false; - pending: boolean = false; - rstCode: number = 0; + aborted = false; + closed = false; + destroyed = false; + pending = false; + rstCode = 0; + // tslint:disable:no-any session: http2.Http2Session = {} as any; state: http2.StreamState = {} as any; + // tslint:enable:no-any close = mockFunction; priority = mockFunction; rstStream = mockFunction; @@ -58,7 +61,7 @@ class ClientHttp2StreamMock extends stream.Duplex implements http2.ClientHttp2St if (this.dataFrame === this.dataFrames.frameLengths.length) { if (this.bytesRead < this.dataFrames.payload.length) { this.push(this.dataFrames.payload.slice( - this.bytesRead, this.dataFrames.payload.length)); + this.bytesRead, this.dataFrames.payload.length)); } this.push(null); return; @@ -66,7 +69,7 @@ class ClientHttp2StreamMock extends stream.Duplex implements http2.ClientHttp2St const from = this.bytesRead; this.bytesRead += this.dataFrames.frameLengths[this.dataFrame++]; this.push(this.dataFrames.payload.slice(from, this.bytesRead)); - }; + } _write(chunk: Buffer, encoding: string, cb: Function) { this.emit('write', chunk); cb(); @@ -81,28 +84,28 @@ describe('CallStream', () => { host: '' }; const filterStackFactory = new FilterStackFactory([]); - const message = 'eat this message'; // 16 bytes + const message = 'eat this message'; // 16 bytes beforeEach(() => { assert2.clearMustCalls(); }); - it('should emit a metadata event when it receives a response event', (done) => { - const responseMetadata = new Metadata(); - responseMetadata.add('key', 'value'); - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); + it('should emit a metadata event when it receives a response event', + (done) => { + const responseMetadata = new Metadata(); + responseMetadata.add('key', 'value'); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.alloc(0), - frameLengths: [] - }); - callStream.once('metadata', assert2.mustCall((metadata) => { - assert.deepStrictEqual(metadata.get('key'), ['value']); - })); - callStream.attachHttp2Stream(http2Stream); - http2Stream.emitResponse(200, responseMetadata); - assert2.afterMustCallsSatisfied(done); - }); + const http2Stream = new ClientHttp2StreamMock( + {payload: Buffer.alloc(0), frameLengths: []}); + callStream.once('metadata', assert2.mustCall((metadata) => { + assert.deepStrictEqual(metadata.get('key'), ['value']); + })); + callStream.attachHttp2Stream(http2Stream); + http2Stream.emitResponse(200, responseMetadata); + assert2.afterMustCallsSatisfied(done); + }); describe('should end a call with an error if a stream was closed', () => { const c = http2.constants; @@ -126,14 +129,13 @@ describe('CallStream', () => { keys.forEach((key) => { const value = errorCodeMapping[key]; // A null value indicates: behavior isn't specified, so skip this test. - let maybeSkip = (fn: typeof it) => value ? fn : fn.skip; + const maybeSkip = (fn: typeof it) => value ? fn : fn.skip; maybeSkip(it)(`for error code ${key}`, () => { return new Promise((resolve, reject) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.alloc(0), - frameLengths: [] - }); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = new ClientHttp2StreamMock( + {payload: Buffer.alloc(0), frameLengths: []}); callStream.attachHttp2Stream(http2Stream); callStream.once('status', (status) => { try { @@ -150,7 +152,8 @@ describe('CallStream', () => { }); it('should have functioning getters', (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); assert.strictEqual(callStream.getDeadline(), callStreamArgs.deadline); assert.strictEqual(callStream.getCredentials(), callStreamArgs.credentials); assert.strictEqual(callStream.getStatus(), null); @@ -166,11 +169,10 @@ describe('CallStream', () => { describe('attachHttp2Stream', () => { it('should handle an empty message', (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: serialize(''), - frameLengths: [] - }); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = + new ClientHttp2StreamMock({payload: serialize(''), frameLengths: []}); callStream.once('data', assert2.mustCall((buffer) => { assert.strictEqual(buffer.toString('utf8'), ''); })); @@ -178,65 +180,57 @@ describe('CallStream', () => { assert2.afterMustCallsSatisfied(done); }); - [ - { - description: 'all data is supplied in a single frame', - frameLengths: [] - }, - { - description: 'frames are split along header field delimiters', - frameLengths: [1, 4] - }, - { - description: 'portions of header fields are split between different frames', - frameLengths: [2, 1, 1, 4] - }, - { - description: 'frames are split into bytes', - frameLengths: range(0, 20).map(() => 1) - } - ].forEach((testCase: { description: string, frameLengths: number[] }) => { - it(`should handle a short message where ${testCase.description}`, (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: serialize(message), // 21 bytes - frameLengths: testCase.frameLengths - }); - callStream.once('data', assert2.mustCall((buffer) => { - assert.strictEqual(buffer.toString('utf8'), message); - })); - callStream.once('end', assert2.mustCall(() => {})); - callStream.attachHttp2Stream(http2Stream); - assert2.afterMustCallsSatisfied(done); - }); + [{description: 'all data is supplied in a single frame', frameLengths: []}, + { + description: 'frames are split along header field delimiters', + frameLengths: [1, 4] + }, + { + description: + 'portions of header fields are split between different frames', + frameLengths: [2, 1, 1, 4] + }, + { + description: 'frames are split into bytes', + frameLengths: range(0, 20).map(() => 1) + }].forEach((testCase: {description: string, frameLengths: number[]}) => { + it(`should handle a short message where ${testCase.description}`, + (done) => { + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = new ClientHttp2StreamMock({ + payload: serialize(message), // 21 bytes + frameLengths: testCase.frameLengths + }); + callStream.once('data', assert2.mustCall((buffer) => { + assert.strictEqual(buffer.toString('utf8'), message); + })); + callStream.once('end', assert2.mustCall(() => {})); + callStream.attachHttp2Stream(http2Stream); + assert2.afterMustCallsSatisfied(done); + }); }); - [ - { - description: 'all data is supplied in a single frame', - frameLengths: [] - }, - { - description: 'frames are split between delimited messages', - frameLengths: [21] - }, - { - description: 'frames are split within messages', - frameLengths: [10, 22] - }, - { - description: 'part of 2nd message\'s header is in first frame', - frameLengths: [24] - }, - { - description: 'frames are split into bytes', - frameLengths: range(0, 41).map(() => 1) - } - ].forEach((testCase: { description: string, frameLengths: number[] }) => { + [{description: 'all data is supplied in a single frame', frameLengths: []}, + { + description: 'frames are split between delimited messages', + frameLengths: [21] + }, + {description: 'frames are split within messages', frameLengths: [10, 22]}, + { + description: 'part of 2nd message\'s header is in first frame', + frameLengths: [24] + }, + { + description: 'frames are split into bytes', + frameLengths: range(0, 41).map(() => 1) + }].forEach((testCase: {description: string, frameLengths: number[]}) => { it(`should handle two messages where ${testCase.description}`, (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.concat([serialize(message), serialize(message)]), // 42 bytes + payload: Buffer.concat( + [serialize(message), serialize(message)]), // 42 bytes frameLengths: testCase.frameLengths }); callStream.once('data', assert2.mustCall((buffer) => { @@ -252,11 +246,10 @@ describe('CallStream', () => { }); it('should send buffered writes', (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.alloc(0), - frameLengths: [] - }); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = new ClientHttp2StreamMock( + {payload: Buffer.alloc(0), frameLengths: []}); let streamFlushed = false; http2Stream.once('write', assert2.mustCall((chunk: Buffer) => { const dataLength = chunk.readInt32BE(1); @@ -265,9 +258,7 @@ describe('CallStream', () => { assert.strictEqual(encodedMessage, message); streamFlushed = true; })); - callStream.write({ - message: Buffer.from(message) - }, assert2.mustCall(() => { + callStream.write({message: Buffer.from(message)}, assert2.mustCall(() => { // Ensure this is called only after contents are written to http2Stream assert.ok(streamFlushed); })); @@ -276,32 +267,30 @@ describe('CallStream', () => { assert2.afterMustCallsSatisfied(done); }); - it('should cause data chunks in write calls afterward to be written to the given stream', (done) => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.alloc(0), - frameLengths: [] - }); - http2Stream.once('write', assert2.mustCall((chunk: Buffer) => { - const dataLength = chunk.readInt32BE(1); - const encodedMessage = chunk.slice(5).toString('utf8'); - assert.strictEqual(dataLength, message.length); - assert.strictEqual(encodedMessage, message); - })); - callStream.attachHttp2Stream(http2Stream); - callStream.write({ - message: Buffer.from(message) - }, assert2.mustCall(() => {})); - callStream.end(assert2.mustCall(() => {})); - assert2.afterMustCallsSatisfied(done); - }); + it('should cause data chunks in write calls afterward to be written to the given stream', + (done) => { + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = new ClientHttp2StreamMock( + {payload: Buffer.alloc(0), frameLengths: []}); + http2Stream.once('write', assert2.mustCall((chunk: Buffer) => { + const dataLength = chunk.readInt32BE(1); + const encodedMessage = chunk.slice(5).toString('utf8'); + assert.strictEqual(dataLength, message.length); + assert.strictEqual(encodedMessage, message); + })); + callStream.attachHttp2Stream(http2Stream); + callStream.write( + {message: Buffer.from(message)}, assert2.mustCall(() => {})); + callStream.end(assert2.mustCall(() => {})); + assert2.afterMustCallsSatisfied(done); + }); it('should handle underlying stream errors', () => { - const callStream = new Http2CallStream('foo', callStreamArgs, filterStackFactory); - const http2Stream = new ClientHttp2StreamMock({ - payload: Buffer.alloc(0), - frameLengths: [] - }); + const callStream = + new Http2CallStream('foo', callStreamArgs, filterStackFactory); + const http2Stream = new ClientHttp2StreamMock( + {payload: Buffer.alloc(0), frameLengths: []}); callStream.once('status', assert2.mustCall((status) => { assert.strictEqual(status.code, Status.INTERNAL); })); diff --git a/packages/grpc-js-core/test/test-channel-credentials.ts b/packages/grpc-js-core/test/test-channel-credentials.ts index 15dfbfac..aa9e2033 100644 --- a/packages/grpc-js-core/test/test-channel-credentials.ts +++ b/packages/grpc-js-core/test/test-channel-credentials.ts @@ -32,6 +32,7 @@ class CallCredentialsMock implements CallCredentials { } } +// tslint:disable-next-line:no-any const readFile: (...args: any[]) => Promise = promisify(fs.readFile); // A promise which resolves to loaded files in the form { ca, key, cert } const pFixtures = Promise From cf004c30a58ff037232062e82e59f3cd9e68648b Mon Sep 17 00:00:00 2001 From: Nikos Koumbakis Date: Sun, 15 Apr 2018 20:48:30 +0300 Subject: [PATCH 13/30] Update protobufjs version Fixes [ReDoS Vulnerability](https://github.com/dcodeIO/protobuf.js/releases/tag/6.8.6) --- packages/grpc-protobufjs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grpc-protobufjs/package.json b/packages/grpc-protobufjs/package.json index e15c31f0..1ed26975 100644 --- a/packages/grpc-protobufjs/package.json +++ b/packages/grpc-protobufjs/package.json @@ -41,7 +41,7 @@ "@types/lodash": "^4.14.104", "@types/node": "^9.4.6", "lodash": "^4.17.5", - "protobufjs": "^6.8.5" + "protobufjs": "^6.8.6" }, "devDependencies": { "clang-format": "^1.2.2", From ff16b66b6f31e517e3b0d177a6e7e26e73eaaf2b Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 30 Apr 2018 09:39:56 -0700 Subject: [PATCH 14/30] Don't upgrade npm in Windows tests --- run-tests.bat | 1 - 1 file changed, 1 deletion(-) diff --git a/run-tests.bat b/run-tests.bat index 5aeaa700..9a05432a 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -39,7 +39,6 @@ SET FAILED=0 for %%v in (4 6 7 8 9) do ( call nvm install %%v call nvm use %%v - call npm install -g npm @rem https://github.com/mapbox/node-pre-gyp/issues/362 call npm install -g node-gyp node -e "console.log(process.versions)" From 5405aa31f46ac25f016bbc8654e87fa685545e7b Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 30 Apr 2018 13:04:03 -0700 Subject: [PATCH 15/30] Upgrade npm on Node 4 --- run-tests.bat | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run-tests.bat b/run-tests.bat index 9a05432a..2b460ffa 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -39,6 +39,9 @@ SET FAILED=0 for %%v in (4 6 7 8 9) do ( call nvm install %%v call nvm use %%v + if "%%v"=="4" ( + npm install -g npm@5 + ) @rem https://github.com/mapbox/node-pre-gyp/issues/362 call npm install -g node-gyp node -e "console.log(process.versions)" From a63f534979a2fdaba7f4111be3aad9348a69e4c5 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 30 Apr 2018 13:31:12 -0700 Subject: [PATCH 16/30] Change 'include' to 'includeDirs' in proto-loader package --- packages/grpc-protobufjs/README.md | 2 +- packages/grpc-protobufjs/src/index.ts | 18 +++++++++--------- test/interop/interop_client.js | 2 +- test/interop/interop_server.js | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/grpc-protobufjs/README.md b/packages/grpc-protobufjs/README.md index 4e57faf4..307c635c 100644 --- a/packages/grpc-protobufjs/README.md +++ b/packages/grpc-protobufjs/README.md @@ -36,7 +36,7 @@ The options parameter is an object that can have the following optional properti | `arrays` | `true` or `false` | Set empty arrays for missing array values even if `defaults` is `false` Defaults to `false`. | `objects` | `true` or `false` | Set empty objects for missing object values even if `defaults` is `false` Defaults to `false`. | `oneofs` | `true` or `false` | Set virtual oneof properties to the present field's name. Defaults to `false`. -| `include` | An array of strings | A list of search paths for imported `.proto` files. +| `includeDirs` | An array of strings | A list of search paths for imported `.proto` files. The following options object closely approximates the existing behavior of `grpc.load`: diff --git a/packages/grpc-protobufjs/src/index.ts b/packages/grpc-protobufjs/src/index.ts index 85c2c941..5f443f98 100644 --- a/packages/grpc-protobufjs/src/index.ts +++ b/packages/grpc-protobufjs/src/index.ts @@ -48,7 +48,7 @@ export interface PackageDefinition { } export type Options = Protobuf.IParseOptions & Protobuf.IConversionOptions & { - include?: string[]; + includeDirs?: string[]; }; function joinName(baseName: string, name: string): string { @@ -154,15 +154,15 @@ function addIncludePathResolver(root: Protobuf.Root, includePaths: string[]) { * `defaults` is `false`. Defaults to `false`. * @param options.oneofs Set virtual oneof properties to the present field's * name - * @param options.include Paths to search for imported `.proto` files. + * @param options.includeDirs Paths to search for imported `.proto` files. */ export function load(filename: string, options: Options): Promise { const root: Protobuf.Root = new Protobuf.Root(); - if (!!options.include) { - if (!(options.include instanceof Array)) { - return Promise.reject(new Error('The include option must be an array')); + if (!!options.includeDirs) { + if (!(options.includeDirs instanceof Array)) { + return Promise.reject(new Error('The includeDirs option must be an array')); } - addIncludePathResolver(root, options.include as string[]); + addIncludePathResolver(root, options.includeDirs as string[]); } return root.load(filename, options).then((loadedRoot) => { loadedRoot.resolveAll(); @@ -172,11 +172,11 @@ export function load(filename: string, options: Options): Promise Date: Mon, 30 Apr 2018 14:00:42 -0700 Subject: [PATCH 17/30] Bump version to v1.11.0 --- packages/grpc-native-core/build.yaml | 2 +- packages/grpc-native-core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/grpc-native-core/build.yaml b/packages/grpc-native-core/build.yaml index 5703b3c8..55bf7a48 100644 --- a/packages/grpc-native-core/build.yaml +++ b/packages/grpc-native-core/build.yaml @@ -1,3 +1,3 @@ settings: '#': It's possible to have node_version here as a key to override the core's version. - 'node_version': 1.11.0-pre2 + 'node_version': 1.11.0 diff --git a/packages/grpc-native-core/package.json b/packages/grpc-native-core/package.json index c53db230..c112e772 100644 --- a/packages/grpc-native-core/package.json +++ b/packages/grpc-native-core/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.11.0-pre2", + "version": "1.11.0", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "https://grpc.io/", From 9d1904fb9a9044c4876e7af00508649eec2f2354 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 1 May 2018 23:32:30 +0200 Subject: [PATCH 18/30] Adding initial node 10 support. --- packages/grpc-native-core/build.yaml | 2 +- packages/grpc-native-core/package.json | 4 ++-- packages/grpc-native-core/templates/package.json.template | 2 +- .../tools/run_tests/artifacts/build_artifact_node.bat | 2 +- .../tools/run_tests/artifacts/build_artifact_node.sh | 2 +- .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/grpc-native-core/build.yaml b/packages/grpc-native-core/build.yaml index 55bf7a48..4836b249 100644 --- a/packages/grpc-native-core/build.yaml +++ b/packages/grpc-native-core/build.yaml @@ -1,3 +1,3 @@ settings: '#': It's possible to have node_version here as a key to override the core's version. - 'node_version': 1.11.0 + 'node_version': 1.11.1 diff --git a/packages/grpc-native-core/package.json b/packages/grpc-native-core/package.json index c112e772..78a487b4 100644 --- a/packages/grpc-native-core/package.json +++ b/packages/grpc-native-core/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.11.0", + "version": "1.11.1", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "https://grpc.io/", @@ -30,7 +30,7 @@ "dependencies": { "lodash": "^4.15.0", "nan": "^2.0.0", - "node-pre-gyp": "0.7.0", + "node-pre-gyp": "^0.10.0", "protobufjs": "^5.0.0" }, "devDependencies": { diff --git a/packages/grpc-native-core/templates/package.json.template b/packages/grpc-native-core/templates/package.json.template index 35f55b0e..33a77dbb 100644 --- a/packages/grpc-native-core/templates/package.json.template +++ b/packages/grpc-native-core/templates/package.json.template @@ -32,7 +32,7 @@ "dependencies": { "lodash": "^4.15.0", "nan": "^2.0.0", - "node-pre-gyp": "0.7.0", + "node-pre-gyp": "^0.10.0", "protobufjs": "^5.0.0" }, "devDependencies": { diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat index e84dd896..31d062f7 100644 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat @@ -14,7 +14,7 @@ set arch_list=ia32 x64 -set node_versions=4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 +set node_versions=4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 10.0.0 set electron_versions=1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index 006370da..d9b2c424 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -17,7 +17,7 @@ set -ex arch_list=( ia32 x64 ) -node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 ) +node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 10.0.0 ) electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 ) while true ; do diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index 7faf15cc..275b43b2 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -23,7 +23,7 @@ mkdir -p "${ARTIFACTS_OUT}" npm update -node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 ) +node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 10.0.0 ) for version in ${node_versions[@]} do From 05221bad2664e8e31b33cc97d8acbf2f1cb0e157 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 1 May 2018 15:21:58 -0700 Subject: [PATCH 19/30] Add a missing directory to grpc package.json --- packages/grpc-native-core/package.json | 1 + packages/grpc-native-core/templates/package.json.template | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/grpc-native-core/package.json b/packages/grpc-native-core/package.json index c112e772..627386c3 100644 --- a/packages/grpc-native-core/package.json +++ b/packages/grpc-native-core/package.json @@ -71,6 +71,7 @@ "deps/grpc/third_party/boringssl/crypto/**/*.{c,cc,h}", "deps/grpc/third_party/boringssl/include/**/*.{c,cc,h}", "deps/grpc/third_party/boringssl/ssl/**/*.{c,cc,h}", + "deps/grpc/third_party/boringssl/third_party/**/*.{c,h}", "deps/grpc/third_party/abseil-cpp/absl/**/*.{h,hh}", "binding.gyp" ], diff --git a/packages/grpc-native-core/templates/package.json.template b/packages/grpc-native-core/templates/package.json.template index 35f55b0e..383eb4ec 100644 --- a/packages/grpc-native-core/templates/package.json.template +++ b/packages/grpc-native-core/templates/package.json.template @@ -73,6 +73,7 @@ "deps/grpc/third_party/boringssl/crypto/**/*.{c,cc,h}", "deps/grpc/third_party/boringssl/include/**/*.{c,cc,h}", "deps/grpc/third_party/boringssl/ssl/**/*.{c,cc,h}", + "deps/grpc/third_party/boringssl/third_party/**/*.{c,h}", "deps/grpc/third_party/abseil-cpp/absl/**/*.{h,hh}", "binding.gyp" ], From e35856061ebd28aaee67d30a856634981affc713 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 00:45:04 +0200 Subject: [PATCH 20/30] Building with node 10, because otherwise there's a weird issue, and I can't be bothered to understand it. --- .../tools/run_tests/artifacts/build_artifact_node.bat | 7 +++++++ .../tools/run_tests/artifacts/build_artifact_node.sh | 2 ++ .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 3 +++ 3 files changed, 12 insertions(+) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat index 31d062f7..442b2b04 100644 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat @@ -12,6 +12,13 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. +powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" + +SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% + +call nvm install 10 +call nvm use 10 + set arch_list=ia32 x64 set node_versions=4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 10.0.0 diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index d9b2c424..303fd3ec 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +nvm install 10 +nvm use 10 set -ex diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index 275b43b2..e7e301ed 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +nvm install 10 +nvm use 10 + set -ex cd $(dirname $0)/../../.. From 5f47953c88ac9671e5e474630b640cf56b28b587 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 01:20:08 +0200 Subject: [PATCH 21/30] Installing nvm from kokoro scripts. --- .../tools/run_tests/artifacts/build_artifact_node.bat | 4 ---- tools/release/kokoro.bat | 5 +++-- tools/release/kokoro.sh | 5 +++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat index 442b2b04..2c4ee6f3 100644 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat @@ -12,10 +12,6 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. -powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" - -SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% - call nvm install 10 call nvm use 10 diff --git a/tools/release/kokoro.bat b/tools/release/kokoro.bat index 1fde63b5..c55ddbf3 100644 --- a/tools/release/kokoro.bat +++ b/tools/release/kokoro.bat @@ -14,8 +14,9 @@ @echo "Starting Windows build" -@rem https://github.com/mapbox/node-pre-gyp/issues/362 -call npm install -g node-gyp +powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" + +SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% cd /d %~dp0 cd ..\.. diff --git a/tools/release/kokoro.sh b/tools/release/kokoro.sh index b89504a9..37e61ea7 100755 --- a/tools/release/kokoro.sh +++ b/tools/release/kokoro.sh @@ -13,8 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# https://github.com/mapbox/node-pre-gyp/issues/362 -npm install -g node-gyp +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" set -ex cd $(dirname $0)/../.. From 582c171da4711441c9a7e92c149f2b784deb4aad Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 01:43:31 +0200 Subject: [PATCH 22/30] Shuffling things around a bit better... --- .../tools/run_tests/artifacts/build_artifact_node.bat | 3 --- .../tools/run_tests/artifacts/build_artifact_node.sh | 3 --- .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 6 +++--- tools/release/kokoro.bat | 5 +++++ tools/release/kokoro.sh | 5 +++++ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat index 2c4ee6f3..31d062f7 100644 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat @@ -12,9 +12,6 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. -call nvm install 10 -call nvm use 10 - set arch_list=ia32 x64 set node_versions=4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 10.0.0 diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index 303fd3ec..3120d6d3 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -13,9 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -nvm install 10 -nvm use 10 - set -ex arch_list=( ia32 x64 ) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index e7e301ed..34d9ffac 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -13,11 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -nvm install 10 -nvm use 10 - set -ex +# https://github.com/mapbox/node-pre-gyp/issues/362 +npm install -g node-gyp + cd $(dirname $0)/../../.. rm -rf build || true diff --git a/tools/release/kokoro.bat b/tools/release/kokoro.bat index c55ddbf3..d26f58b3 100644 --- a/tools/release/kokoro.bat +++ b/tools/release/kokoro.bat @@ -17,6 +17,11 @@ powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% +call nvm install 10 +call nvm use 10 + +call npm install -g npm +call npm install -g node-gyp cd /d %~dp0 cd ..\.. diff --git a/tools/release/kokoro.sh b/tools/release/kokoro.sh index 37e61ea7..4b0fe37d 100755 --- a/tools/release/kokoro.sh +++ b/tools/release/kokoro.sh @@ -17,6 +17,11 @@ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +nvm install 10 +nvm use 10 +npm install -g npm +npm install -g node-gyp + set -ex cd $(dirname $0)/../.. base_dir=$(pwd) From 1ef4c902707ac8babe7d77828d42fb4059a38d89 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Mon, 23 Apr 2018 03:53:52 +0200 Subject: [PATCH 23/30] Let's start building electron 2 binaries. --- .../tools/run_tests/artifacts/build_artifact_node.bat | 2 +- .../tools/run_tests/artifacts/build_artifact_node.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat index e84dd896..da2efa55 100644 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.bat @@ -16,7 +16,7 @@ set arch_list=ia32 x64 set node_versions=4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 -set electron_versions=1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 +set electron_versions=1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 2.0.0 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index 006370da..e27b42d2 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -18,7 +18,7 @@ set -ex arch_list=( ia32 x64 ) node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 8.0.0 9.0.0 ) -electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 ) +electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 2.0.0 ) while true ; do case $1 in From c94718c007f56bb49a709009be6e2b21cc9a5a67 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 03:41:42 +0200 Subject: [PATCH 24/30] Let's double down on installing node 10... --- .../tools/run_tests/artifacts/build_artifact_node.sh | 5 +++++ .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index 3120d6d3..d76536fd 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -13,6 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +nvm install 10 +nvm use 10 +npm install -g npm +npm install -g node-gyp + set -ex arch_list=( ia32 x64 ) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index 34d9ffac..3ca347f7 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -13,6 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +nvm install 10 +nvm use 10 +npm install -g npm +npm install -g node-gyp + set -ex # https://github.com/mapbox/node-pre-gyp/issues/362 From 727e54ef1ba9d11e32e2195787d45675bdefdf2a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 04:07:41 +0200 Subject: [PATCH 25/30] Right. We need to install nvm into the docker image. --- .../grpc-native-core/tools/docker/alpine_artifact/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile b/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile index 0674654a..1a7ee6ed 100644 --- a/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile +++ b/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile @@ -1,2 +1,3 @@ FROM node:8-alpine RUN apk add --no-cache python curl bash build-base +RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash From d46556622de61aef6382222bd0a691135d3ea54a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 04:11:35 +0200 Subject: [PATCH 26/30] More nvm love. --- .../tools/run_tests/artifacts/build_artifact_node.sh | 3 +++ .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index d76536fd..1dc04d64 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install 10 nvm use 10 npm install -g npm diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index 3ca347f7..24292c5f 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install 10 nvm use 10 npm install -g npm From c5fbaf1b5b7fc2e0d9abd416a2c22a58dc2ff64e Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 05:33:08 +0200 Subject: [PATCH 27/30] Reverting these... --- .../tools/run_tests/artifacts/build_artifact_node.sh | 8 -------- .../tools/run_tests/artifacts/build_artifact_node_arm.sh | 8 -------- 2 files changed, 16 deletions(-) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh index 2b3452a5..a98c775d 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node.sh @@ -13,14 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -nvm install 10 -nvm use 10 -npm install -g npm -npm install -g node-gyp - set -ex arch_list=( ia32 x64 ) diff --git a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh index 24292c5f..34d9ffac 100755 --- a/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh +++ b/packages/grpc-native-core/tools/run_tests/artifacts/build_artifact_node_arm.sh @@ -13,14 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -nvm install 10 -nvm use 10 -npm install -g npm -npm install -g node-gyp - set -ex # https://github.com/mapbox/node-pre-gyp/issues/362 From 30310d79b1bacb0b89fbd9131be39d045d858ad7 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 2 May 2018 05:36:19 +0200 Subject: [PATCH 28/30] Better this way... --- .../grpc-native-core/tools/docker/alpine_artifact/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile b/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile index 1a7ee6ed..728ccd02 100644 --- a/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile +++ b/packages/grpc-native-core/tools/docker/alpine_artifact/Dockerfile @@ -1,3 +1,2 @@ -FROM node:8-alpine +FROM node:10-alpine RUN apk add --no-cache python curl bash build-base -RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash From 85c154c5079d1873f831cc8cf9fb99cf50893e4d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 2 May 2018 11:53:43 -0700 Subject: [PATCH 29/30] Add loadPackageDefinition and interceptor APIs to .d.ts file --- packages/grpc-native-core/index.d.ts | 208 ++++++++++++++++++++++++++- 1 file changed, 207 insertions(+), 1 deletion(-) diff --git a/packages/grpc-native-core/index.d.ts b/packages/grpc-native-core/index.d.ts index 73a685cd..13405183 100644 --- a/packages/grpc-native-core/index.d.ts +++ b/packages/grpc-native-core/index.d.ts @@ -78,6 +78,13 @@ declare module "grpc" { */ export function load(filename: Filename, format?: "proto" | "json", options?: LoadOptions): T; + /** + * Load a gRPC package definition as a gRPC object hierarchy + * @param packageDef The package definition object + * @return The resulting gRPC object + */ + export function loadPackageDefinition(packageDefinition: PackageDefinition): GrpcObject; + /** * A filename */ @@ -235,12 +242,18 @@ declare module "grpc" { /** * An object that completely defines a service. - * @typedef {Object.} grpc~ServiceDefinition */ export type ServiceDefinition = { readonly [I in keyof ImplementationType]: MethodDefinition; } + /** + * An object that defines a package containing multiple services + */ + export type PackageDefinition = { + readonly [fullyQualifiedName: string]: ServiceDefinition; + } + /** * An object that completely defines a service method signature. */ @@ -1259,4 +1272,197 @@ declare module "grpc" { * @param clientObj The client to close */ export function closeClient(clientObj: Client): void; + + /** + * A builder for gRPC status objects + */ + export class StatusBuilder { + constructor() + + /** + * Adds a status code to the builder + * @param code The status code + */ + withCode(code: number): this; + + /** + * Adds details to the builder + * @param details A status message + */ + withDetails(details: string): this; + + /** + * Adds metadata to the builder + * @param metadata The gRPC status metadata + */ + withMetadata(metadata: Metadata): this; + + /** + * Builds the status object + * @return A gRPC status + */ + build(): StatusObject; + } + + export type MetadataListener = (metadata: Metadata, next: function) => void; + + export type MessageListener = (message: any, next: function) => void; + + export type StatusListener = (status: StatusObject, next: function) => void; + + export interface Listener { + onReceiveMetadata?: MetadataListener; + onReceiveMessage?: MessageListener; + onReceiveStatus?: StatusListener; + } + + /** + * A builder for listener interceptors + */ + export class ListenerBuilder { + constructor(); + + /** + * Adds onReceiveMetadata method to the builder + * @param onReceiveMetadata A listener method for receiving metadata + */ + withOnReceiveMetadata(onReceiveMetadata: MetadataListener): this; + + /** + * Adds onReceiveMessage method to the builder + * @param onReceiveMessage A listener method for receiving message + */ + withOnReceiveMessage(onReceiveMessage: MessageListener): this; + + /** + * Adds onReceiveStatus method to the builder + * @param onReceiveStatus A listener method for receiving status + */ + withOnReceiveStatus(onReceiveStatus: StatusListener): this; + + /** + * Builds the call listener + */ + build(): Listener; + } + + export type MetadataRequester = (metadata: Metadata, listener: Listener, next: function) => void; + + export type MessageRequester = (message: any, next: function) => void; + + export type CloseRequester = (next: function) => void; + + export type CancelRequester = (next: function) => void; + + export type GetPeerRequester = (next: function) => string; + + export interface Requester { + start?: MetadataRequester; + sendMessage?: MessageRequester; + halfClose?: CloseRequester; + cancel?: CancelRequester; + getPeer?: GetPeerRequester; + } + + /** + * A builder for the outbound methods of an interceptor + */ + export class RequesterBuilder { + constructor(); + + /** + * Add a metadata requester to the builder + * @param start A requester method for handling metadata + */ + withStart(start: MetadataRequester): this; + + /** + * Add a message requester to the builder. + * @param sendMessage A requester method for handling + * messages. + */ + withSendMessage(sendMessage: MessageRequester): this; + + /** + * Add a close requester to the builder. + * @param halfClose A requester method for handling client + * close. + */ + withHalfClose(halfClose: CloseRequester): this; + + /** + * Add a cancel requester to the builder. + * @param cancel A requester method for handling `cancel` + */ + withCancel(cancel: CancelRequester): this; + + /** + * Builds the requester's interceptor methods. + */ + build(): Requester; + } + + /** + * A chainable gRPC call proxy which will delegate to an optional requester + * object. By default, interceptor methods will chain to nextCall. If a + * requester is provided which implements an interceptor method, that + * requester method will be executed as part of the chain. + * operations. + */ + export class InterceptingCall { + /** + * @param next_Call The next call in the chain + * @param requester Interceptor methods to handle request + */ + constructor(nextCall: InterceptingCall|null, requester?: Requester); + + /** + * Starts a call through the outbound interceptor chain and adds an element to + * the reciprocal inbound listener chain. + */ + start(metadata: Metadata, listener: Listener): void; + + /** + * Pass a message through the interceptor chain. + */ + sendMessage(message: any): void; + + /** + * Run a close operation through the interceptor chain + */ + halfClose(): void; + + /** + * Run a cancel operation through the interceptor chain + */ + cancel(): void; + + /** + * Run a cancelWithStatus operation through the interceptor chain. + * @param status + * @param message + */ + cancelWithStatus(status: StatusObject, message: string): void; + + /** + * Pass a getPeer call down to the base gRPC call (should not be intercepted) + */ + getPeer(): object; + + /** + * For streaming calls, we need to transparently pass the stream's context + * through the interceptor chain. Passes the context between InterceptingCalls + * but hides it from any requester implementations. + * @param context Carries objects needed for streaming operations. + * @param message The message to send. + */ + sendMessageWithContext(context: object, message: any): void; + + /** + * For receiving streaming messages, we need to seed the base interceptor with + * the streaming context to create a RECV_MESSAGE batch. + * @param context Carries objects needed for streaming operations + */ + recvMessageWithContext(context: object): void; + } } From 5233c2d8eb307369b45fe570465996482cc40e39 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Wed, 2 May 2018 15:24:34 -0700 Subject: [PATCH 30/30] fix: use capital `F` for `Function` when used as a type --- packages/grpc-native-core/index.d.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/grpc-native-core/index.d.ts b/packages/grpc-native-core/index.d.ts index 13405183..be0c0b05 100644 --- a/packages/grpc-native-core/index.d.ts +++ b/packages/grpc-native-core/index.d.ts @@ -84,7 +84,7 @@ declare module "grpc" { * @return The resulting gRPC object */ export function loadPackageDefinition(packageDefinition: PackageDefinition): GrpcObject; - + /** * A filename */ @@ -1304,11 +1304,11 @@ declare module "grpc" { build(): StatusObject; } - export type MetadataListener = (metadata: Metadata, next: function) => void; + export type MetadataListener = (metadata: Metadata, next: Function) => void; - export type MessageListener = (message: any, next: function) => void; + export type MessageListener = (message: any, next: Function) => void; - export type StatusListener = (status: StatusObject, next: function) => void; + export type StatusListener = (status: StatusObject, next: Function) => void; export interface Listener { onReceiveMetadata?: MetadataListener; @@ -1346,15 +1346,15 @@ declare module "grpc" { build(): Listener; } - export type MetadataRequester = (metadata: Metadata, listener: Listener, next: function) => void; + export type MetadataRequester = (metadata: Metadata, listener: Listener, next: Function) => void; - export type MessageRequester = (message: any, next: function) => void; + export type MessageRequester = (message: any, next: Function) => void; - export type CloseRequester = (next: function) => void; + export type CloseRequester = (next: Function) => void; - export type CancelRequester = (next: function) => void; + export type CancelRequester = (next: Function) => void; - export type GetPeerRequester = (next: function) => string; + export type GetPeerRequester = (next: Function) => string; export interface Requester { start?: MetadataRequester; @@ -1443,7 +1443,7 @@ declare module "grpc" { * @param message */ cancelWithStatus(status: StatusObject, message: string): void; - + /** * Pass a getPeer call down to the base gRPC call (should not be intercepted) */