google / ground-platform

Ground hosted components: Web console, Cloud Functions, db config
http://groundplatform.org
Apache License 2.0
204 stars 84 forks source link

[PROJECT] New proto-backed Firestore structure #1758

Closed jcqli closed 1 month ago

jcqli commented 5 months ago

Parent issue tracking the work needed to introduce protos as our db and Firestore schema.

Additional tasks related to this migration:

gino-m commented 4 months ago

Did some research on various protoc plugins for generating js+ts code from protodef. We need something which makes metadata accessible (esp. field numbers) in order to implement the representation described in #2455. Here are my findings:

protobufjs ✅

The most popular lib I found (16M weekly downloads), originally designed by Google. It can generate js and ts, but to get what we want you need to call it three times - once to generate the js, once to generate to ts bindings, and once to generate JSON with pb metadata.

npm i -D protobufjs protobufjs-cli
npx pbjs -t static-module ../proto/survey.proto -o dist/survey.js
npx pbts dist/survey.js -o dist/survey.d.ts
npx pbjs -t json ../proto/survey.proto -o dist/survey.proto.json

We could load the JSON at runtime to pick out field numbers we need.

Alternatives considered

@protobuf-ts/plugin

146k downloads/week. Generates pure ts code in a single command, and includes field numbers in the message metadata. But given this is a less "standard", less used library, prefer using protobufjs.

ts-proto

OTOO 300k weekly downloads, and doesn't encode the field numbers anywhere we can use at runtime, so we can exclude this one for now.

protoc-gen-ts

It seems the protoc packaged with the one didn't support my M1 Mac.

npm i -D @protobuf-ts/plugin
npx protoc --ts_out dist --proto_path ../proto survey.proto loi.proto submission.proto

It doesn't produce or consume JSON, but it's fairly easy to go from ts object<>JSON anyway, plus we'll prob want more control over the formats.

grpc_tools_node_protoc_ts

Only 100k downloads per week, but uses the standard google grpc-tools. Doesn't seem to embed the set of valid field numbers, though individual fields can be fetched by field number:

npm i -D grpc-tools grpc_tools_node_protoc_ts
npx grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./dist --grpc_out=grpc_js:./dist --plugin=protoc-gen-grpc=./node_modules/.bin/grpc_tools_node_protoc_plugin -I ../proto survey.proto
npx protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js:./dist -I ../proto survey.proto
gino-m commented 4 months ago

Also, carrying forward proposal from https://github.com/google/ground-android/issues/2455:

Example survey data before:

{
  "title": "My survey",
  "description": "An example survey",
   //...
}

Example survey data after:

{
  1: "My survey",
  2: "An example survey",
  ...
}

This has several advantages:

This has a few disadvantages as well:

jcqli commented 1 month ago

Filed https://github.com/google/ground-platform/issues/1966 to track cleanup of old code @gino-m shall we mark this as closed?

gino-m commented 1 month ago

Yes, I think we can!