Skip to content

Commit

Permalink
Load Protos from JSON (#5883)
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidt-sebastian committed Jan 13, 2022
1 parent 3105541 commit ff2f7d4
Show file tree
Hide file tree
Showing 15 changed files with 2,946 additions and 287 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-pots-fetch.md
@@ -0,0 +1,5 @@
---
"@firebase/firestore": patch
---

The Node SDK now uses JSON to load its internal Protobuf definition, which allows the Node SDK to work with bundlers such as Rollup and Webpack.
49 changes: 1 addition & 48 deletions packages/firestore/rollup.config.js
Expand Up @@ -18,12 +18,10 @@
import { version as grpcVersion } from '@grpc/grpc-js/package.json';
import alias from '@rollup/plugin-alias';
import json from '@rollup/plugin-json';
import copy from 'rollup-plugin-copy';
import replace from 'rollup-plugin-replace';
import { terser } from 'rollup-plugin-terser';
import typescriptPlugin from 'rollup-plugin-typescript2';
import tmp from 'tmp';
import { basename } from 'path';
import typescript from 'typescript';

import { generateBuildTargetReplaceConfig } from '../../scripts/build/rollup_replace_build_target';
Expand All @@ -32,40 +30,6 @@ import pkg from './package.json';

const util = require('./rollup.shared');

// Customize how import.meta.url is polyfilled in cjs nodejs build. We use it to
// be able to use require() in esm. It only generates the nodejs version of the
// polyfill, as opposed to the default polyfill which supports both browser and
// nodejs. The browser support doesn't work well with Jest.
// See https://github.com/firebase/firebase-js-sdk/issues/5687
// Although this is a cjs Node build and shouldn't require the browser option,
// Vercel apps using this break on deployment, but work in local development.
// See https://github.com/firebase/firebase-js-sdk/issues/5823
function importMetaUrlPolyfillPlugin(filename) {
return {
name: 'import-meta-url-current-module',
resolveImportMeta(property, { moduleId }) {
if (property === 'url') {
// Added a check for Jest (see issue 5687 linked above)
// See https://jestjs.io/docs/environment-variables - apparently
// these are not always both set.
const JEST_CHECK =
`typeof process !== 'undefined' && process.env !== undefined` +
` && (process.env.JEST_WORKER_ID !== undefined || ` +
`process.env.NODE_ENV === 'test')`;
// Copied from rollup output
return (
`((typeof document === 'undefined' || (${JEST_CHECK})) ?` +
` new (require('url').URL)` +
`('file:' + __filename).href : (document.currentScript && ` +
`document.currentScript.src || new URL('${filename}', ` +
`document.baseURI).href))`
);
}
return null;
}
};
}

const nodePlugins = function () {
return [
typescriptPlugin({
Expand All @@ -80,17 +44,7 @@ const nodePlugins = function () {
transformers: [util.removeAssertTransformer]
}),
json({ preferConst: true }),
// Needed as we also use the *.proto files
copy({
targets: [
{
src: 'src/protos',
dest: 'dist/src'
}
]
}),
replace({
'process.env.FIRESTORE_PROTO_ROOT': JSON.stringify('src/protos'),
'__GRPC_VERSION__': grpcVersion
})
];
Expand Down Expand Up @@ -142,8 +96,7 @@ const allBuilds = [
},
plugins: [
...util.es2017ToEs5Plugins(/* mangled= */ false),
replace(generateBuildTargetReplaceConfig('cjs', 2017)),
importMetaUrlPolyfillPlugin(basename(pkg.main))
replace(generateBuildTargetReplaceConfig('cjs', 2017))
],
external: util.resolveNodeExterns,
treeshake: {
Expand Down
14 changes: 1 addition & 13 deletions packages/firestore/rollup.config.lite.js
Expand Up @@ -22,7 +22,6 @@ import alias from '@rollup/plugin-alias';
import typescriptPlugin from 'rollup-plugin-typescript2';
import typescript from 'typescript';
import sourcemaps from 'rollup-plugin-sourcemaps';
import copy from 'rollup-plugin-copy';
import replace from 'rollup-plugin-replace';
import { terser } from 'rollup-plugin-terser';

Expand All @@ -44,18 +43,7 @@ const nodePlugins = function () {
abortOnError: false,
transformers: [util.removeAssertTransformer]
}),
json({ preferConst: true }),
copy({
targets: [
{
src: 'src/protos',
dest: 'dist/lite/src'
}
]
}),
replace({
'process.env.FIRESTORE_PROTO_ROOT': JSON.stringify('src/protos')
})
json({ preferConst: true })
];
};

Expand Down
24 changes: 5 additions & 19 deletions packages/firestore/src/platform/node/load_protos.ts
Expand Up @@ -15,20 +15,16 @@
* limitations under the License.
*/

import { join, resolve, isAbsolute, dirname } from 'path';
import { fileURLToPath } from 'url';

// __filename and __dirname globals are unavailable in ES modules
// @ts-ignore To avoid using `--module es2020` flag.
const __filenameInESM = fileURLToPath(import.meta.url);
const __dirnameInESM = dirname(__filenameInESM);
import { join, resolve, isAbsolute } from 'path';

import { loadPackageDefinition, GrpcObject } from '@grpc/grpc-js';
import { loadSync } from '@grpc/proto-loader';
import { fromJSON } from '@grpc/proto-loader';
// only used in tests
// eslint-disable-next-line import/no-extraneous-dependencies
import { IConversionOptions, Root } from 'protobufjs';

import * as protos from '../../protos/protos.json';

/** Used by tests so we can match @grpc/proto-loader behavior. */
export const protoLoaderOptions: IConversionOptions = {
longs: String,
Expand All @@ -43,17 +39,7 @@ export const protoLoaderOptions: IConversionOptions = {
* @returns The GrpcObject representing our protos.
*/
export function loadProtos(): GrpcObject {
const root = resolve(
__dirnameInESM,
process.env.FIRESTORE_PROTO_ROOT || '../../protos'
);
const firestoreProtoFile = join(root, 'google/firestore/v1/firestore.proto');

const packageDefinition = loadSync(firestoreProtoFile, {
...protoLoaderOptions,
includeDirs: [root]
});

const packageDefinition = fromJSON(protos, protoLoaderOptions);
return loadPackageDefinition(packageDefinition);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/firestore/src/protos/google/api/annotations.proto
@@ -1,4 +1,4 @@
// Copyright (c) 2015, Google Inc.
// Copyright 2015 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
29 changes: 17 additions & 12 deletions packages/firestore/src/protos/google/api/http.proto
@@ -1,4 +1,4 @@
// Copyright 2018 Google LLC.
// Copyright 2015 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -11,7 +11,6 @@
// 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.
//

syntax = "proto3";

Expand All @@ -24,7 +23,6 @@ option java_outer_classname = "HttpProto";
option java_package = "com.google.api";
option objc_class_prefix = "GAPI";


// Defines the HTTP configuration for an API service. It contains a list of
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
// to one or more HTTP REST API methods.
Expand All @@ -34,7 +32,7 @@ message Http {
// **NOTE:** All service configuration rules follow "last one wins" order.
repeated HttpRule rules = 1;

// When set to true, URL path parmeters will be fully URI-decoded except in
// When set to true, URL path parameters will be fully URI-decoded except in
// cases of single segment matches in reserved expansion, where "%2F" will be
// left encoded.
//
Expand Down Expand Up @@ -112,7 +110,9 @@ message Http {
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` |
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield:
// "foo"))`
//
// Note that fields which are mapped to URL query parameters must have a
// primitive type or a repeated primitive type or a non-repeated message type.
Expand Down Expand Up @@ -144,7 +144,8 @@ message Http {
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" message { text: "Hi!" })`
//
// The special name `*` can be used in the body mapping to define that
// every field not bound by the path template should be mapped to the
Expand All @@ -169,7 +170,8 @@ message Http {
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" text: "Hi!")`
//
// Note that when using `*` in the body mapping, it is not possible to
// have HTTP parameters, as all fields not bound by the path end in
Expand Down Expand Up @@ -200,7 +202,8 @@ message Http {
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id:
// "123456")`
//
// ## Rules for HTTP mapping
//
Expand Down Expand Up @@ -244,16 +247,18 @@ message Http {
// `"{var=*}"`, when such a variable is expanded into a URL path on the client
// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The
// server side does the reverse decoding. Such variables show up in the
// [Discovery Document](https://developers.google.com/discovery/v1/reference/apis)
// as `{var}`.
// [Discovery
// Document](https://developers.google.com/discovery/v1/reference/apis) as
// `{var}`.
//
// If a variable contains multiple path segments, such as `"{var=foo/*}"`
// or `"{var=**}"`, when such a variable is expanded into a URL path on the
// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded.
// The server side does the reverse decoding, except "%2F" and "%2f" are left
// unchanged. Such variables show up in the
// [Discovery Document](https://developers.google.com/discovery/v1/reference/apis)
// as `{+var}`.
// [Discovery
// Document](https://developers.google.com/discovery/v1/reference/apis) as
// `{+var}`.
//
// ## Using gRPC API Service Configuration
//
Expand Down
@@ -1,4 +1,4 @@
// Copyright 2018 Google LLC.
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -11,14 +11,13 @@
// 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.
//

syntax = "proto3";

package google.firestore.v1;

import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";

option csharp_namespace = "Google.Cloud.Firestore.V1";
option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore";
Expand All @@ -27,7 +26,7 @@ option java_outer_classname = "CommonProto";
option java_package = "com.google.firestore.v1";
option objc_class_prefix = "GCFS";
option php_namespace = "Google\\Cloud\\Firestore\\V1";

option ruby_package = "Google::Cloud::Firestore::V1";

// A set of field paths on a document.
// Used to restrict a get or update operation on a document to a subset of its
Expand Down
@@ -1,4 +1,4 @@
// Copyright 2018 Google LLC.
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -11,16 +11,15 @@
// 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.
//

syntax = "proto3";

package google.firestore.v1;

import "google/api/annotations.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/type/latlng.proto";
import "google/api/annotations.proto";

option csharp_namespace = "Google.Cloud.Firestore.V1";
option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore";
Expand All @@ -29,7 +28,7 @@ option java_outer_classname = "DocumentProto";
option java_package = "com.google.firestore.v1";
option objc_class_prefix = "GCFS";
option php_namespace = "Google\\Cloud\\Firestore\\V1";

option ruby_package = "Google::Cloud::Firestore::V1";

// A Firestore document.
//
Expand Down

0 comments on commit ff2f7d4

Please sign in to comment.