From f15b514c382ef65dec4eaeb5241c07f828ae0f28 Mon Sep 17 00:00:00 2001 From: Timo Stamm Date: Fri, 22 Jul 2022 10:10:32 +0200 Subject: [PATCH] Port the code generator to TypeScript (#159) --- .github/workflows/ci.yaml | 22 +- .gitignore | 7 +- .golangci.yaml | 67 - .prettierignore | 8 +- Makefile | 399 ++- README.md | 28 +- .../internal/gencommon/gencommon.go | 197 -- .../internal/gencommon/textformat.go | 137 - .../internal/gencommon/typescript.go | 37 - cmd/protoc-gen-es/internal/gencommon/wkt.go | 246 -- cmd/protoc-gen-es/internal/gendts/gendts.go | 202 -- cmd/protoc-gen-es/internal/genjs/genjs.go | 522 ---- cmd/protoc-gen-es/internal/gents/gents.go | 587 ---- cmd/protoc-gen-es/main.go | 51 - docs/generated_code.md | 12 +- docs/migrating.md | 2 +- docs/releasing.md | 2 +- docs/runtime_api.md | 14 +- go.mod | 5 - go.sum | 8 - make/scripts/checknodiffgenerated.bash | 39 - make/scripts/go-build-npm-shim.cjs | 109 - make/scripts/go-build-npm.js | 184 -- make/scripts/update-go-version-file.js | 63 - package-lock.json | 110 +- package.json | 9 +- packages/README.md | 31 - packages/example/src/gen/addressbook_pb.ts | 2 +- .../README.md | 2 +- packages/protobuf-bench/buf.gen.yaml | 13 + .../package.json | 2 +- .../report.mjs | 0 .../src/entry-google-protobuf.js | 0 .../src/entry-protobuf-es.ts | 0 .../buf/alpha/audit/v1alpha1/envelope_pb.js | 0 .../buf/alpha/audit/v1alpha1/module_pb.js | 0 .../buf/alpha/audit/v1alpha1/plugin_pb.js | 0 .../buf/alpha/audit/v1alpha1/repository_pb.js | 0 .../buf/alpha/audit/v1alpha1/role_pb.js | 0 .../buf/alpha/audit/v1alpha1/search_pb.js | 0 .../buf/alpha/audit/v1alpha1/user_pb.js | 0 .../buf/alpha/breaking/v1/config_pb.js | 0 .../buf/alpha/image/v1/image_pb.js | 0 .../buf/alpha/lint/v1/config_pb.js | 0 .../buf/alpha/module/v1alpha1/module_pb.js | 0 .../buf/alpha/registry/v1alpha1/admin_pb.js | 0 .../alpha/registry/v1alpha1/audit_logs_pb.js | 0 .../buf/alpha/registry/v1alpha1/authn_pb.js | 0 .../buf/alpha/registry/v1alpha1/authz_pb.js | 0 .../buf/alpha/registry/v1alpha1/display_pb.js | 0 .../buf/alpha/registry/v1alpha1/doc_pb.js | 0 .../alpha/registry/v1alpha1/download_pb.js | 0 .../alpha/registry/v1alpha1/generate_pb.js | 0 .../buf/alpha/registry/v1alpha1/image_pb.js | 0 .../alpha/registry/v1alpha1/jsonschema_pb.js | 0 .../buf/alpha/registry/v1alpha1/module_pb.js | 0 .../registry/v1alpha1/organization_pb.js | 0 .../buf/alpha/registry/v1alpha1/owner_pb.js | 0 .../buf/alpha/registry/v1alpha1/plugin_pb.js | 0 .../buf/alpha/registry/v1alpha1/push_pb.js | 0 .../registry/v1alpha1/recommendation_pb.js | 0 .../alpha/registry/v1alpha1/reference_pb.js | 0 .../registry/v1alpha1/repository_branch_pb.js | 0 .../registry/v1alpha1/repository_commit_pb.js | 0 .../alpha/registry/v1alpha1/repository_pb.js | 0 .../registry/v1alpha1/repository_tag_pb.js | 0 .../v1alpha1/repository_track_commit_pb.js | 0 .../registry/v1alpha1/repository_track_pb.js | 0 .../buf/alpha/registry/v1alpha1/resolve_pb.js | 0 .../buf/alpha/registry/v1alpha1/role_pb.js | 0 .../buf/alpha/registry/v1alpha1/search_pb.js | 0 .../buf/alpha/registry/v1alpha1/token_pb.js | 0 .../buf/alpha/registry/v1alpha1/user_pb.js | 0 .../buf/alpha/rpc/v1alpha1/error_pb.js | 0 .../buf/alpha/audit/v1alpha1/envelope_pb.ts | 30 +- .../buf/alpha/audit/v1alpha1/module_pb.ts | 14 +- .../buf/alpha/audit/v1alpha1/plugin_pb.ts | 6 +- .../buf/alpha/audit/v1alpha1/repository_pb.ts | 8 +- .../buf/alpha/audit/v1alpha1/role_pb.ts | 44 +- .../buf/alpha/audit/v1alpha1/search_pb.ts | 14 +- .../buf/alpha/audit/v1alpha1/user_pb.ts | 6 +- .../buf/alpha/breaking/v1/config_pb.ts | 0 .../buf/alpha/image/v1/image_pb.ts | 2 +- .../buf/alpha/lint/v1/config_pb.ts | 0 .../buf/alpha/module/v1alpha1/module_pb.ts | 2 +- .../buf/alpha/registry/v1alpha1/admin_pb.ts | 0 .../alpha/registry/v1alpha1/audit_logs_pb.ts | 2 +- .../buf/alpha/registry/v1alpha1/authn_pb.ts | 0 .../buf/alpha/registry/v1alpha1/authz_pb.ts | 0 .../buf/alpha/registry/v1alpha1/display_pb.ts | 0 .../buf/alpha/registry/v1alpha1/doc_pb.ts | 0 .../alpha/registry/v1alpha1/download_pb.ts | 0 .../alpha/registry/v1alpha1/generate_pb.ts | 0 .../buf/alpha/registry/v1alpha1/image_pb.ts | 2 +- .../alpha/registry/v1alpha1/jsonschema_pb.ts | 0 .../buf/alpha/registry/v1alpha1/module_pb.ts | 2 +- .../registry/v1alpha1/organization_pb.ts | 2 +- .../buf/alpha/registry/v1alpha1/owner_pb.ts | 0 .../buf/alpha/registry/v1alpha1/plugin_pb.ts | 0 .../buf/alpha/registry/v1alpha1/push_pb.ts | 0 .../registry/v1alpha1/recommendation_pb.ts | 2 +- .../alpha/registry/v1alpha1/reference_pb.ts | 0 .../registry/v1alpha1/repository_branch_pb.ts | 2 +- .../registry/v1alpha1/repository_commit_pb.ts | 2 +- .../alpha/registry/v1alpha1/repository_pb.ts | 2 +- .../registry/v1alpha1/repository_tag_pb.ts | 2 +- .../v1alpha1/repository_track_commit_pb.ts | 2 +- .../registry/v1alpha1/repository_track_pb.ts | 2 +- .../buf/alpha/registry/v1alpha1/resolve_pb.ts | 0 .../buf/alpha/registry/v1alpha1/role_pb.ts | 0 .../buf/alpha/registry/v1alpha1/search_pb.ts | 0 .../buf/alpha/registry/v1alpha1/token_pb.ts | 2 +- .../buf/alpha/registry/v1alpha1/user_pb.ts | 2 +- .../buf/alpha/rpc/v1alpha1/error_pb.ts | 0 .../tsconfig.json | 0 .../README.md | 0 .../bin/conformance_esm.js | 0 .../conformance_failing_tests.txt | 0 .../conformance_failing_tests_text_format.txt | 0 .../package.json | 2 +- .../src/conformance.ts | 10 +- .../src/gen/conformance/conformance_pb.ts | 0 .../protobuf/test_messages_proto2_pb.ts | 4 +- .../protobuf/test_messages_proto3_pb.ts | 2 +- .../tsconfig.json | 0 .../{enum-annotated.proto => enum.proto} | 30 +- .../src/create-registry-from-desc.test.ts | 51 + .../protobuf-test/src/create-registry.test.ts | 38 + .../protobuf-test/src/descriptor-set.test.ts | 166 ++ packages/protobuf-test/src/enum.test.ts | 116 + .../src/gen/js/extra/comments_pb.d.ts | 2 - .../src/gen/js/extra/comments_pb.js | 10 +- .../gen/js/extra/deprecation-explicit_pb.js | 10 +- .../src/gen/js/extra/enum_pb.d.ts | 124 + .../protobuf-test/src/gen/js/extra/enum_pb.js | 88 + .../src/gen/js/extra/msg-json-names_pb.d.ts | 2 +- .../src/gen/js/extra/msg-json-names_pb.js | 2 +- .../src/gen/js/extra/msg-maps_pb.js | 7 +- .../src/gen/js/extra/msg-oneof_pb.js | 7 +- .../src/gen/js/extra/proto2_pb.js | 9 +- .../src/gen/js/extra/proto3_pb.js | 7 +- .../src/gen/js/extra/wkt-wrappers_pb.js | 2 +- .../src/gen/js/google/protobuf/any_pb.d.ts | 193 ++ .../src/gen/js/google/protobuf/any_pb.js | 212 ++ .../src/gen/js/google/protobuf/api_pb.d.ts | 322 +++ .../src/gen/js/google/protobuf/api_pb.js | 172 ++ .../google/protobuf/compiler/plugin_pb.d.ts | 324 +++ .../js/google/protobuf/compiler/plugin_pb.js | 126 + .../gen/js/google/protobuf/descriptor_pb.d.ts | 1959 +++++++++++++ .../gen/js/google/protobuf/descriptor_pb.js | 562 ++++ .../gen/js/google/protobuf/duration_pb.d.ts | 138 + .../src/gen/js/google/protobuf/duration_pb.js | 149 + .../src/gen/js/google/protobuf/empty_pb.d.ts | 66 + .../src/gen/js/google/protobuf/empty_pb.js | 54 + .../gen/js/google/protobuf/field_mask_pb.d.ts | 263 ++ .../gen/js/google/protobuf/field_mask_pb.js | 308 +++ .../js/google/protobuf/source_context_pb.d.ts | 67 + .../js/google/protobuf/source_context_pb.js | 49 + .../src/gen/js/google/protobuf/struct_pb.d.ts | 200 ++ .../src/gen/js/google/protobuf/struct_pb.js | 179 ++ .../protobuf/test_messages_proto2_pb.js | 4 +- .../protobuf/test_messages_proto3_pb.js | 2 +- .../gen/js/google/protobuf/timestamp_pb.d.ts | 175 ++ .../gen/js/google/protobuf/timestamp_pb.js | 202 ++ .../src/gen/js/google/protobuf/type_pb.d.ts | 4 +- .../src/gen/js/google/protobuf/type_pb.js | 18 +- .../protobuf/unittest_custom_options_pb.js | 3 +- .../js/google/protobuf/unittest_lite_pb.js | 6 +- .../unittest_no_field_presence_pb.d.ts | 2 +- .../src/gen/js/google/protobuf/unittest_pb.js | 18 +- .../protobuf/unittest_well_known_types_pb.js | 2 +- .../gen/js/google/protobuf/wrappers_pb.d.ts | 362 +++ .../src/gen/js/google/protobuf/wrappers_pb.js | 406 +++ .../src/gen/ts/extra/comments_pb.ts | 2 - .../src/gen/ts/extra/enum-annotated_pb.ts | 40 - .../protobuf-test/src/gen/ts/extra/enum_pb.ts | 162 ++ .../src/gen/ts/extra/msg-json-names_pb.ts | 4 +- .../src/gen/ts/extra/proto2_pb.ts | 4 +- .../src/gen/ts/extra/wkt-wrappers_pb.ts | 2 +- .../src/gen/ts/google/protobuf/any_pb.ts | 276 ++ .../src/gen/ts/google/protobuf/api_pb.ts | 374 +++ .../ts/google/protobuf/compiler/plugin_pb.ts | 392 +++ .../gen/ts/google/protobuf/descriptor_pb.ts | 2460 +++++++++++++++++ .../src/gen/ts/google/protobuf/duration_pb.ts | 193 ++ .../src/gen/ts/google/protobuf/empty_pb.ts | 78 + .../gen/ts/google/protobuf/field_mask_pb.ts | 338 +++ .../ts/google/protobuf/source_context_pb.ts | 80 + .../src/gen/ts/google/protobuf/struct_pb.ts | 321 +++ .../protobuf/test_messages_proto2_pb.ts | 4 +- .../protobuf/test_messages_proto3_pb.ts | 2 +- .../gen/ts/google/protobuf/timestamp_pb.ts | 244 ++ .../src/gen/ts/google/protobuf/type_pb.ts | 4 +- .../ts/google/protobuf/unittest_lite_pb.ts | 6 +- .../protobuf/unittest_no_field_presence_pb.ts | 2 +- .../src/gen/ts/google/protobuf/unittest_pb.ts | 18 +- .../protobuf/unittest_well_known_types_pb.ts | 2 +- .../src/gen/ts/google/protobuf/wrappers_pb.ts | 668 +++++ .../src/google/protobuf/any.test.ts | 127 +- .../src/google/protobuf/duration.test.ts | 62 +- .../src/google/protobuf/field_mask.test.ts | 30 +- .../src/google/protobuf/struct.test.ts | 170 +- .../src/google/protobuf/timestamp.test.ts | 29 +- .../src/google/protobuf/wrappers.test.ts | 198 ++ packages/protobuf-test/src/helpers.ts | 17 +- ....ts => legacy-descriptor-registry.test.ts} | 21 +- .../src/legacy-descriptor-set.test.ts | 28 + packages/protobuf/README.md | 38 +- packages/protobuf/package.json | 2 +- packages/protobuf/src/codegen-info.ts | 94 + .../protobuf/src/create-descriptor-set.ts | 1167 ++++++++ .../protobuf/src/create-registry-from-desc.ts | 523 ++++ packages/protobuf/src/create-registry.ts | 79 + packages/protobuf/src/descriptor-set.ts | 1224 ++++---- packages/protobuf/src/enum.ts | 15 +- packages/protobuf/src/index.ts | 25 +- ...istry.ts => legacy-descriptor-registry.ts} | 33 +- .../protobuf/src/legacy-descriptor-set.ts | 731 +++++ packages/protobuf/src/legacy-type-registry.ts | 115 + packages/protobuf/src/private/enum.ts | 74 +- .../protobuf/src/private/field-wrapper.ts | 33 + packages/protobuf/src/private/field.ts | 4 +- packages/protobuf/src/private/message-type.ts | 5 +- packages/protobuf/src/private/names.ts | 216 +- .../protobuf/src/private/proto-runtime.ts | 4 +- packages/protobuf/src/private/util.ts | 8 +- packages/protobuf/src/proto2.ts | 6 +- packages/protobuf/src/proto3.ts | 6 +- packages/protobuf/src/type-registry.ts | 91 - packages/protoc-gen-es-darwin-64/package.json | 25 - .../protoc-gen-es-darwin-arm64/package.json | 25 - .../protoc-gen-es-freebsd-64/package.json | 25 - .../protoc-gen-es-freebsd-arm64/package.json | 25 - packages/protoc-gen-es-linux-32/package.json | 25 - packages/protoc-gen-es-linux-64/package.json | 25 - packages/protoc-gen-es-linux-arm/package.json | 25 - .../protoc-gen-es-linux-arm64/package.json | 25 - packages/protoc-gen-es-netbsd-64/package.json | 25 - .../protoc-gen-es-openbsd-64/package.json | 25 - .../protoc-gen-es-windows-32/package.json | 25 - .../protoc-gen-es-windows-64/package.json | 25 - .../protoc-gen-es-windows-arm64/package.json | 25 - packages/protoc-gen-es/README.md | 60 +- packages/protoc-gen-es/bin/protoc-gen-es | 6 + packages/protoc-gen-es/package.json | 30 +- packages/protoc-gen-es/src/declaration.ts | 221 ++ packages/protoc-gen-es/src/javascript.ts | 562 ++++ packages/protoc-gen-es/src/match-wkt.ts | 285 ++ .../protoc-gen-es/src/protoc-gen-es-plugin.ts | 43 + packages/protoc-gen-es/src/typescript.ts | 587 ++++ packages/protoc-gen-es/tsconfig.json | 4 + packages/protoplugin/README.md | 38 + packages/protoplugin/package.json | 48 + packages/protoplugin/src/create-es-plugin.ts | 153 + .../protoplugin/src/ecmascript/gencommon.ts | 381 +++ .../src/ecmascript/generated-file.ts | 433 +++ .../src/ecmascript/import-symbol.ts | 79 + packages/protoplugin/src/ecmascript/index.ts | 32 + .../src/ecmascript/runtime-imports.ts | 72 + packages/protoplugin/src/ecmascript/schema.ts | 165 ++ .../protoplugin/src/ecmascript/target.ts | 25 +- packages/protoplugin/src/error.ts | 33 + .../src/index.ts} | 21 +- .../src/plugin.ts} | 25 +- packages/protoplugin/src/run-node.ts | 92 + packages/protoplugin/tsconfig.json | 4 + private/protoplugin/comments.go | 148 - private/protoplugin/generated_file.go | 307 -- private/protoplugin/generated_file_test.go | 127 - private/protoplugin/names.go | 320 --- private/protoplugin/names_test.go | 159 -- private/protoplugin/protoplugin.go | 1246 --------- private/protoplugin/run_test.go | 112 - private/protoplugin/runtime.go | 78 - .../set-workspace-version.js | 0 274 files changed, 20586 insertions(+), 6991 deletions(-) delete mode 100644 .golangci.yaml delete mode 100644 cmd/protoc-gen-es/internal/gencommon/gencommon.go delete mode 100644 cmd/protoc-gen-es/internal/gencommon/textformat.go delete mode 100644 cmd/protoc-gen-es/internal/gencommon/typescript.go delete mode 100644 cmd/protoc-gen-es/internal/gencommon/wkt.go delete mode 100644 cmd/protoc-gen-es/internal/gendts/gendts.go delete mode 100644 cmd/protoc-gen-es/internal/genjs/genjs.go delete mode 100644 cmd/protoc-gen-es/internal/gents/gents.go delete mode 100644 cmd/protoc-gen-es/main.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100755 make/scripts/checknodiffgenerated.bash delete mode 100755 make/scripts/go-build-npm-shim.cjs delete mode 100755 make/scripts/go-build-npm.js delete mode 100755 make/scripts/update-go-version-file.js delete mode 100644 packages/README.md rename packages/{bench-codesize => protobuf-bench}/README.md (92%) create mode 100644 packages/protobuf-bench/buf.gen.yaml rename packages/{bench-codesize => protobuf-bench}/package.json (86%) rename packages/{bench-codesize => protobuf-bench}/report.mjs (100%) rename packages/{bench-codesize => protobuf-bench}/src/entry-google-protobuf.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/entry-protobuf-es.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/envelope_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/module_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/plugin_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/repository_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/role_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/search_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/user_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/breaking/v1/config_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/image/v1/image_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/lint/v1/config_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/module/v1alpha1/module_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/admin_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/audit_logs_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authn_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authz_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/display_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/doc_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/download_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/generate_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/image_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/jsonschema_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/module_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/organization_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/owner_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/plugin_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/push_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/recommendation_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/reference_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_branch_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_commit_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_tag_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_commit_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/resolve_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/role_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/search_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/token_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/user_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/google-protobuf/buf/alpha/rpc/v1alpha1/error_pb.js (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts (95%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts (97%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts (98%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts (83%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts (85%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts (90%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/breaking/v1/config_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/lint/v1/config_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/admin_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts (98%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authn_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authz_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/display_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/doc_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/download_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/generate_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/jsonschema_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts (98%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/owner_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/plugin_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/push_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/reference_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/resolve_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/role_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/search_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts (99%) rename packages/{bench-codesize => protobuf-bench}/src/gen/protobuf-es/buf/alpha/rpc/v1alpha1/error_pb.ts (100%) rename packages/{bench-codesize => protobuf-bench}/tsconfig.json (100%) rename packages/{conformance-test => protobuf-conformance}/README.md (100%) rename packages/{conformance-test => protobuf-conformance}/bin/conformance_esm.js (100%) rename packages/{conformance-test => protobuf-conformance}/conformance_failing_tests.txt (100%) rename packages/{conformance-test => protobuf-conformance}/conformance_failing_tests_text_format.txt (100%) rename packages/{conformance-test => protobuf-conformance}/package.json (92%) rename packages/{conformance-test => protobuf-conformance}/src/conformance.ts (97%) rename packages/{conformance-test => protobuf-conformance}/src/gen/conformance/conformance_pb.ts (100%) rename packages/{conformance-test => protobuf-conformance}/src/gen/google/protobuf/test_messages_proto2_pb.ts (99%) rename packages/{conformance-test => protobuf-conformance}/src/gen/google/protobuf/test_messages_proto3_pb.ts (99%) rename packages/{conformance-test => protobuf-conformance}/tsconfig.json (100%) rename packages/protobuf-test/extra/{enum-annotated.proto => enum.proto} (66%) create mode 100644 packages/protobuf-test/src/create-registry-from-desc.test.ts create mode 100644 packages/protobuf-test/src/create-registry.test.ts create mode 100644 packages/protobuf-test/src/descriptor-set.test.ts create mode 100644 packages/protobuf-test/src/enum.test.ts create mode 100644 packages/protobuf-test/src/gen/js/extra/enum_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/extra/enum_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/any_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/any_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/api_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/api_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.js create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.d.ts create mode 100644 packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.js delete mode 100644 packages/protobuf-test/src/gen/ts/extra/enum-annotated_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/extra/enum_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/any_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/api_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/compiler/plugin_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/descriptor_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/duration_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/empty_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/field_mask_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/source_context_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/struct_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/timestamp_pb.ts create mode 100644 packages/protobuf-test/src/gen/ts/google/protobuf/wrappers_pb.ts create mode 100644 packages/protobuf-test/src/google/protobuf/wrappers.test.ts rename packages/protobuf-test/src/{descriptor-registry.test.ts => legacy-descriptor-registry.test.ts} (75%) create mode 100644 packages/protobuf-test/src/legacy-descriptor-set.test.ts create mode 100644 packages/protobuf/src/codegen-info.ts create mode 100644 packages/protobuf/src/create-descriptor-set.ts create mode 100644 packages/protobuf/src/create-registry-from-desc.ts create mode 100644 packages/protobuf/src/create-registry.ts rename packages/protobuf/src/{descriptor-registry.ts => legacy-descriptor-registry.ts} (95%) create mode 100644 packages/protobuf/src/legacy-descriptor-set.ts create mode 100644 packages/protobuf/src/legacy-type-registry.ts delete mode 100644 packages/protoc-gen-es-darwin-64/package.json delete mode 100644 packages/protoc-gen-es-darwin-arm64/package.json delete mode 100644 packages/protoc-gen-es-freebsd-64/package.json delete mode 100644 packages/protoc-gen-es-freebsd-arm64/package.json delete mode 100644 packages/protoc-gen-es-linux-32/package.json delete mode 100644 packages/protoc-gen-es-linux-64/package.json delete mode 100644 packages/protoc-gen-es-linux-arm/package.json delete mode 100644 packages/protoc-gen-es-linux-arm64/package.json delete mode 100644 packages/protoc-gen-es-netbsd-64/package.json delete mode 100644 packages/protoc-gen-es-openbsd-64/package.json delete mode 100644 packages/protoc-gen-es-windows-32/package.json delete mode 100644 packages/protoc-gen-es-windows-64/package.json delete mode 100644 packages/protoc-gen-es-windows-arm64/package.json create mode 100755 packages/protoc-gen-es/bin/protoc-gen-es create mode 100644 packages/protoc-gen-es/src/declaration.ts create mode 100644 packages/protoc-gen-es/src/javascript.ts create mode 100644 packages/protoc-gen-es/src/match-wkt.ts create mode 100644 packages/protoc-gen-es/src/protoc-gen-es-plugin.ts create mode 100644 packages/protoc-gen-es/src/typescript.ts create mode 100644 packages/protoc-gen-es/tsconfig.json create mode 100644 packages/protoplugin/README.md create mode 100644 packages/protoplugin/package.json create mode 100644 packages/protoplugin/src/create-es-plugin.ts create mode 100644 packages/protoplugin/src/ecmascript/gencommon.ts create mode 100644 packages/protoplugin/src/ecmascript/generated-file.ts create mode 100644 packages/protoplugin/src/ecmascript/import-symbol.ts create mode 100644 packages/protoplugin/src/ecmascript/index.ts create mode 100644 packages/protoplugin/src/ecmascript/runtime-imports.ts create mode 100644 packages/protoplugin/src/ecmascript/schema.ts rename private/protoplugin/fuzz_test.go => packages/protoplugin/src/ecmascript/target.ts (62%) create mode 100644 packages/protoplugin/src/error.ts rename packages/{protobuf-test/src/gen/js/extra/enum-annotated_pb.js => protoplugin/src/index.ts} (58%) rename packages/{protobuf-test/src/gen/js/extra/enum-annotated_pb.d.ts => protoplugin/src/plugin.ts} (61%) create mode 100644 packages/protoplugin/src/run-node.ts create mode 100644 packages/protoplugin/tsconfig.json delete mode 100644 private/protoplugin/comments.go delete mode 100644 private/protoplugin/generated_file.go delete mode 100644 private/protoplugin/generated_file_test.go delete mode 100644 private/protoplugin/names.go delete mode 100644 private/protoplugin/names_test.go delete mode 100644 private/protoplugin/protoplugin.go delete mode 100644 private/protoplugin/run_test.go delete mode 100644 private/protoplugin/runtime.go rename {make/scripts => scripts}/set-workspace-version.js (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3e4a5cb69..7a2aa09b3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,10 +8,6 @@ jobs: steps: - name: checkout uses: actions/checkout@v3 - - name: setup-go - uses: actions/setup-go@v3 - with: - go-version: 1.18 - uses: bufbuild/buf-setup-action@v1.6.0 with: version: 1.1.0 @@ -19,20 +15,10 @@ jobs: uses: actions/cache@v3 with: path: | - ~/.cache - .cache + ~/.tmp + .tmp key: ${{ runner.os }}-protobuf-es-ci-${{ hashFiles('Makefile') }} restore-keys: | ${{ runner.os }}-protobuf-es-ci- - - name: make-ci-generate - run: bash make/scripts/checknodiffgenerated.bash make ci-generate - - name: make-format - run: bash make/scripts/checknodiffgenerated.bash make format - - name: make-build - run: make build - - name: make-lint - run: make lint - - name: make-test - run: make test - - name: make-bench-codesize - run: make bench-codesize + - name: make + run: make all checkdiff diff --git a/.gitignore b/.gitignore index 853246b56..5e457f72f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ node_modules +/packages/*/dist +/packages/protobuf-test/descriptorset.bin /testdata/gen/**/*.js /testdata/gen/**/*.ts /testdata/gen/**/**.d.ts -/packages/protoc-gen-es*/bin/protoc-gen-es* -/packages/*/dist -/packages/protobuf-test/descriptorset.bin -/.cache +/.tmp diff --git a/.golangci.yaml b/.golangci.yaml deleted file mode 100644 index 2e6e70e29..000000000 --- a/.golangci.yaml +++ /dev/null @@ -1,67 +0,0 @@ -run: - skip-dirs-use-default: false -linters-settings: - errcheck: - check-type-assertions: true - forbidigo: - forbid: - - '^fmt\.Print' - - '^log\.' - - '^print$' - - '^println$' -linters: - enable: - - asciicheck - - bidichk - - bodyclose - - containedctx - - contextcheck - - deadcode - - decorder - - depguard - - dogsled - - errcheck - - exportloopref - - forbidigo - - forcetypeassert - - gochecknoinits - - gofmt - - goheader - - goimports - - gomodguard - - goprintffuncname - - gosec - - gosimple - - govet - - grouper - - importas - - ineffassign - - makezero - - misspell - - nakedret - - nilerr - - nolintlint - - predeclared - - promlinter - - rowserrcheck - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unused - - varcheck - - wastedassign - - whitespace - disable-all: true -issues: - exclude-rules: - - linters: [gosec] - path: private/protoplugin/names.go - text: "G101: Potential hardcoded credentials" - - linters: [stylecheck] - path: private/protoplugin/comments.go - text: "ST1003: should not use underscores in Go names; const fieldNumber_" - - linters: [stylecheck] - path: private/protoplugin/runtime.go - text: "ST1003: struct field Json" diff --git a/.prettierignore b/.prettierignore index 5db0a0219..43f80108d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,6 @@ -/packages/*/src/gen -/packages/*/dist -/packages/*/bin /node_modules -/.cache +/packages/*/bin +/packages/*/dist +/packages/*/src/gen /packages/protobuf/src/google +/.tmp diff --git a/Makefile b/Makefile index 350c0860d..40f276232 100644 --- a/Makefile +++ b/Makefile @@ -1,260 +1,217 @@ -CACHE_DIR = .cache -SHELL := /usr/bin/env bash -o pipefail -.DEFAULT_GOAL = all -export PATH := $(abspath $(CACHE_DIR)/bin):$(PATH) - -# We use the official protocolbuffers implementation to: -# 1. generate wkt as part of the NPM package "@bufbuild/protobuf" -# 2. test conformance -# 3. test .proto file compilation -GOOGLE_PROTOBUF_VERSION = 3.20.1 -GOOGLE_PROTOBUF_SOURCE_URL = https://github.com/protocolbuffers/protobuf/releases/download/v$(GOOGLE_PROTOBUF_VERSION)/protobuf-all-$(GOOGLE_PROTOBUF_VERSION).tar.gz -GOOGLE_PROTOBUF_SOURCE = $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION) -GOOGLE_PROTOBUF_WKT_PROTOS = google/protobuf/api.proto google/protobuf/any.proto google/protobuf/compiler/plugin.proto google/protobuf/descriptor.proto google/protobuf/duration.proto google/protobuf/descriptor.proto google/protobuf/empty.proto google/protobuf/field_mask.proto google/protobuf/source_context.proto google/protobuf/struct.proto google/protobuf/timestamp.proto google/protobuf/type.proto google/protobuf/wrappers.proto -GOOGLE_PROTOBUF_CONFORMANCE_RUNNER_BIN = $(GOOGLE_PROTOBUF_SOURCE)/bazel-bin/conformance_test_runner -GOOGLE_PROTOBUF_PROTOC_BIN = $(GOOGLE_PROTOBUF_SOURCE)/bazel-bin/protoc -$(GOOGLE_PROTOBUF_SOURCE): - mkdir -p $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION) - curl --silent -L $(GOOGLE_PROTOBUF_SOURCE_URL) > $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION).tar.gz - tar -xzf $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION).tar.gz -C $(CACHE_DIR)/ -$(GOOGLE_PROTOBUF_PROTOC_BIN): $(GOOGLE_PROTOBUF_SOURCE) - cd $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION) && bazel build protoc - touch $(GOOGLE_PROTOBUF_PROTOC_BIN) -$(GOOGLE_PROTOBUF_CONFORMANCE_RUNNER_BIN): $(GOOGLE_PROTOBUF_SOURCE) - cd $(CACHE_DIR)/protobuf-$(GOOGLE_PROTOBUF_VERSION) && bazel build test_messages_proto3_proto conformance_proto conformance_test conformance_test_runner -export PATH := $(abspath $(GOOGLE_PROTOBUF_SOURCE)/bazel-bin):$(PATH) - - -# Install license-header -LICENSE_HEADER_VERSION := v1.1.0 -LICENSE_HEADER_LICENSE_TYPE := apache -LICENSE_HEADER_COPYRIGHT_HOLDER := Buf Technologies, Inc. +# See https://tech.davis-hansson.com/p/make/ +SHELL := bash +.DELETE_ON_ERROR: +.SHELLFLAGS := -eu -o pipefail -c +.DEFAULT_GOAL := all +MAKEFLAGS += --warn-undefined-variables +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --no-print-directory +TMP = .tmp +BIN = .tmp/bin +BUILD = .tmp/build +GEN = .tmp/gen +PB = .tmp/protobuf-$(GOOGLE_PROTOBUF_VERSION) LICENSE_HEADER_YEAR_RANGE := 2021-2022 -LICENSE_HEADER_IGNORES := .cache\/ node_module\/ packages\/conformance-test\/bin\/conformance_esm.js packages\/conformance-test\/src\/gen\/ packages\/protobuf-test\/src\/gen\/ packages\/protobuf\/src\/google\/varint.ts packages\/bench-codesize\/src\/gen\/ packages\/protobuf\/dist\/ packages\/protobuf-test\/dist\/ make\/scripts\/ -LICENSE_HEADER_DEP := $(CACHE_DIR)/dep/license-header-$(LICENSE_HEADER_VERSION) -$(LICENSE_HEADER_DEP): - GOBIN=$(abspath $(CACHE_DIR)/bin) go install github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@$(LICENSE_HEADER_VERSION) - mkdir -p $(dir $(LICENSE_HEADER_DEP)) && touch $(LICENSE_HEADER_DEP) - - -# Install git-ls-files-unstaged -GIT_LS_FILES_UNSTAGED_VERSION ?= v1.1.0 -GIT_LS_FILES_UNSTAGED_DEP := $(CACHE_DIR)/dep/git-ls-files-unstaged-$(GIT_LS_FILES_UNSTAGED_VERSION) -$(GIT_LS_FILES_UNSTAGED_DEP): - GOBIN=$(abspath $(CACHE_DIR)/bin) go install github.com/bufbuild/buf/private/pkg/git/cmd/git-ls-files-unstaged@$(GIT_LS_FILES_UNSTAGED_VERSION) - mkdir -p $(dir $(GIT_LS_FILES_UNSTAGED_DEP)) && touch $(GIT_LS_FILES_UNSTAGED_DEP) - - -# Install golangci-lint -GOLANGCI_LINT_VERSION ?= v1.44.0 -GOLANGCI_LINT_DEP := $(CACHE_DIR)/dep/golangci-lint-$(GOLANGCI_LINT_VERSION) -$(GOLANGCI_LINT_DEP): - GOBIN=$(abspath $(CACHE_DIR)/bin) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) - mkdir -p $(dir $(GOLANGCI_LINT_DEP)) && touch $(GOLANGCI_LINT_DEP) - +LICENSE_HEADER_IGNORES := .cache\/ node_module\/ packages\/protobuf-conformance\/bin\/conformance_esm.js packages\/protobuf-conformance\/src\/gen\/ packages\/protobuf-test\/src\/gen\/ packages\/protobuf\/src\/google\/varint.ts packages\/protobuf-bench\/src\/gen\/ packages\/protobuf\/dist\/ packages\/protobuf-test\/dist\/ scripts\/ +GOOGLE_PROTOBUF_WKT = google/protobuf/api.proto google/protobuf/any.proto google/protobuf/compiler/plugin.proto google/protobuf/descriptor.proto google/protobuf/duration.proto google/protobuf/descriptor.proto google/protobuf/empty.proto google/protobuf/field_mask.proto google/protobuf/source_context.proto google/protobuf/struct.proto google/protobuf/timestamp.proto google/protobuf/type.proto google/protobuf/wrappers.proto +GOOGLE_PROTOBUF_VERSION = 3.20.1 -# Install NPM dependencies -# (We need --force so NPM doesn't bail on the platform-specific -# packages in the workspace) node_modules: package-lock.json - npm ci --force - - -# Our code generator protoc-gen-es generates message and enum types -# It is used within the project to: -# 1. compile .proto files for tests -# 2. generate wkt as part of the NPM package "@bufbuild/protobuf" -PROTOC_GEN_ES_BIN := $(CACHE_DIR)/protoc-gen-es -PROTOC_GEN_ES_SOURCES = go.mod $(shell find . -name '*.go') -$(PROTOC_GEN_ES_BIN): $(PROTOC_GEN_ES_SOURCES) - go build -o $(PROTOC_GEN_ES_BIN) ./cmd/protoc-gen-es - - -# The NPM package "@bufbuild/protobuf" is the runtime library required by the code our plugin generates -RUNTIME_DIR = packages/protobuf -RUNTIME_GEN = $(CACHE_DIR)/gen/bufbuild-protobuf-wkt-$(GOOGLE_PROTOBUF_VERSION) -RUNTIME_BUILD = $(CACHE_DIR)/build/packages-protobuf -RUNTIME_SOURCES = $(RUNTIME_DIR)/*.json $(RUNTIME_DIR)/src/*.ts $(RUNTIME_DIR)/src/*/*.ts -$(RUNTIME_BUILD): node_modules $(RUNTIME_GEN) $(RUNTIME_SOURCES) - cd $(RUNTIME_DIR) && npm run clean && npm run build - mkdir -p $(CACHE_DIR)/build && touch $(RUNTIME_BUILD) -$(RUNTIME_GEN): $(GOOGLE_PROTOBUF_PROTOC_BIN) $(PROTOC_GEN_ES_BIN) $(LICENSE_HEADER_DEP) - $(GOOGLE_PROTOBUF_PROTOC_BIN) -I $(GOOGLE_PROTOBUF_SOURCE)/src --plugin $(PROTOC_GEN_ES_BIN) --es_out $(RUNTIME_DIR)/src --es_opt bootstrap_wkt=true,ts_nocheck=false,target=ts $(GOOGLE_PROTOBUF_WKT_PROTOS) - find $(RUNTIME_DIR)/src/google -name '*.ts' \ - | grep -v $(patsubst %,-e %,$(sort $(LICENSE_HEADER_IGNORES))) \ - | xargs license-header \ - --license-type "$(LICENSE_HEADER_LICENSE_TYPE)" \ - --copyright-holder "$(LICENSE_HEADER_COPYRIGHT_HOLDER)" \ - --year-range "$(LICENSE_HEADER_YEAR_RANGE)" - mkdir -p $(dir $(RUNTIME_GEN)) && touch $(RUNTIME_GEN) - - -# The private NPM package "@bufbuild/conformance-test" runs the protobuf conformance test suite -CONFORMANCE_DIR = packages/conformance-test -CONFORMANCE_GEN = $(CACHE_DIR)/gen/conformance-test-$(GOOGLE_PROTOBUF_VERSION) -CONFORMANCE_BUILD = $(CACHE_DIR)/build/conformance-test -CONFORMANCE_SOURCES = $(shell find $(CONFORMANCE_DIR)/src -name '*.ts' -or -name '*.js') $(CONFORMANCE_DIR)/*.json -$(CONFORMANCE_GEN): $(GOOGLE_PROTOBUF_SOURCE) $(GOOGLE_PROTOBUF_PROTOC_BIN) $(PROTOC_GEN_ES_BIN) $(shell find $(CONFORMANCE_DIR) -name '*.proto') - rm -rf $(CONFORMANCE_DIR)/src/gen/* - $(GOOGLE_PROTOBUF_PROTOC_BIN) --plugin $(PROTOC_GEN_ES_BIN) --es_out $(CONFORMANCE_DIR)/src/gen --es_opt ts_nocheck=false,target=ts \ - -I $(GOOGLE_PROTOBUF_SOURCE) -I $(GOOGLE_PROTOBUF_SOURCE)/src \ + npm ci + +$(PB): + echo $(PB) + @mkdir -p $(TMP) + curl -L https://github.com/protocolbuffers/protobuf/releases/download/v$(GOOGLE_PROTOBUF_VERSION)/protobuf-all-$(GOOGLE_PROTOBUF_VERSION).tar.gz \ + > $(TMP)/protobuf-$(GOOGLE_PROTOBUF_VERSION).tar.gz + tar -xzf $(TMP)/protobuf-$(GOOGLE_PROTOBUF_VERSION).tar.gz -C $(TMP)/ + +$(BIN)/protoc: $(PB) + @mkdir -p $(@D) + cd $(PB) && bazel build protoc + cp -f $(PB)/bazel-bin/protoc $(@D) + @touch $(@) + +$(BIN)/conformance_test_runner: $(PB) + @mkdir -p $(@D) + cd $(PB) && bazel build test_messages_proto3_proto conformance_proto conformance_test conformance_test_runner + cp -f $(PB)/bazel-bin/conformance_test_runner $(@D) + @touch $(@) + +$(BIN)/license-header: Makefile + @mkdir -p $(@D) + GOBIN=$(abspath $(BIN)) go install github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@v1.1.0 + +$(BIN)/git-ls-files-unstaged: Makefile + @mkdir -p $(@D) + GOBIN=$(abspath $(BIN)) go install github.com/bufbuild/buf/private/pkg/git/cmd/git-ls-files-unstaged@v1.1.0 + +$(BUILD)/protobuf: node_modules tsconfig.base.json packages/protobuf/tsconfig.json $(shell find packages/protobuf/src -name '*.ts') + npm run -w packages/protobuf clean + npm run -w packages/protobuf build + @mkdir -p $(@D) + @touch $(@) + +$(BUILD)/protobuf-test: $(BUILD)/protobuf $(GEN)/protobuf-test node_modules tsconfig.base.json packages/protobuf-test/tsconfig.json $(shell find packages/protobuf-test/src -name '*.ts') + npm run -w packages/protobuf-test clean + npm run -w packages/protobuf-test build + @mkdir -p $(@D) + @touch $(@) + +$(BUILD)/protoplugin: $(BUILD)/protobuf node_modules tsconfig.base.json packages/protoplugin/tsconfig.json $(shell find packages/protoplugin/src -name '*.ts') + npm run -w packages/protoplugin clean + npm run -w packages/protoplugin build + @mkdir -p $(@D) + @touch $(@) + +$(BUILD)/protoc-gen-es: $(BUILD)/protoplugin node_modules tsconfig.base.json packages/protoc-gen-es/tsconfig.json $(shell find packages/protoc-gen-es/src -name '*.ts') + npm run -w packages/protoc-gen-es clean + npm run -w packages/protoc-gen-es build + @mkdir -p $(@D) + @touch $(@) + +$(BUILD)/protobuf-conformance: $(GEN)/protobuf-conformance node_modules tsconfig.base.json packages/protobuf-conformance $(shell find packages/protobuf-conformance/src -name '*.ts') + npm run -w packages/protobuf-conformance clean + npm run -w packages/protobuf-conformance build + @mkdir -p $(@D) + @touch $(@) + +$(BUILD)/example: $(BUILD)/protobuf node_modules tsconfig.base.json packages/example/tsconfig.json $(shell find packages/example/src -name '*.ts') + npm run -w packages/example clean + npm run -w packages/example build + @mkdir -p $(@D) + @touch $(@) + +$(GEN)/protobuf-test: $(BIN)/protoc $(BUILD)/protoc-gen-es + @rm -rf packages/protobuf-test/src/gen/ts/* packages/protobuf-test/src/gen/js/* packages/protobuf-test/descriptorset.bin + $(BIN)/protoc \ + --descriptor_set_out packages/protobuf-test/descriptorset.bin --include_imports --include_source_info \ + --plugin protoc-gen-a=packages/protoc-gen-es/bin/protoc-gen-es --a_out packages/protobuf-test/src/gen/ts --a_opt ts_nocheck=false,target=ts \ + --plugin protoc-gen-b=packages/protoc-gen-es/bin/protoc-gen-es --b_out packages/protobuf-test/src/gen/js --b_opt ts_nocheck=false,target=js+dts \ + --proto_path $(PB) --proto_path $(PB)/src -I packages/protobuf-test \ + $(shell cd packages/protobuf-test && find . -name '*.proto' | cut -sd / -f 2-) \ + $(shell cd $(PB)/src && find . -name 'unittest*.proto' | cut -sd / -f 2-) \ + google/protobuf/type.proto \ + google/protobuf/test_messages_proto2.proto \ + google/protobuf/test_messages_proto3.proto + $(BIN)/protoc \ + --plugin protoc-gen-a=packages/protoc-gen-es/bin/protoc-gen-es --a_out packages/protobuf-test/src/gen/ts --a_opt ts_nocheck=false,target=ts \ + --plugin protoc-gen-b=packages/protoc-gen-es/bin/protoc-gen-es --b_out packages/protobuf-test/src/gen/js --b_opt ts_nocheck=false,target=js+dts \ + --proto_path $(PB)/src \ + $(GOOGLE_PROTOBUF_WKT) + @mkdir -p $(@D) + @touch $(@) + +$(GEN)/protobuf-conformance: $(BIN)/protoc $(BUILD)/protoc-gen-es Makefile + @rm -rf packages/protobuf-conformance/src/gen/* + $(BIN)/protoc --plugin packages/protoc-gen-es/bin/protoc-gen-es --es_out packages/protobuf-conformance/src/gen --es_opt ts_nocheck=false,target=ts \ + --proto_path $(PB) --proto_path $(PB)/src \ conformance/conformance.proto \ google/protobuf/test_messages_proto2.proto \ google/protobuf/test_messages_proto3.proto - mkdir -p $(dir $(CONFORMANCE_GEN)) && touch $(CONFORMANCE_GEN) -$(CONFORMANCE_BUILD): $(PROTOC_GEN_ES_BIN) $(CONFORMANCE_GEN) $(RUNTIME_BUILD) $(CONFORMANCE_SOURCES) - cd $(CONFORMANCE_DIR) && npm run clean && npm run build - mkdir -p $(dir $(CONFORMANCE_BUILD)) && touch $(CONFORMANCE_BUILD) - - -# The private NPM package "@bufbuild/protobuf-test" is used to test: -# 1. compilation of a large number of .proto files -# 2. unit test generated code -# 3. test interoperability with protoc (JSON names) -TEST_DIR = packages/protobuf-test -TEST_GEN = $(CACHE_DIR)/gen/protobuf-test-$(GOOGLE_PROTOBUF_VERSION) -TEST_BUILD = $(CACHE_DIR)/build/protobuf-test -TEST_SOURCES = $(shell find $(TEST_DIR)/src -name '*.ts') $(TEST_DIR)/*.json -$(TEST_GEN) : protoc = $(GOOGLE_PROTOBUF_PROTOC_BIN) -I $(GOOGLE_PROTOBUF_SOURCE) -I $(GOOGLE_PROTOBUF_SOURCE)/src -I $(TEST_DIR) $(shell cd $(TEST_DIR) && find . -name '*.proto' | cut -sd / -f 2-) google/protobuf/type.proto $(shell cd $(GOOGLE_PROTOBUF_SOURCE)/src && find . -name 'unittest*.proto' | cut -sd / -f 2-) google/protobuf/test_messages_proto2.proto google/protobuf/test_messages_proto3.proto -$(TEST_GEN): $(GOOGLE_PROTOBUF_SOURCE) $(GOOGLE_PROTOBUF_PROTOC_BIN) $(PROTOC_GEN_ES_BIN) $(shell find $(TEST_DIR) -name '*.proto') - rm -rf $(TEST_DIR)/src/gen/ts/* $(TEST_DIR)/src/gen/js/* $(TEST_DIR)/descriptorset.bin - $(protoc) --plugin $(PROTOC_GEN_ES_BIN) --es_out $(TEST_DIR)/src/gen/ts --es_opt ts_nocheck=false,target=ts - $(protoc) --plugin $(PROTOC_GEN_ES_BIN) --es_out $(TEST_DIR)/src/gen/js --es_opt ts_nocheck=false,target=js+dts - $(protoc) --descriptor_set_out $(TEST_DIR)/descriptorset.bin --include_imports --include_source_info - mkdir -p $(dir $(TEST_GEN)) && touch $(TEST_GEN) -$(TEST_BUILD): $(PROTOC_GEN_ES_BIN) $(TEST_GEN) $(RUNTIME_BUILD) $(TEST_SOURCES) - cd $(TEST_DIR) && npm run clean && npm run build - mkdir -p $(dir $(TEST_BUILD)) && touch $(TEST_BUILD) - - -# The private NPM package "@bufbuild/bench-codesize" benchmarks code size -BENCHCODESIZE_DIR = packages/bench-codesize -BENCHCODESIZE_BUF_COMMIT=4505cba5e5a94a42af02ebc7ac3a0a04 -BENCHCODESIZE_GEN = $(CACHE_DIR)/gen/bench-codesize-$(BENCHCODESIZE_BUF_COMMIT) -BUF_GENERATE_TEMPLATE = '\ -{\ - "version": "v1",\ - "plugins": [\ - {\ - "name":"es", \ - "path": "$(PROTOC_GEN_ES_BIN)",\ - "out": "$(BENCHCODESIZE_DIR)/src/gen/protobuf-es",\ - "opt": "ts_nocheck=false,target=ts"\ - },{\ - "remote":"buf.build/protocolbuffers/plugins/js:v3.19.3-1", \ - "out": "$(BENCHCODESIZE_DIR)/src/gen/google-protobuf", \ - "opt": "import_style=commonjs"\ - }\ - ]\ -}' -$(BENCHCODESIZE_GEN): $(PROTOC_GEN_ES_BIN) $(PROTOC_GEN_CONNECT_WEB_BIN) - rm -rf $(BENCHCODESIZE_DIR)/src/gen/* - buf generate buf.build/bufbuild/buf:$(BENCHCODESIZE_BUF_COMMIT) --template $(BUF_GENERATE_TEMPLATE) - mkdir -p $(dir $(BENCHCODESIZE_GEN)) && touch $(BENCHCODESIZE_GEN) + @mkdir -p $(@D) + @touch $(@) +$(GEN)/example: $(BIN)/protoc $(BUILD)/protoc-gen-es packages/example/buf.gen.yaml $(shell find packages/example -name '*.proto') + @rm -rf packages/example/src/gen/* + buf generate packages/example --template packages/example/buf.gen.yaml --output packages/example + @mkdir -p $(@D) + @touch $(@) -# The private NPM package "@bufbuild/example" provides a code example -EXAMPLE_DIR = packages/example -EXAMPLE_GEN = $(CACHE_DIR)/gen/example -EXAMPLE_BUILD = $(CACHE_DIR)/build/example -EXAMPLE_SOURCES = $(shell find $(EXAMPLE_DIR)/src -name '*.ts' -or -name '*.js') $(EXAMPLE_DIR)/*.json -EXAMPLE_PROTOS = $(shell find $(EXAMPLE_DIR) -name '*.proto') -$(EXAMPLE_GEN): $(GOOGLE_PROTOBUF_PROTOC_BIN) $(PROTOC_GEN_ES_BIN) $(EXAMPLE_PROTOS) - rm -rf $(EXAMPLE_DIR)/src/gen/* - $(GOOGLE_PROTOBUF_PROTOC_BIN) --plugin $(PROTOC_GEN_ES_BIN) --es_out $(EXAMPLE_DIR)/src/gen --es_opt target=ts \ - -I $(GOOGLE_PROTOBUF_SOURCE)/src \ - -I $(EXAMPLE_DIR) \ - $(EXAMPLE_PROTOS) - mkdir -p $(dir $(EXAMPLE_GEN)) && touch $(EXAMPLE_GEN) -$(EXAMPLE_BUILD): $(PROTOC_GEN_ES_BIN) $(EXAMPLE_GEN) $(RUNTIME_BUILD) $(EXAMPLE_SOURCES) - cd $(EXAMPLE_DIR) && npm run clean && npm run build - mkdir -p $(dir $(EXAMPLE_BUILD)) && touch $(EXAMPLE_BUILD) +$(GEN)/protobuf-bench: $(BIN)/protoc $(BUILD)/protoc-gen-es packages/protobuf-bench Makefile + @rm -rf packages/protobuf-bench/src/gen/* + buf generate buf.build/bufbuild/buf:4505cba5e5a94a42af02ebc7ac3a0a04 --template packages/protobuf-bench/buf.gen.yaml --output packages/protobuf-bench + @mkdir -p $(@D) + @touch $(@) - -# Commands -.PHONY: all clean test-go test-jest test-conformance fuzz-go set-version - +.PHONY: help help: ## Describe useful make targets @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}' -all: build test format lint bench-codesize ## build, test, format, lint, and bench-codesize (default) +.PHONY: all +all: build test format lint bench bootstrapwkt ## build, test, format, lint, bench, and bootstrapwkt (default) +.PHONY: clean clean: ## Delete build artifacts and installed dependencies - cd $(RUNTIME_DIR); npm run clean - cd $(TEST_DIR); npm run clean - cd $(BENCHCODESIZE_DIR); npm run clean - [ -n "$(CACHE_DIR)" ] && rm -rf $(CACHE_DIR)/* - rm -rf node_modules - rm -rf packages/protoc-gen-*/bin/* - -build: $(RUNTIME_BUILD) $(TEST_BUILD) $(CONFORMANCE_BUILD) $(PROTOC_GEN_ES_BIN) $(EXAMPLE_BUILD) ## Build - -test: test-go test-jest test-conformance ## Run all tests + @# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs + git clean -Xdf -test-jest: $(TEST_BUILD) $(TEST_DIR)/*.config.js - cd $(TEST_DIR) && NODE_OPTIONS=--experimental-vm-modules npx jest +.PHONY: build +build: $(BUILD)/protobuf $(BUILD)/protobuf-test $(BUILD)/protoplugin $(BUILD)/protobuf-conformance $(BUILD)/protoc-gen-es $(BUILD)/example ## Build -test-conformance: $(GOOGLE_PROTOBUF_CONFORMANCE_RUNNER_BIN) $(PROTOC_GEN_ES_BIN) $(CONFORMANCE_BUILD) - $(GOOGLE_PROTOBUF_CONFORMANCE_RUNNER_BIN) --enforce_recommended --failure_list $(CONFORMANCE_DIR)/conformance_failing_tests.txt --text_format_failure_list $(CONFORMANCE_DIR)/conformance_failing_tests_text_format.txt $(CONFORMANCE_DIR)/bin/conformance_esm.js +.PHONY: test +test: test-jest test-conformance ## Run all tests -test-go: $(TEST_GEN) - go test ./private/... ./cmd/... +.PHONY: test-jest +test-jest: $(BUILD)/protobuf-test packages/protobuf-test/jest.config.js + cd packages/protobuf-test && PATH="$(abspath $(BIN)):$(PATH)" NODE_OPTIONS=--experimental-vm-modules npx jest -fuzz-go: - gotip test ./private/protoplugin -cpu=1 -parallel=1 -fuzz FuzzProtoCamelCase +.PHONY: test-conformance +test-conformance: $(BIN)/conformance_test_runner $(BUILD)/protobuf-conformance + $(BIN)/conformance_test_runner --enforce_recommended \ + --failure_list packages/protobuf-conformance/conformance_failing_tests.txt \ + --text_format_failure_list packages/protobuf-conformance/conformance_failing_tests_text_format.txt \ + packages/protobuf-conformance/bin/conformance_esm.js -lint: $(GOLANGCI_LINT_DEP) node_modules $(RUNTIME_BUILD) $(TEST_BUILD) $(CONFORMANCE_BUILD) $(BENCHCODESIZE_GEN) $(EXAMPLE_GEN) ## Lint all files - golangci-lint run +.PHONY: lint +lint: node_modules $(BUILD)/protobuf $(BUILD)/protobuf-test $(BUILD)/protobuf-conformance $(GEN)/protobuf-bench $(GEN)/example ## Lint all files npx eslint --max-warnings 0 . -format: node_modules $(GIT_LS_FILES_UNSTAGED_DEP) $(LICENSE_HEADER_DEP) ## Format all files, adding license headers - go fmt ./private/... ./cmd/... +.PHONY: format +format: node_modules $(BIN)/git-ls-files-unstaged $(BIN)/license-header ## Format all files, adding license headers npx prettier --write '**/*.{json,js,jsx,ts,tsx,css}' --loglevel error - git-ls-files-unstaged | \ + $(BIN)/git-ls-files-unstaged | \ grep -v $(patsubst %,-e %,$(sort $(LICENSE_HEADER_IGNORES))) | \ - xargs license-header \ - --license-type "$(LICENSE_HEADER_LICENSE_TYPE)" \ - --copyright-holder "$(LICENSE_HEADER_COPYRIGHT_HOLDER)" \ + xargs $(BIN)/license-header \ + --license-type "apache" \ + --copyright-holder "Buf Technologies, Inc." \ --year-range "$(LICENSE_HEADER_YEAR_RANGE)" -bench-codesize: $(BENCHCODESIZE_GEN) node_modules $(RUNTIME_BUILD) ## Benchmark code size - cd $(BENCHCODESIZE_DIR) && npm run report +.PHONY: bench +bench: node_modules $(GEN)/protobuf-bench $(BUILD)/protobuf ## Benchmark code size + npm run -w packages/protobuf-bench report + +.PHONY: boostrapwkt +bootstrapwkt: $(BIN)/protoc $(BUILD)/protoc-gen-es $(BIN)/license-header ## Generate the well-known types in @bufbuild/protobuf + @rm -rf $(TMP)/bootstrapwkt + @mkdir -p $(TMP)/bootstrapwkt + $(BIN)/protoc \ + --plugin packages/protoc-gen-es/bin/protoc-gen-es --es_out $(TMP)/bootstrapwkt --es_opt bootstrap_wkt=true,ts_nocheck=false,target=ts \ + --proto_path $(PB)/src $(GOOGLE_PROTOBUF_WKT) + find $(TMP)/bootstrapwkt -name '*.ts' | \ + grep -v $(patsubst %,-e %,$(sort $(LICENSE_HEADER_IGNORES))) | \ + xargs $(BIN)/license-header \ + --license-type "apache" \ + --copyright-holder "Buf Technologies, Inc." \ + --year-range "$(LICENSE_HEADER_YEAR_RANGE)" + @# If the generated code differs, use it, and run tests again + diff >/dev/null -r packages/protobuf/src/google/protobuf $(TMP)/bootstrapwkt/google/protobuf || \ + (cp -r $(TMP)/bootstrapwkt/google/protobuf packages/protobuf/src/google/ && $(MAKE) build test format lint) -set-version: ## Set a new version in for the project, i.e. make set-version SET_VERSION=1.2.3 - node make/scripts/update-go-version-file.js cmd/protoc-gen-es/main.go $(SET_VERSION) - node make/scripts/set-workspace-version.js $(SET_VERSION) +.PHONY: setversion +setversion: ## Set a new version in for the project, i.e. make setversion SET_VERSION=1.2.3 + node scripts/set-workspace-version.js $(SET_VERSION) rm package-lock.json - npm i -f + npm i $(MAKE) all -# Some builds need code generation, some code generation needs builds. -# We expose this target only for ci, so it can check for diffs. -ci-generate: $(RUNTIME_GEN) $(TEST_GEN) $(BENCHCODESIZE_GEN) $(CONFORMANCE_GEN) $(EXAMPLE_GEN) - -# Release @bufbuild/protobuf. # Recommended procedure: -# 1. Set a new version with the target `set-version` +# 1. Set a new version with the target `setversion` # 2. Commit and push all changes # 3. Login with `npm login` # 4. Run this target, publishing to npmjs.com # 5. Tag the release +.PHONY: release release: all ## Release @bufbuild/protobuf @[ -z "$(shell git status --short)" ] || (echo "Uncommitted changes found." && exit 1); - node make/scripts/go-build-npm.js packages/protoc-gen-es ./cmd/protoc-gen-es npm publish \ --workspace packages/protobuf \ - --workspace packages/protoc-gen-es \ - --workspace packages/protoc-gen-es-darwin-64 \ - --workspace packages/protoc-gen-es-darwin-arm64 \ - --workspace packages/protoc-gen-es-freebsd-64 \ - --workspace packages/protoc-gen-es-freebsd-arm64 \ - --workspace packages/protoc-gen-es-linux-32 \ - --workspace packages/protoc-gen-es-linux-64 \ - --workspace packages/protoc-gen-es-linux-arm \ - --workspace packages/protoc-gen-es-linux-arm64 \ - --workspace packages/protoc-gen-es-netbsd-64 \ - --workspace packages/protoc-gen-es-openbsd-64 \ - --workspace packages/protoc-gen-es-windows-32 \ - --workspace packages/protoc-gen-es-windows-64 \ - --workspace packages/protoc-gen-es-windows-arm64 + --workspace packages/protoplugin \ + --workspace packages/protoc-gen-es + +.PHONY: checkdiff +checkdiff: + @# Used in CI to verify that `make` doesn't produce a diff, but ignore changes in benchmarks + git checkout packages/protobuf-bench/README.md + test -z "$$(git status --porcelain | tee /dev/stderr)" diff --git a/README.md b/README.md index 7007d5396..a138cd50f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Protobuf-ES =========== -A complete implementation of [protocol buffers](https://developers.google.com/protocol-buffers) in TypeScript, +A complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) in TypeScript, suitable for web browsers and Node.js. For example, the following definition: @@ -27,9 +27,9 @@ pete = Person.fromBinary(bytes); pete = Person.fromJsonString('{"name": "pete", "id": 123}'); ``` -To learn more, have a look at a complete [code example](packages/example), the documentation -for the [generated code](docs/generated_code.md), and the documentation for the -[runtime API](docs/runtime_api.md). +To learn more, have a look at a complete [code example](https://github.com/bufbuild/protobuf-es/packages/example), +the documentation for the [generated code](https://github.com/bufbuild/protobuf-es/docs/generated_code.md), +and the documentation for the [runtime API](https://github.com/bufbuild/protobuf-es/docs/runtime_api.md). ### How does this compare to protoc's JavaScript generator? @@ -48,7 +48,7 @@ Because of this, we want to provide a solid, modern alternative with Protobuf-ES The main differences of the generated code: - we use plain properties for fields, where protoc uses getter and setter methods - we implement the canonical JSON format -- we generate [much smaller bundles](packages/bench-codesize) +- we generate [much smaller bundles](packages/protobuf-bench) - we rely on standard APIs instead of the [Closure Library](http://googlecode.blogspot.com/2009/11/introducing-closure-tools.html) See the [migration guides](docs/migrating.md) for details. @@ -59,9 +59,25 @@ See the [migration guides](docs/migrating.md) for details. We implement all proto3 features, including the canonical JSON format. We implement all proto2 features, except for extensions and the text format. The implementation is covered by the protocol buffers -[conformance tests](packages/conformance-test). +[conformance tests](packages/protobuf-conformance). +### Packages + +#### @bufbuild/protoc-gen-es +This package provides the code generator plugin `protoc-gen-es`. The code it +generates depends on `@bufbuild/protobuf`. +[Source](packages/protoc-gen-es) | [npmjs.com](https://www.npmjs.com/package/@bufbuild/protoc-gen-es) + +#### @bufbuild/protobuf +This package provides the runtime library for the code generator plugin +[`protoc-gen-es`](https://github.com/bufbuild/packages/protoc-gen-es). +[Source](packages/protobuf) | [npmjs.com](https://www.npmjs.com/package/@bufbuild/protobuf) + +#### @bufbuild/protoplugin +This package helps to create your own code generator plugin. +[Source](packages/protoplugin) | [npmjs.com](https://www.npmjs.com/package/@bufbuild/protoplugin) + ### Copyright diff --git a/cmd/protoc-gen-es/internal/gencommon/gencommon.go b/cmd/protoc-gen-es/internal/gencommon/gencommon.go deleted file mode 100644 index 1141bd190..000000000 --- a/cmd/protoc-gen-es/internal/gencommon/gencommon.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gencommon - -import ( - "fmt" - "strings" - - "github.com/bufbuild/protobuf-es/private/protoplugin" - "google.golang.org/protobuf/types/descriptorpb" -) - -// GetFieldTyping returns an expression for the TypeScript typing of a field, -// and whether the property should be optional. -func GetFieldTyping(field *protoplugin.Field) (expr []interface{}, optional bool) { - switch field.Kind { - case protoplugin.FieldKindScalar: - expr = append(expr, ScalarTypeScriptType(field.Scalar)) - optional = field.Optional - - case protoplugin.FieldKindMessage: - if unwrapped, ok := GetUnwrappedFieldType(field); ok { - expr = append(expr, ScalarTypeScriptType(unwrapped)) - } else { - expr = append(expr, field.Message.Symbol.ToTypeOnly()) - } - optional = true - - case protoplugin.FieldKindEnum: - expr = append(expr, field.Enum.Symbol.ToTypeOnly()) - optional = field.Optional - - case protoplugin.FieldKindMap: - var keyType string - switch field.Map.Key { - case - descriptorpb.FieldDescriptorProto_TYPE_INT32, - descriptorpb.FieldDescriptorProto_TYPE_FIXED32, - descriptorpb.FieldDescriptorProto_TYPE_UINT32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED32, - descriptorpb.FieldDescriptorProto_TYPE_SINT32: - keyType = "number" - default: - keyType = "string" - } - var valueType interface{} - switch field.Map.ValueKind { - case protoplugin.FieldKindScalar: - valueType = ScalarTypeScriptType(field.Map.ValueScalar) - case protoplugin.FieldKindMessage: - valueType = field.Map.ValueMessage.Symbol.ToTypeOnly() - case protoplugin.FieldKindEnum: - valueType = field.Map.ValueEnum.Symbol.ToTypeOnly() - } - expr = append(expr, "{ [key: ", keyType, "]: ", valueType, " }") - optional = false - } - - if field.Repeated { - expr = append(expr, "[]") - optional = false - } - - return expr, optional -} - -// GetFieldExplicitDefaultValue returns an expression for the default value -// specified via `[ default = 123 ]`, and a bool that indicates whether the -// TypeScript type of the value can be trivially inferred from the value. -// If the field has no explicit default value, the expression is nil. -func GetFieldExplicitDefaultValue(field *protoplugin.Field) (expr []interface{}, typingInferrable bool) { - rt := field.Parent.File.RuntimeSymbols - if field.Parent.File.Syntax != protoplugin.ProtoSyntax2 { - return nil, false - } - value := field.Proto.GetDefaultValue() - if value == "" { - return nil, true - } - switch field.Kind { - case protoplugin.FieldKindEnum: - enumValue := field.Enum.FindValueByName(field.Proto.GetDefaultValue()) - expr = append(expr, field.Enum.Symbol, ".", enumValue.LocalName) - return expr, true - case protoplugin.FieldKindScalar: - switch field.Scalar { - case descriptorpb.FieldDescriptorProto_TYPE_STRING: - expr = append(expr, `"`+strings.ReplaceAll(value, `"`, `\"`)+`"`) - case descriptorpb.FieldDescriptorProto_TYPE_BYTES: - bytes, err := UnescapeBytesDefaultValue(value) - if err != nil { - return nil, false - } - expr = append(expr, "new Uint8Array([") - for _, b := range bytes { - expr = append(expr, fmt.Sprintf("0x%02X, ", b)) - } - expr = append(expr, "])") - case - descriptorpb.FieldDescriptorProto_TYPE_INT64, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64, - descriptorpb.FieldDescriptorProto_TYPE_SINT64: - str := `"` + strings.ReplaceAll(value, `"`, `\"`) + `"` - expr = append(expr, rt.ProtoInt64, ".parse(", str, ")") - case descriptorpb.FieldDescriptorProto_TYPE_UINT64, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64: - str := `"` + strings.ReplaceAll(value, `"`, `\"`) + `"` - expr = append(expr, rt.ProtoInt64, ".uParse(", str, ")") - case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE, - descriptorpb.FieldDescriptorProto_TYPE_FLOAT: - switch value { - case "inf": - expr = append(expr, "globalThis.Number.POSITIVE_INFINITY") - case "-inf": - expr = append(expr, "globalThis.Number.NEGATIVE_INFINITY") - case "nan": - expr = append(expr, "globalThis.Number.NaN") - default: - expr = append(expr, value) - } - case descriptorpb.FieldDescriptorProto_TYPE_INT32, - descriptorpb.FieldDescriptorProto_TYPE_UINT32, - descriptorpb.FieldDescriptorProto_TYPE_SINT32, - descriptorpb.FieldDescriptorProto_TYPE_FIXED32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: - expr = append(expr, value) - case descriptorpb.FieldDescriptorProto_TYPE_BOOL: - switch value { - case "true", "false": - expr = append(expr, value) - } - } - return expr, true - } - return nil, false -} - -// GetFieldIntrinsicDefaultValue returns an expression for the intrinsic -// default value for a field, and a bool that indicates whether the -// TypeScript type of the value can be trivially inferred from the value. -// If the field has no intrinsic default value, the expression is nil. -func GetFieldIntrinsicDefaultValue(field *protoplugin.Field) (expr []interface{}, typingInferrable bool) { - rt := field.Parent.File.RuntimeSymbols - if field.Repeated { - expr = append(expr, "[]") - return expr, false - } - if field.Kind == protoplugin.FieldKindMap { - expr = append(expr, "{}") - return expr, false - } - if field.Parent.File.Syntax != protoplugin.ProtoSyntax3 { - return nil, false - } - switch field.Kind { - case protoplugin.FieldKindEnum: - if !field.Optional { - enumValue := field.Enum.FindValueByNumber(0) - expr = append(expr, field.Enum.Symbol, ".", enumValue.LocalName) - return expr, true - } - case protoplugin.FieldKindScalar: - if !field.Optional { - switch field.Scalar { - case descriptorpb.FieldDescriptorProto_TYPE_STRING: - expr = append(expr, `""`) - case descriptorpb.FieldDescriptorProto_TYPE_BOOL: - expr = append(expr, false) - case - descriptorpb.FieldDescriptorProto_TYPE_UINT64, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64, - descriptorpb.FieldDescriptorProto_TYPE_SINT64, - descriptorpb.FieldDescriptorProto_TYPE_INT64: - expr = append(expr, rt.ProtoInt64, ".zero") - case descriptorpb.FieldDescriptorProto_TYPE_BYTES: - expr = append(expr, "new Uint8Array(0)") - default: - expr = append(expr, "0") - } - return expr, true - } - } - return nil, false -} diff --git a/cmd/protoc-gen-es/internal/gencommon/textformat.go b/cmd/protoc-gen-es/internal/gencommon/textformat.go deleted file mode 100644 index ee07bfc94..000000000 --- a/cmd/protoc-gen-es/internal/gencommon/textformat.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gencommon - -import ( - "bytes" - "errors" - "strconv" - "unicode/utf8" -) - -var errUnescape = errors.New("cannot unescape") - -// UnescapeBytesDefaultValue parses a text-encoded default value (proto2) of a -// BYTES field. -func UnescapeBytesDefaultValue(str string) ([]byte, error) { - p := newInput(str) - var b bytes.Buffer - for p.next() { - switch p.r { - case '\\': - if p.next() { - switch p.r { - case '\\': - b.WriteRune(p.r) - case 'b': - b.WriteRune('\b') - case 'f': - b.WriteRune('\f') - case 'n': - b.WriteRune('\n') - case 'r': - b.WriteRune('\r') - case 't': - b.WriteRune('\t') - case 'v': - b.WriteRune('\v') - case '0', '1', '2', '3', '4', '5', '6', '7': - s := string(p.r) - t, ok := p.take(2) - if !ok { - return nil, errUnescape - } - s = s + t - i, err := strconv.ParseUint(s, 8, 8) - if err != nil { - return nil, errors.New("cannot parse " + s) - } - b.WriteByte(byte(i)) - case 'x': - p.next() - s, ok := p.take(2) - if !ok { - return nil, errUnescape - } - i, err := strconv.ParseUint(s, 16, 64) - if err != nil { - return nil, errUnescape - } - b.WriteByte(byte(i)) - case 'u': - p.next() - s, ok := p.take(4) - if !ok { - return nil, errUnescape - } - i, err := strconv.ParseUint(s, 16, 64) - if err != nil { - return nil, errUnescape - } - b.WriteRune(rune(i)) - case 'U': - p.next() - s, ok := p.take(8) - if !ok { - return nil, errUnescape - } - i, err := strconv.ParseUint(s, 16, 64) - if err != nil { - return nil, errUnescape - } - b.WriteRune(rune(i)) - } - } - default: - b.WriteRune(p.r) - } - } - return b.Bytes(), nil -} - -type input struct { - tail string - r rune -} - -func newInput(str string) *input { - return &input{ - tail: str, - } -} - -func (p *input) next() bool { - if len(p.tail) == 0 { - return false - } - var l int - p.r, l = utf8.DecodeRuneInString(p.tail) - if p.r == utf8.RuneError { - return false - } - p.tail = p.tail[l:] - return true -} - -func (p *input) take(n int) (string, bool) { - b := make([]rune, 0, n) - for len(b) < n { - if !p.next() { - return "", false - } - b = append(b, p.r) - } - return string(b), true -} diff --git a/cmd/protoc-gen-es/internal/gencommon/typescript.go b/cmd/protoc-gen-es/internal/gencommon/typescript.go deleted file mode 100644 index 398a9be4b..000000000 --- a/cmd/protoc-gen-es/internal/gencommon/typescript.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gencommon - -import "google.golang.org/protobuf/types/descriptorpb" - -func ScalarTypeScriptType(scalarType descriptorpb.FieldDescriptorProto_Type) string { - switch scalarType { - case descriptorpb.FieldDescriptorProto_TYPE_STRING: - return "string" - case descriptorpb.FieldDescriptorProto_TYPE_BOOL: - return "boolean" - case - descriptorpb.FieldDescriptorProto_TYPE_UINT64, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64, - descriptorpb.FieldDescriptorProto_TYPE_SINT64, - descriptorpb.FieldDescriptorProto_TYPE_INT64: - return "bigint" - case descriptorpb.FieldDescriptorProto_TYPE_BYTES: - return "Uint8Array" - default: - return "number" - } -} diff --git a/cmd/protoc-gen-es/internal/gencommon/wkt.go b/cmd/protoc-gen-es/internal/gencommon/wkt.go deleted file mode 100644 index 909a27090..000000000 --- a/cmd/protoc-gen-es/internal/gencommon/wkt.go +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gencommon - -import ( - "github.com/bufbuild/protobuf-es/private/protoplugin" - "google.golang.org/protobuf/types/descriptorpb" -) - -var wrapperToBaseType = map[string]descriptorpb.FieldDescriptorProto_Type{ - "google.protobuf.DoubleValue": descriptorpb.FieldDescriptorProto_TYPE_DOUBLE, - "google.protobuf.FloatValue": descriptorpb.FieldDescriptorProto_TYPE_FLOAT, - "google.protobuf.Int64Value": descriptorpb.FieldDescriptorProto_TYPE_INT64, - "google.protobuf.UInt64Value": descriptorpb.FieldDescriptorProto_TYPE_UINT64, - "google.protobuf.Int32Value": descriptorpb.FieldDescriptorProto_TYPE_INT32, - "google.protobuf.UInt32Value": descriptorpb.FieldDescriptorProto_TYPE_UINT32, - "google.protobuf.BoolValue": descriptorpb.FieldDescriptorProto_TYPE_BOOL, - "google.protobuf.StringValue": descriptorpb.FieldDescriptorProto_TYPE_STRING, - "google.protobuf.BytesValue": descriptorpb.FieldDescriptorProto_TYPE_BYTES, -} - -func GetUnwrappedFieldType(field *protoplugin.Field) (scalarType descriptorpb.FieldDescriptorProto_Type, ok bool) { - if field.Kind != protoplugin.FieldKindMessage { - return 0, false - } - if field.Repeated { - return 0, false - } - if field.Oneof != nil { - return 0, false - } - scalarType, ok = wrapperToBaseType[field.Message.TypeName] - return scalarType, ok -} - -type wktAny struct { - TypeURL *protoplugin.Field - Value *protoplugin.Field -} - -func MatchWktAny(message *protoplugin.Message) (bool, *wktAny) { - if message.TypeName != "google.protobuf.Any" { - return false, nil - } - ok := true - r := &wktAny{ - TypeURL: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_STRING), - Value: findField(&ok, message, 2, descriptorpb.FieldDescriptorProto_TYPE_BYTES), - } - return ok, r -} - -type wktTimestamp struct { - Seconds *protoplugin.Field - Nanos *protoplugin.Field -} - -func MatchWktTimestamp(message *protoplugin.Message) (bool, *wktTimestamp) { - if message.TypeName != "google.protobuf.Timestamp" { - return false, nil - } - ok := true - r := &wktTimestamp{ - Seconds: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_INT64), - Nanos: findField(&ok, message, 2, descriptorpb.FieldDescriptorProto_TYPE_INT32), - } - return ok, r -} - -type wktDuration struct { - Seconds *protoplugin.Field - Nanos *protoplugin.Field -} - -func MatchWktDuration(message *protoplugin.Message) (bool, *wktDuration) { - if message.TypeName != "google.protobuf.Duration" { - return false, nil - } - ok := true - r := &wktDuration{ - Seconds: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_INT64), - Nanos: findField(&ok, message, 2, descriptorpb.FieldDescriptorProto_TYPE_INT32), - } - return ok, r -} - -type wktStruct struct { - Fields *protoplugin.Field -} - -func MatchWktStruct(message *protoplugin.Message) (bool, *wktStruct) { - if message.TypeName != "google.protobuf.Struct" { - return false, nil - } - ok := true - r := &wktStruct{ - Fields: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, func(field *protoplugin.Field) bool { - if field.Kind != protoplugin.FieldKindMap { - return false - } - if field.Map.ValueKind != protoplugin.FieldKindMessage { - return false - } - return field.Map.ValueMessage.TypeName == "google.protobuf.Value" - }), - } - return ok, r -} - -type wktValue struct { - Kind *protoplugin.Oneof - NullValue *protoplugin.Field - NumberValue *protoplugin.Field - StringValue *protoplugin.Field - BoolValue *protoplugin.Field - StructValue *protoplugin.Field - ListValue *protoplugin.Field -} - -func MatchWktValue(message *protoplugin.Message) (bool, *wktValue) { - if message.TypeName != "google.protobuf.Value" { - return false, nil - } - ok := true - kind := findOneof(&ok, message, "kind") - r := &wktValue{ - Kind: kind, - NullValue: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_ENUM, func(field *protoplugin.Field) bool { - return field.Oneof == kind - }), - NumberValue: findField(&ok, message, 2, descriptorpb.FieldDescriptorProto_TYPE_DOUBLE, func(field *protoplugin.Field) bool { - return field.Oneof == kind - }), - StringValue: findField(&ok, message, 3, descriptorpb.FieldDescriptorProto_TYPE_STRING, func(field *protoplugin.Field) bool { - return field.Oneof == kind - }), - BoolValue: findField(&ok, message, 4, descriptorpb.FieldDescriptorProto_TYPE_BOOL, func(field *protoplugin.Field) bool { - return field.Oneof == kind - }), - StructValue: findField(&ok, message, 5, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, func(field *protoplugin.Field) bool { - return field.Oneof == kind && field.Message.TypeName == "google.protobuf.Struct" - }), - ListValue: findField(&ok, message, 6, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, func(field *protoplugin.Field) bool { - return field.Message.TypeName == "google.protobuf.ListValue" - }), - } - return ok, r -} - -type wktListValue struct { - Values *protoplugin.Field -} - -func MatchWktListValue(message *protoplugin.Message) (bool, *wktListValue) { - if message.TypeName != "google.protobuf.ListValue" { - return false, nil - } - ok := true - r := &wktListValue{ - Values: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, func(field *protoplugin.Field) bool { - return field.Repeated && field.Kind == protoplugin.FieldKindMessage && field.Message.TypeName == "google.protobuf.Value" - }), - } - return ok, r -} - -type wktFieldMask struct { - Paths *protoplugin.Field -} - -func MatchWktFieldMask(message *protoplugin.Message) (bool, *wktFieldMask) { - if message.TypeName != "google.protobuf.FieldMask" { - return false, nil - } - ok := true - r := &wktFieldMask{ - Paths: findField(&ok, message, 1, descriptorpb.FieldDescriptorProto_TYPE_STRING, func(field *protoplugin.Field) bool { - return field.Repeated - }), - } - return ok, r -} - -type wktWrapper struct { - Value *protoplugin.Field -} - -func MatchWktWrapper(message *protoplugin.Message) (bool, *wktWrapper) { - baseType, ok := wrapperToBaseType[message.TypeName] - if !ok { - return false, nil - } - ok = true - r := &wktWrapper{ - Value: findField(&ok, message, 1, baseType, func(field *protoplugin.Field) bool { - return !field.Repeated - }), - } - return ok, r -} - -func findOneof(ok *bool, message *protoplugin.Message, wantName string) *protoplugin.Oneof { - if *ok { - for _, oneof := range message.Oneofs { - if oneof.Proto.GetName() != wantName { - continue - } - return oneof - } - } - *ok = false - return nil -} - -func findField(ok *bool, message *protoplugin.Message, wantNumber int32, wantType descriptorpb.FieldDescriptorProto_Type, predicate ...func(*protoplugin.Field) bool) *protoplugin.Field { - if *ok { - for _, f := range message.Fields { - if f.Proto.GetNumber() != wantNumber { - continue - } - if f.Proto.GetType() != wantType { - continue - } - for _, p := range predicate { - if !p(f) { - continue - } - } - return f - } - } - *ok = false - return nil -} diff --git a/cmd/protoc-gen-es/internal/gendts/gendts.go b/cmd/protoc-gen-es/internal/gendts/gendts.go deleted file mode 100644 index 3a01ac398..000000000 --- a/cmd/protoc-gen-es/internal/gendts/gendts.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gendts - -import ( - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/gencommon" - "github.com/bufbuild/protobuf-es/private/protoplugin" -) - -func GenerateFile(gen *protoplugin.Generator, file *protoplugin.File) { - f := gen.NewGeneratedFile(file.Name + "_pb.d.ts") - f.ImportPath = file.StandardImportPath - f.H(file.Preamble) - for _, enum := range file.Enums { - generateEnum(f, enum) - } - for _, message := range file.Messages { - generateMessage(f, message) - } - // We do not generate anything for services, and we do not support extensions at this time -} - -func generateEnum(f *protoplugin.GeneratedFile, enum *protoplugin.Enum) { - f.P(enum.JSDoc("")) - f.P("export declare enum ", enum.Symbol, " {") - for index, value := range enum.Values { - if index > 0 { - f.P() - } - f.P(value.JSDoc(" ")) - f.P(" ", value.LocalName, " = ", value.Proto.GetNumber(), ",") - } - f.P("}") - f.P() -} - -func generateMessage(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - f.P(message.JSDoc("")) - f.P("export declare class ", message.Symbol, " extends ", rt.Message, "<", message.Symbol, "> {") - for _, member := range message.Members { - switch member.Kind { - case protoplugin.MemberKindOneof: - generateOneof(f, member.Oneof) - case protoplugin.MemberKindField: - generateField(f, member.Field) - } - f.P() - } - f.P(" constructor(data?: ", rt.PartialMessage, "<", message.Symbol, ">);") - f.P() - generateWktMethods(f, message) - f.P(" static readonly runtime: typeof ", rt.ProtoN, ";") - f.P(" static readonly typeName = \"", message.TypeName, "\";") - f.P(" static readonly fields: ", rt.FieldList, ";") - // In case we start supporting options, we have to surface them here - //f.P(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};") - f.P() - generateWktStaticMethods(f, message) - f.P(" static fromBinary(bytes: Uint8Array, options?: Partial<", rt.BinaryReadOptions, ">): ", message.Symbol, ";") - f.P() - f.P(" static fromJson(jsonValue: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): ", message.Symbol, ";") - f.P() - f.P(" static fromJsonString(jsonString: string, options?: Partial<", rt.JsonReadOptions, ">): ", message.Symbol, ";") - f.P() - f.P(" static equals(a: ", message.Symbol, " | ", rt.PlainMessage, "<", message.Symbol, "> | undefined, b: ", message.Symbol, " | ", rt.PlainMessage, "<", message.Symbol, "> | undefined): boolean;") - f.P("}") - f.P() - for _, nestedEnum := range message.NestedEnums { - generateEnum(f, nestedEnum) - } - for _, nestedMessage := range message.NestedMessages { - generateMessage(f, nestedMessage) - } - // We do not support extensions at this time -} - -func generateOneof(f *protoplugin.GeneratedFile, oneof *protoplugin.Oneof) { - f.P(oneof.JSDoc(" ")) - f.P(" ", oneof.LocalName, ": {") - for i, field := range oneof.Fields { - if i > 0 { - f.P(` } | {`) - } - f.P(field.JSDoc(" ")) - t, _ := gencommon.GetFieldTyping(field) - f.P(` value: `, t, `;`) - f.P(` case: "`, field.LocalName, `";`) - } - f.P(` } | { case: undefined; value?: undefined };`) -} - -func generateField(f *protoplugin.GeneratedFile, field *protoplugin.Field) { - f.P(field.JSDoc(" ")) - var expr []interface{} - expr = append(expr, " ", field.LocalName) - typing, optional := gencommon.GetFieldTyping(field) - if optional { - expr = append(expr, "?: ", typing) - } else { - expr = append(expr, ": ", typing) - } - expr = append(expr, ";") - f.P(expr...) -} - -func generateWktMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - if ok, _ := gencommon.MatchWktAny(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, ";") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - f.P(" packFrom(message: Message): void;") - f.P() - f.P(" unpackTo(target: Message): boolean;") - f.P() - f.P(" is(type: ", rt.MessageType, "): boolean;") - f.P() - f.P(" private typeNameToUrl(name: string): string;") - f.P() - f.P(" private typeUrlToName(url: string): string;") - f.P() - } - if ok, _ := gencommon.MatchWktDuration(message); ok { - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): JsonValue;") - f.P() - } - if ok, _ := gencommon.MatchWktFieldMask(message); ok { - f.P(` toJson(options?: Partial<`, rt.JsonWriteOptions, `>): `, rt.JsonValue, `;`) - f.P() - f.P(` override fromJson(json: `, rt.JsonValue, `, options?: Partial<`, rt.JsonReadOptions, `>): this;`) - f.P() - } - if ok, _ := gencommon.MatchWktStruct(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, ";") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - } - if ok, _ := gencommon.MatchWktValue(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, ";") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - } - if ok, _ := gencommon.MatchWktListValue(message); ok { - f.P(` override toJson(options?: Partial<`, rt.JsonWriteOptions, `>): `, rt.JsonValue, `;`) - f.P() - f.P(` override fromJson(json: `, rt.JsonValue, `, options?: Partial<`, rt.JsonReadOptions, `>): this;`) - f.P() - } - if ok, _ := gencommon.MatchWktTimestamp(message); ok { - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): JsonValue;") - f.P() - f.P(" toDate(): Date;") - f.P() - } - if ok, _ := gencommon.MatchWktWrapper(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, ";") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this;") - f.P() - } -} - -func generateWktStaticMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - if ok, _ := gencommon.MatchWktAny(message); ok { - f.P(" static pack(message: Message): ", message.Symbol, ";") - f.P() - } - if ok, _ := gencommon.MatchWktTimestamp(message); ok { - f.P(" static now(): ", message.Symbol, ";") - f.P() - f.P(" static fromDate(date: Date): ", message.Symbol, ";") - f.P() - } - if ok, ref := gencommon.MatchWktWrapper(message); ok { - t := gencommon.ScalarTypeScriptType(ref.Value.Scalar) - f.P(" static readonly fieldWrapper: {") - f.P(" wrapField(value: ", t, " | ", message.Symbol, "): ", message.Symbol, ",") - f.P(" unwrapField(value: ", message.Symbol, "): ", t, ",") - f.P(" };") - f.P() - } -} diff --git a/cmd/protoc-gen-es/internal/genjs/genjs.go b/cmd/protoc-gen-es/internal/genjs/genjs.go deleted file mode 100644 index 8fcda7b58..000000000 --- a/cmd/protoc-gen-es/internal/genjs/genjs.go +++ /dev/null @@ -1,522 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package genjs - -import ( - "strings" - - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/gencommon" - "github.com/bufbuild/protobuf-es/private/protoplugin" -) - -func GenerateFile(gen *protoplugin.Generator, file *protoplugin.File) { - f := gen.NewGeneratedFile(file.Name + "_pb.js") - f.ImportPath = file.StandardImportPath - f.H(file.Preamble) - for _, enum := range file.Enums { - generateEnum(f, enum) - } - for _, message := range file.Messages { - generateMessage(f, message) - } - // We do not generate anything for services, and we do not support extensions at this time -} - -func generateEnum(f *protoplugin.GeneratedFile, enum *protoplugin.Enum) { - rt := enum.File.RuntimeSymbols - f.P(enum.JSDoc("")) - f.P("export const ", enum.Symbol, " = ", rt.ProtoN, ".makeEnum(") - f.P(` "`, enum.TypeName, `",`) - f.P(` [`) - for _, value := range enum.Values { - f.P(" {no: ", value.Proto.GetNumber(), ", name: \"", value.Proto.GetName(), "\"},") - } - f.P(` ],`) - if enum.SharedPrefix != "" { - f.P(` {sharedPrefix: "`, enum.SharedPrefix, `"},`) - } - f.P(");") - f.P() -} - -func generateMessage(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - needsLocalName := message.Proto.GetName() != message.Symbol.Name // if localName is not inferrable, we need to provide it - f.P(message.JSDoc("")) - f.P("export const ", message.Symbol, " = ", rt.ProtoN, ".makeMessageType(") - f.P(` "`, message.TypeName, `",`) - if len(message.Fields) == 0 { - f.P(" [],") - } else { - f.P(" () => [") - for _, field := range message.Fields { - generateFieldInfo(f, field) - } - f.P(" ],") - } - if needsLocalName { - f.P(` {localName: "`, message.Symbol, `"},`) - } - f.P(");") - f.P() - generateWktMethods(f, message) - generateWktStaticMethods(f, message) - for _, nestedEnum := range message.NestedEnums { - generateEnum(f, nestedEnum) - } - for _, nestedMessage := range message.NestedMessages { - generateMessage(f, nestedMessage) - } - // We do not support extensions at this time -} - -func generateFieldInfo(f *protoplugin.GeneratedFile, field *protoplugin.Field) { - rt := field.Parent.File.RuntimeSymbols - - e := make([]interface{}, 0) - e = append(e, " { no: ", field.Proto.GetNumber(), `, name: "`, field.Proto.GetName(), `", `) - - if field.JSONName != "" { - e = append(e, `jsonName: "`, field.JSONName, `", `) - } - - switch field.Kind { - case protoplugin.FieldKindScalar: - t := strings.TrimPrefix(field.Scalar.String(), "TYPE_") - e = append(e, `kind: "scalar", T: `, int32(field.Scalar), ` /* ScalarType.`, t, ` */, `) - - case protoplugin.FieldKindMap: - t := strings.TrimPrefix(field.Map.Key.String(), "TYPE_") - e = append(e, `kind: "map", K: `, int32(field.Map.Key), ` /* ScalarType.`, t, ` */, `) - switch field.Map.ValueKind { - case protoplugin.FieldKindScalar: - t := strings.TrimPrefix(field.Map.ValueScalar.String(), "TYPE_") - e = append(e, `V: {kind: "scalar", T: `, int32(field.Map.ValueScalar), ` /* ScalarType.`, t, ` */}, `) - case protoplugin.FieldKindMessage: - e = append(e, `V: {kind: "message", T: `, field.Map.ValueMessage.Symbol, `}, `) - case protoplugin.FieldKindEnum: - e = append(e, `V: {kind: "enum", T: `, rt.ProtoN, `.getEnumType(`, field.Map.ValueEnum.Symbol, `)}, `) - } - - case protoplugin.FieldKindMessage: - e = append(e, `kind: "message", T: `, field.Message.Symbol, `, `) - - case protoplugin.FieldKindEnum: - e = append(e, `kind: "enum", T: `, rt.ProtoN, `.getEnumType(`, field.Enum.Symbol, `), `) - } - - if field.Repeated { - e = append(e, `repeated: true, `) - if field.Packed != field.PackedByDefault { - e = append(e, `packed: `, field.Packed, `, `) - } - } - - if field.Optional { - e = append(e, `opt: true, `) - } - - if expr, _ := gencommon.GetFieldExplicitDefaultValue(field); expr != nil { - e = append(e, `default: `, expr, `, `) - } - - if field.Oneof != nil { - e = append(e, `oneof: "`, field.Oneof.Proto.GetName(), `", `) - } - - if l, ok := e[len(e)-1].(string); ok && strings.HasSuffix(l, ", ") { - e = append(e[:len(e)-1], strings.TrimSuffix(l, ", ")) // remove trailing ", " - } - e = append(e, " },") - f.P(e...) -} - -func generateWktMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - if ok, ref := gencommon.MatchWktAny(message); ok { - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(` if (this.`, ref.TypeURL.LocalName, ` === "") {`) - f.P(" return {};") - f.P(" }") - f.P(" const typeName = this.typeUrlToName(this.", ref.TypeURL.LocalName, ");") - f.P(" const messageType = options?.typeRegistry?.findMessage(typeName);") - f.P(" if (!messageType) {") - f.P(" throw new Error(`cannot encode message ", message.TypeName, " to JSON: \"${this.", ref.TypeURL.LocalName, "}\" is not in the type registry`);") - f.P(" }") - f.P(" const message = messageType.fromBinary(this.", ref.Value.LocalName, ");") - f.P(" let json = message.toJson(options);") - f.P(` if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) {`) - f.P(" json = {value: json};") - f.P(" }") - f.P(` json["@type"] = this.`, ref.TypeURL.LocalName, `;`) - f.P(" return json;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (json === null || Array.isArray(json) || typeof json != "object") {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: expected object but got ${json === null ? \"null\" : Array.isArray(json) ? \"array\" : typeof json}`);") - f.P(" }") - f.P(` const typeUrl = json["@type"];`) - f.P(` if (typeof typeUrl != "string" || typeUrl == "") {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: \"@type\" is empty`);") - f.P(" }") - f.P(" const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName);") - f.P(" if (!messageType) {") - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: ${typeUrl} is not in the type registry`);") - f.P(" }") - f.P(" let message;") - f.P(` if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) {`) - f.P(` message = messageType.fromJson(json["value"], options);`) - f.P(" } else {") - f.P(" const copy = Object.assign({}, json);") - f.P(` delete copy["@type"];`) - f.P(" message = messageType.fromJson(copy, options);") - f.P(" }") - f.P(" this.packFrom(message);") - f.P(" return this;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.packFrom = function packFrom(message) {") - f.P(" this.", ref.Value.LocalName, " = message.toBinary();") - f.P(" this.", ref.TypeURL.LocalName, " = this.typeNameToUrl(message.getType().typeName);") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.unpackTo = function unpackTo(target) {") - f.P(" unpackTo(target) {") - f.P(" if (!this.is(target.getType())) {") - f.P(" return false;") - f.P(" }") - f.P(" target.fromBinary(this.", ref.Value.LocalName, ");") - f.P(" return true;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.is = function is(type) {") - f.P(" is(type) {") - f.P(" return this.", ref.TypeURL.LocalName, " === this.typeNameToUrl(type.typeName);") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.typeNameToUrl = function typeNameToUrl(name) {") - f.P(" return `type.googleapis.com/${name}`;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.typeUrlToName = function typeUrlToName(url) {") - f.P(" if (!url.length) {") - f.P(" throw new Error(`invalid type url: ${url}`);") - f.P(" }") - f.P(` const slash = url.lastIndexOf("/");`) - f.P(" const name = slash > 0 ? url.substring(slash + 1) : url;") - f.P(" if (!name.length) {") - f.P(" throw new Error(`invalid type url: ${url}`);") - f.P(" }") - f.P(" return name;") - f.P(" };") - f.P() - } - if ok, ref := gencommon.MatchWktDuration(message); ok { - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (typeof json !== "string") {`) - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${proto3.json.debug(json)}`);") - f.P(" }") - f.P(` const match = json.match(/^(-?[0-9]+)(?:\.([0-9]+))?s/);`) - f.P(" if (match === null) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(" const longSeconds = Number(match[1]);") - f.P(" if (longSeconds > 315576000000 || longSeconds < -315576000000) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(" this.", ref.Seconds.LocalName, " = ", rt.ProtoInt64, ".parse(longSeconds);") - f.P(` if (typeof match[2] == "string") {`) - f.P(` const nanosStr = match[2] + "0".repeat(9 - match[2].length);`) - f.P(" this.", ref.Nanos.LocalName, " = parseInt(nanosStr);") - f.P(" if (longSeconds < ", rt.ProtoInt64, ".zero) {") - f.P(" this.", ref.Nanos.LocalName, " = -this.", ref.Nanos.LocalName, ";") - f.P(" }") - f.P(" }") - f.P(" return this;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(" if (Number(this.", ref.Seconds.LocalName, ") > 315576000000 || Number(this.", ref.Seconds.LocalName, ") < -315576000000) {") - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: value out of range`);") - f.P(" }") - f.P(" let text = this.", ref.Seconds.LocalName, ".toString();") - f.P(" if (this.", ref.Nanos.LocalName, " !== 0) {") - f.P(" let nanosStr = Math.abs(this.", ref.Nanos.LocalName, ").toString();") - f.P(` nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;`) - f.P(` if (nanosStr.substring(3) === "000000") {`) - f.P(" nanosStr = nanosStr.substring(0, 3);") - f.P(` } else if (nanosStr.substring(6) === "000") {`) - f.P(" nanosStr = nanosStr.substring(0, 6);") - f.P(` }`) - f.P(` text += "." + nanosStr;`) - f.P(" }") - f.P(` return text + "s";`) - f.P(" };") - f.P() - } - if ok, ref := gencommon.MatchWktFieldMask(message); ok { - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(` // Converts snake_case to protoCamelCase according to the convention`) - f.P(` // used by protoc to convert a field name to a JSON name.`) - f.P(` function protoCamelCase(snakeCase: string): string {`) - f.P(` let capNext = false;`) - f.P(` const b = [];`) - f.P(` for (let i = 0; i < snakeCase.length; i++) {`) - f.P(` let c = snakeCase.charAt(i);`) - f.P(` switch (c) {`) - f.P(` case '_':`) - f.P(` capNext = true;`) - f.P(` break;`) - f.P(` case '0':`) - f.P(` case '1':`) - f.P(` case '2':`) - f.P(` case '3':`) - f.P(` case '4':`) - f.P(` case '5':`) - f.P(` case '6':`) - f.P(` case '7':`) - f.P(` case '8':`) - f.P(` case '9':`) - f.P(` b.push(c);`) - f.P(` capNext = false;`) - f.P(` break;`) - f.P(` default:`) - f.P(` if (capNext) {`) - f.P(` capNext = false;`) - f.P(` c = c.toUpperCase();`) - f.P(` }`) - f.P(` b.push(c);`) - f.P(` break;`) - f.P(` }`) - f.P(` }`) - f.P(` return b.join('');`) - f.P(` }`) - f.P(` return this.`, ref.Paths.LocalName, `.map(p => {`) - f.P(` if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: lowerCamelCase of path name \"" + p + "\" is irreversible");`) - f.P(` }`) - f.P(` return protoCamelCase(p);`) - f.P(` }).join(",");`) - f.P(` };`) - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (typeof json !== "string") {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: " + proto3.json.debug(json));`) - f.P(` }`) - f.P(` if (json === "") {`) - f.P(` return this;`) - f.P(` }`) - f.P(` function camelToSnake (str) {`) - f.P(` if (str.includes("_")) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: path names must be lowerCamelCase");`) - f.P(` }`) - f.P(` const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase());`) - f.P(` return (sc[0] === "_") ? sc.substring(1) : sc;`) - f.P(` }`) - f.P(` this.`, ref.Paths.LocalName, ` = json.split(",").map(camelToSnake);`) - f.P(` return this;`) - f.P(` };`) - f.P() - } - if ok, ref := gencommon.MatchWktStruct(message); ok { - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(" const json = {}") - f.P(" for (const [k, v] of Object.entries(this.", ref.Fields.LocalName, ")) {") - f.P(" json[k] = v.toJson(options);") - f.P(" }") - f.P(" return json;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (typeof json != "object" || json == null || Array.isArray(json)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(" }") - f.P(" for (const [k, v] of Object.entries(json)) {") - f.P(" this.", ref.Fields.LocalName, "[k] = ", ref.Fields.Map.ValueMessage.Symbol, ".fromJson(v);") - f.P(" }") - f.P(" return this;") - f.P(" };") - f.P() - } - if ok, ref := gencommon.MatchWktValue(message); ok { - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(" switch (this.", ref.Kind.LocalName, ".case) {") - f.P(` case "`, ref.NullValue.LocalName, `":`) - f.P(" return null;") - f.P(` case "`, ref.BoolValue.LocalName, `":`) - f.P(` case "`, ref.NumberValue.LocalName, `":`) - f.P(` case "`, ref.StringValue.LocalName, `":`) - f.P(" return this.", ref.Kind.LocalName, ".value;") - f.P(` case "`, ref.StructValue.LocalName, `":`) - f.P(` case "`, ref.ListValue.LocalName, `":`) - f.P(` return this.`, ref.Kind.LocalName, `.value.toJson({...options, emitDefaultValues: true});`) - f.P(" }") - f.P(` throw new Error("`, message.TypeName, ` must have a value");`) - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(" switch (typeof json) {") - f.P(` case "number":`) - f.P(` this.kind = { case: "`, ref.NumberValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "string":`) - f.P(` this.kind = { case: "`, ref.StringValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "boolean":`) - f.P(` this.kind = { case: "`, ref.BoolValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "object":`) - f.P(" if (json === null) {") - f.P(` this.kind = { case: "`, ref.NullValue.LocalName, `", value: `, ref.NullValue.Enum.Symbol, `.`, ref.NullValue.Enum.Values[0].LocalName, ` };`) - f.P(" } else if (Array.isArray(json)) {") - f.P(` this.kind = { case: "`, ref.ListValue.LocalName, `", value: `, ref.ListValue.Message.Symbol, `.fromJson(json) };`) - f.P(" } else {") - f.P(` this.kind = { case: "`, ref.StructValue.LocalName, `", value: `, ref.StructValue.Message.Symbol, `.fromJson(json) };`) - f.P(" }") - f.P(" break;") - f.P(" default:") - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(" }") - f.P(" return this;") - f.P(" };") - f.P() - } - if ok, ref := gencommon.MatchWktListValue(message); ok { - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(` return this.`, ref.Values.LocalName, `.map(v => v.toJson());`) - f.P(` }`) - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (!Array.isArray(json)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(` }`) - f.P(` for (let e of json) {`) - f.P(` this.`, ref.Values.LocalName, `.push(`, ref.Values.Message.Symbol, `.fromJson(e));`) - f.P(` }`) - f.P(` return this;`) - f.P(` };`) - f.P() - } - if ok, ref := gencommon.MatchWktTimestamp(message); ok { - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(` if (typeof json !== "string") {`) - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(` const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);`) - f.P(" if (!matches) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: invalid RFC 3339 string`);") - f.P(" }") - f.P(` const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));`) - f.P(" if (Number.isNaN(ms)) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: invalid RFC 3339 string`);") - f.P(" }") - f.P(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);") - f.P(" }") - f.P(" this.", ref.Seconds.LocalName, " = ", rt.ProtoInt64, ".parse(ms / 1000);") - f.P(" this.", ref.Nanos.LocalName, " = 0;") - f.P(" if (matches[7]) {") - f.P(` this.`, ref.Nanos.LocalName, ` = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000);`) - f.P(" }") - f.P(" return this;") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.toJson = function toJson(options) {") - f.P(" const ms = Number(this.", ref.Seconds.LocalName, ") * 1000;") - f.P(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`) - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);") - f.P(" }") - f.P(" if (this.", ref.Nanos.LocalName, " < 0) {") - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: nanos must not be negative`);") - f.P(" }") - f.P(` let z = "Z";`) - f.P(" if (this.", ref.Nanos.LocalName, " > 0) {") - f.P(" const nanosStr = (this.", ref.Nanos.LocalName, " + 1000000000).toString().substring(1);") - f.P(` if (nanosStr.substring(3) === "000000") {`) - f.P(` z = "." + nanosStr.substring(0, 3) + "Z";`) - f.P(` } else if (nanosStr.substring(6) === "000") {`) - f.P(` z = "." + nanosStr.substring(0, 6) + "Z";`) - f.P(" } else {") - f.P(` z = "." + nanosStr + "Z";`) - f.P(" }") - f.P(" }") - f.P(` return new Date(ms).toISOString().replace(".000Z", z);`) - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.typeUrlToName = function typeUrlToName(url) {") - f.P(" toDate(): Date {") - f.P(" return new Date(Number(this.", ref.Seconds.LocalName, ") * 1000 + Math.ceil(this.", ref.Nanos.LocalName, " / 1000000));") - f.P(" };") - f.P() - } - if ok, ref := gencommon.MatchWktWrapper(message); ok { - t := strings.TrimPrefix(ref.Value.Scalar.String(), "TYPE_") - f.P(message.Symbol, ".prototype.typeUrlToName = function toJson(options) {") - f.P(" return proto3.json.writeScalar(", rt.ScalarType, ".", t, ", this.value, true);") - f.P(" };") - f.P() - f.P(message.Symbol, ".prototype.fromJson = function fromJson(json, options) {") - f.P(" try {") - f.P(" this.value = ", rt.ProtoN, ".json.readScalar(", rt.ScalarType, ".", t, ", json);") - f.P(" } catch (e) {") - f.P(" let m = `cannot decode message ", message.TypeName, " from JSON\"`;") - f.P(" if (e instanceof Error && e.message.length > 0) {") - f.P(" m += `: ${e.message}`") - f.P(" }") - f.P(" throw new Error(m);") - f.P(" }") - f.P(" return this;") - f.P(" };") - f.P() - } -} - -func generateWktStaticMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - if ok, _ := gencommon.MatchWktAny(message); ok { - f.P(message.Symbol, ".pack = function pack(message) {") - f.P(" const any = new ", message.Symbol, "();") - f.P(" any.packFrom(message);") - f.P(" return any;") - f.P("};") - f.P() - } - if ok, ref := gencommon.MatchWktTimestamp(message); ok { - f.P(message.Symbol, ".now = function now() {") - f.P(" return ", message.Symbol, ".fromDate(new Date())") - f.P("};") - f.P() - f.P(message.Symbol, ".fromDate = function fromDate(date) {") - f.P(" const ms = date.getTime();") - f.P(" return new ", message.Symbol, "({") - f.P(" ", ref.Seconds.LocalName, ": ", rt.ProtoInt64, ".parse(Math.floor(ms / 1000)),") - f.P(" ", ref.Nanos.LocalName, ": (ms % 1000) * 1000000,") - f.P(" });") - f.P("};") - f.P() - } - if ok, ref := gencommon.MatchWktWrapper(message); ok { - f.P(message.Symbol, ".fieldWrapper = {") - f.P(" wrapField(value) {") - f.P(" return value instanceof ", message.Symbol, " ? value : new ", message.Symbol, "({value});") - f.P(" },") - f.P(" unwrapField(value) {") - f.P(" return value.", ref.Value.LocalName, ";") - f.P(" }") - f.P("};") - f.P() - } -} diff --git a/cmd/protoc-gen-es/internal/gents/gents.go b/cmd/protoc-gen-es/internal/gents/gents.go deleted file mode 100644 index 8728f06cf..000000000 --- a/cmd/protoc-gen-es/internal/gents/gents.go +++ /dev/null @@ -1,587 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package gents - -import ( - "strings" - - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/gencommon" - "github.com/bufbuild/protobuf-es/private/protoplugin" -) - -func GenerateFile(gen *protoplugin.Generator, file *protoplugin.File) { - f := gen.NewGeneratedFile(file.Name + "_pb.ts") - f.ImportPath = file.StandardImportPath - f.H(file.Preamble) - for _, enum := range file.Enums { - generateEnum(f, enum) - } - for _, message := range file.Messages { - generateMessage(f, message) - } - // We do not generate anything for services, and we do not support extensions at this time -} - -func generateEnum(f *protoplugin.GeneratedFile, enum *protoplugin.Enum) { - rt := enum.File.RuntimeSymbols - f.P(enum.JSDoc("")) - f.P("export enum ", enum.Symbol, " {") - for index, value := range enum.Values { - if index > 0 { - f.P() - } - f.P(value.JSDoc(" ")) - f.P(" ", value.LocalName, " = ", value.Proto.GetNumber(), ",") - } - f.P("}") - switch enum.File.Syntax { - case protoplugin.ProtoSyntax2: - f.P("// Retrieve enum metadata with: proto2.getEnumType(", enum.Symbol, ")") - case protoplugin.ProtoSyntax3: - f.P("// Retrieve enum metadata with: proto3.getEnumType(", enum.Symbol, ")") - } - f.P(rt.ProtoN, `.util.setEnumType(`, enum.Symbol, `, "`, enum.TypeName, `", [`) - for _, value := range enum.Values { - f.P(" { no: ", value.Proto.GetNumber(), ", name: \"", value.Proto.GetName(), "\" },") - } - f.P("]);") - f.P() -} - -func generateMessage(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - f.P(message.JSDoc("")) - f.P("export class ", message.Symbol, " extends ", rt.Message, "<", message.Symbol, "> {") - for _, member := range message.Members { - switch member.Kind { - case protoplugin.MemberKindOneof: - generateOneof(f, member.Oneof) - case protoplugin.MemberKindField: - generateField(f, member.Field) - } - f.P() - } - f.P(" constructor(data?: ", rt.PartialMessage, "<", message.Symbol, ">) {") - f.P(" super();") - f.P(" ", rt.ProtoN, ".util.initPartial(data, this);") - f.P(" }") - f.P() - generateWktMethods(f, message) - f.P(" static readonly runtime = ", rt.ProtoN, ";") - f.P(" static readonly typeName = \"", message.TypeName, "\";") - f.P(" static readonly fields: ", rt.FieldList, " = ", rt.ProtoN, ".util.newFieldList(() => [") - for _, field := range message.Fields { - generateFieldInfo(f, field) - } - f.P(" ]);") - // In case we start supporting options, we have to surface them here - //f.P(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};") - f.P() - generateWktStaticMethods(f, message) - f.P(" static fromBinary(bytes: Uint8Array, options?: Partial<", rt.BinaryReadOptions, ">): ", message.Symbol, " {") - f.P(" return new ", message.Symbol, "().fromBinary(bytes, options);") - f.P(" }") - f.P() - f.P(" static fromJson(jsonValue: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): ", message.Symbol, " {") - f.P(" return new ", message.Symbol, "().fromJson(jsonValue, options);") - f.P(" }") - f.P() - f.P(" static fromJsonString(jsonString: string, options?: Partial<", rt.JsonReadOptions, ">): ", message.Symbol, " {") - f.P(" return new ", message.Symbol, "().fromJsonString(jsonString, options);") - f.P(" }") - f.P() - f.P(" static equals(a: ", message.Symbol, " | ", rt.PlainMessage, "<", message.Symbol, "> | undefined, b: ", message.Symbol, " | ", rt.PlainMessage, "<", message.Symbol, "> | undefined): boolean {") - f.P(" return ", rt.ProtoN, ".util.equals(", message.Symbol, ", a, b);") - f.P(" }") - f.P("}") - f.P() - for _, nestedEnum := range message.NestedEnums { - generateEnum(f, nestedEnum) - } - for _, nestedMessage := range message.NestedMessages { - generateMessage(f, nestedMessage) - } - // We do not support extensions at this time -} - -func generateFieldInfo(f *protoplugin.GeneratedFile, field *protoplugin.Field) { - rt := field.Parent.File.RuntimeSymbols - - e := make([]interface{}, 0) - e = append(e, " { no: ", field.Proto.GetNumber(), `, name: "`, field.Proto.GetName(), `", `) - - if field.JSONName != "" { - e = append(e, `jsonName: "`, field.JSONName, `", `) - } - - switch field.Kind { - case protoplugin.FieldKindScalar: - t := strings.TrimPrefix(field.Scalar.String(), "TYPE_") - e = append(e, `kind: "scalar", T: `, int32(field.Scalar), ` /* ScalarType.`, t, ` */, `) - - case protoplugin.FieldKindMap: - t := strings.TrimPrefix(field.Map.Key.String(), "TYPE_") - e = append(e, `kind: "map", K: `, int32(field.Map.Key), ` /* ScalarType.`, t, ` */, `) - switch field.Map.ValueKind { - case protoplugin.FieldKindScalar: - t := strings.TrimPrefix(field.Map.ValueScalar.String(), "TYPE_") - e = append(e, `V: {kind: "scalar", T: `, int32(field.Map.ValueScalar), ` /* ScalarType.`, t, ` */}, `) - case protoplugin.FieldKindMessage: - e = append(e, `V: {kind: "message", T: `, field.Map.ValueMessage.Symbol, `}, `) - case protoplugin.FieldKindEnum: - e = append(e, `V: {kind: "enum", T: `, rt.ProtoN, `.getEnumType(`, field.Map.ValueEnum.Symbol, `)}, `) - } - - case protoplugin.FieldKindMessage: - e = append(e, `kind: "message", T: `, field.Message.Symbol, `, `) - - case protoplugin.FieldKindEnum: - e = append(e, `kind: "enum", T: `, rt.ProtoN, `.getEnumType(`, field.Enum.Symbol, `), `) - } - - if field.Repeated { - e = append(e, `repeated: true, `) - if field.Packed != field.PackedByDefault { - e = append(e, `packed: `, field.Packed, `, `) - } - } - - if field.Optional { - e = append(e, `opt: true, `) - } - - if expr, _ := gencommon.GetFieldExplicitDefaultValue(field); expr != nil { - e = append(e, `default: `, expr, `, `) - } - - if field.Oneof != nil { - e = append(e, `oneof: "`, field.Oneof.Proto.GetName(), `", `) - } - - if l, ok := e[len(e)-1].(string); ok && strings.HasSuffix(l, ", ") { - e = append(e[:len(e)-1], strings.TrimSuffix(l, ", ")) // remove trailing ", " - } - e = append(e, " },") - f.P(e...) -} - -func generateOneof(f *protoplugin.GeneratedFile, oneof *protoplugin.Oneof) { - f.P(oneof.JSDoc(" ")) - f.P(" ", oneof.LocalName, ": {") - for i, field := range oneof.Fields { - if i > 0 { - f.P(` } | {`) - } - f.P(field.JSDoc(" ")) - t, _ := gencommon.GetFieldTyping(field) - f.P(` value: `, t, `;`) - f.P(` case: "`, field.LocalName, `";`) - } - f.P(` } | { case: undefined; value?: undefined } = { case: undefined };`) -} - -func generateField(f *protoplugin.GeneratedFile, field *protoplugin.Field) { - f.P(field.JSDoc(" ")) - var expr []interface{} - expr = append(expr, " ", field.LocalName) - defaultValue, typingInferrable := gencommon.GetFieldIntrinsicDefaultValue(field) - typing, optional := gencommon.GetFieldTyping(field) - if optional || defaultValue == nil { - expr = append(expr, "?: ", typing) - } else if !typingInferrable { - expr = append(expr, ": ", typing) - } - if defaultValue != nil { - expr = append(expr, " = ", defaultValue) - } - expr = append(expr, ";") - f.P(expr...) -} - -func generateWktMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - if ok, ref := gencommon.MatchWktAny(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, " {") - f.P(` if (this.`, ref.TypeURL.LocalName, ` === "") {`) - f.P(" return {};") - f.P(" }") - f.P(" const typeName = this.typeUrlToName(this.", ref.TypeURL.LocalName, ");") - f.P(" const messageType = options?.typeRegistry?.findMessage(typeName);") - f.P(" if (!messageType) {") - f.P(" throw new Error(`cannot encode message ", message.TypeName, " to JSON: \"${this.", ref.TypeURL.LocalName, "}\" is not in the type registry`);") - f.P(" }") - f.P(" const message = messageType.fromBinary(this.", ref.Value.LocalName, ");") - f.P(" let json = message.toJson(options);") - f.P(` if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) {`) - f.P(" json = {value: json};") - f.P(" }") - f.P(` json["@type"] = this.`, ref.TypeURL.LocalName, `;`) - f.P(" return json;") - f.P(" }") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(` if (json === null || Array.isArray(json) || typeof json != "object") {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: expected object but got ${json === null ? \"null\" : Array.isArray(json) ? \"array\" : typeof json}`);") - f.P(" }") - f.P(` const typeUrl = json["@type"];`) - f.P(` if (typeof typeUrl != "string" || typeUrl == "") {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: \"@type\" is empty`);") - f.P(" }") - f.P(" const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName);") - f.P(" if (!messageType) {") - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: ${typeUrl} is not in the type registry`);") - f.P(" }") - f.P(" let message;") - f.P(` if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) {`) - f.P(` message = messageType.fromJson(json["value"], options);`) - f.P(" } else {") - f.P(" const copy = Object.assign({}, json);") - f.P(` delete copy["@type"];`) - f.P(" message = messageType.fromJson(copy, options);") - f.P(" }") - f.P(" this.packFrom(message);") - f.P(" return this;") - f.P(" }") - f.P() - f.P(" packFrom(message: Message): void {") - f.P(" this.", ref.Value.LocalName, " = message.toBinary();") - f.P(" this.", ref.TypeURL.LocalName, " = this.typeNameToUrl(message.getType().typeName);") - f.P(" }") - f.P() - f.P(" unpackTo(target: Message): boolean {") - f.P(" if (!this.is(target.getType())) {") - f.P(" return false;") - f.P(" }") - f.P(" target.fromBinary(this.", ref.Value.LocalName, ");") - f.P(" return true;") - f.P(" }") - f.P() - f.P(" is(type: ", rt.MessageType, "): boolean {") - f.P(" return this.", ref.TypeURL.LocalName, " === this.typeNameToUrl(type.typeName);") - f.P(" }") - f.P() - f.P(" private typeNameToUrl(name: string): string {") - f.P(" return `type.googleapis.com/${name}`;") - f.P(" }") - f.P() - f.P(" private typeUrlToName(url: string): string {") - f.P(" if (!url.length) {") - f.P(" throw new Error(`invalid type url: ${url}`);") - f.P(" }") - f.P(` const slash = url.lastIndexOf("/");`) - f.P(" const name = slash > 0 ? url.substring(slash + 1) : url;") - f.P(" if (!name.length) {") - f.P(" throw new Error(`invalid type url: ${url}`);") - f.P(" }") - f.P(" return name;") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktDuration(message); ok { - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(` if (typeof json !== "string") {`) - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${proto3.json.debug(json)}`);") - f.P(" }") - f.P(` const match = json.match(/^(-?[0-9]+)(?:\.([0-9]+))?s/);`) - f.P(" if (match === null) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(" const longSeconds = Number(match[1]);") - f.P(" if (longSeconds > 315576000000 || longSeconds < -315576000000) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(" this.", ref.Seconds.LocalName, " = ", rt.ProtoInt64, ".parse(longSeconds);") - f.P(` if (typeof match[2] == "string") {`) - f.P(` const nanosStr = match[2] + "0".repeat(9 - match[2].length);`) - f.P(" this.", ref.Nanos.LocalName, " = parseInt(nanosStr);") - f.P(" if (longSeconds < ", rt.ProtoInt64, ".zero) {") - f.P(" this.", ref.Nanos.LocalName, " = -this.", ref.Nanos.LocalName, ";") - f.P(" }") - f.P(" }") - f.P(" return this;") - f.P(" }") - f.P() - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): JsonValue {") - f.P(" if (Number(this.", ref.Seconds.LocalName, ") > 315576000000 || Number(this.", ref.Seconds.LocalName, ") < -315576000000) {") - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: value out of range`);") - f.P(" }") - f.P(" let text = this.", ref.Seconds.LocalName, ".toString();") - f.P(" if (this.", ref.Nanos.LocalName, " !== 0) {") - f.P(" let nanosStr = Math.abs(this.", ref.Nanos.LocalName, ").toString();") - f.P(` nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;`) - f.P(` if (nanosStr.substring(3) === "000000") {`) - f.P(" nanosStr = nanosStr.substring(0, 3);") - f.P(` } else if (nanosStr.substring(6) === "000") {`) - f.P(" nanosStr = nanosStr.substring(0, 6);") - f.P(` }`) - f.P(` text += "." + nanosStr;`) - f.P(" }") - f.P(` return text + "s";`) - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktFieldMask(message); ok { - f.P(` override toJson(options?: Partial<`, rt.JsonWriteOptions, `>): `, rt.JsonValue, ` {`) - f.P(` // Converts snake_case to protoCamelCase according to the convention`) - f.P(` // used by protoc to convert a field name to a JSON name.`) - f.P(` function protoCamelCase(snakeCase: string): string {`) - f.P(` let capNext = false;`) - f.P(` const b = [];`) - f.P(` for (let i = 0; i < snakeCase.length; i++) {`) - f.P(` let c = snakeCase.charAt(i);`) - f.P(` switch (c) {`) - f.P(` case '_':`) - f.P(` capNext = true;`) - f.P(` break;`) - f.P(` case '0':`) - f.P(` case '1':`) - f.P(` case '2':`) - f.P(` case '3':`) - f.P(` case '4':`) - f.P(` case '5':`) - f.P(` case '6':`) - f.P(` case '7':`) - f.P(` case '8':`) - f.P(` case '9':`) - f.P(` b.push(c);`) - f.P(` capNext = false;`) - f.P(` break;`) - f.P(` default:`) - f.P(` if (capNext) {`) - f.P(` capNext = false;`) - f.P(` c = c.toUpperCase();`) - f.P(` }`) - f.P(` b.push(c);`) - f.P(` break;`) - f.P(` }`) - f.P(` }`) - f.P(` return b.join('');`) - f.P(` }`) - f.P(` return this.`, ref.Paths.LocalName, `.map(p => {`) - f.P(` if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: lowerCamelCase of path name \"" + p + "\" is irreversible");`) - f.P(` }`) - f.P(` return protoCamelCase(p);`) - f.P(` }).join(",");`) - f.P(` }`) - f.P() - f.P(` override fromJson(json: `, rt.JsonValue, `, options?: Partial<`, rt.JsonReadOptions, `>): this {`) - f.P(` if (typeof json !== "string") {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: " + proto3.json.debug(json));`) - f.P(` }`) - f.P(` if (json === "") {`) - f.P(` return this;`) - f.P(` }`) - f.P(` function camelToSnake (str: string) {`) - f.P(` if (str.includes("_")) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON: path names must be lowerCamelCase");`) - f.P(` }`) - f.P(` const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase());`) - f.P(` return (sc[0] === "_") ? sc.substring(1) : sc;`) - f.P(` }`) - f.P(` this.`, ref.Paths.LocalName, ` = json.split(",").map(camelToSnake);`) - f.P(` return this;`) - f.P(` }`) - f.P() - } - if ok, ref := gencommon.MatchWktStruct(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, " {") - f.P(" const json: ", rt.JsonObject, " = {}") - f.P(" for (const [k, v] of Object.entries(this.", ref.Fields.LocalName, ")) {") - f.P(" json[k] = v.toJson(options);") - f.P(" }") - f.P(" return json;") - f.P(" }") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(` if (typeof json != "object" || json == null || Array.isArray(json)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(" }") - f.P(" for (const [k, v] of Object.entries(json)) {") - f.P(" this.", ref.Fields.LocalName, "[k] = ", ref.Fields.Map.ValueMessage.Symbol, ".fromJson(v);") - f.P(" }") - f.P(" return this;") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktValue(message); ok { - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, " {") - f.P(" switch (this.", ref.Kind.LocalName, ".case) {") - f.P(` case "`, ref.NullValue.LocalName, `":`) - f.P(" return null;") - f.P(` case "`, ref.BoolValue.LocalName, `":`) - f.P(` case "`, ref.NumberValue.LocalName, `":`) - f.P(` case "`, ref.StringValue.LocalName, `":`) - f.P(" return this.", ref.Kind.LocalName, ".value;") - f.P(` case "`, ref.StructValue.LocalName, `":`) - f.P(` case "`, ref.ListValue.LocalName, `":`) - f.P(` return this.`, ref.Kind.LocalName, `.value.toJson({...options, emitDefaultValues: true});`) - f.P(" }") - f.P(` throw new Error("`, message.TypeName, ` must have a value");`) - f.P(" }") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(" switch (typeof json) {") - f.P(` case "number":`) - f.P(` this.kind = { case: "`, ref.NumberValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "string":`) - f.P(` this.kind = { case: "`, ref.StringValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "boolean":`) - f.P(` this.kind = { case: "`, ref.BoolValue.LocalName, `", value: json };`) - f.P(" break;") - f.P(` case "object":`) - f.P(" if (json === null) {") - f.P(` this.kind = { case: "`, ref.NullValue.LocalName, `", value: `, ref.NullValue.Enum.Symbol, `.`, ref.NullValue.Enum.Values[0].LocalName, ` };`) - f.P(" } else if (Array.isArray(json)) {") - f.P(` this.kind = { case: "`, ref.ListValue.LocalName, `", value: `, ref.ListValue.Message.Symbol, `.fromJson(json) };`) - f.P(" } else {") - f.P(` this.kind = { case: "`, ref.StructValue.LocalName, `", value: `, ref.StructValue.Message.Symbol, `.fromJson(json) };`) - f.P(" }") - f.P(" break;") - f.P(" default:") - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(" }") - f.P(" return this;") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktListValue(message); ok { - f.P(` override toJson(options?: Partial<`, rt.JsonWriteOptions, `>): `, rt.JsonValue, ` {`) - f.P(` return this.`, ref.Values.LocalName, `.map(v => v.toJson());`) - f.P(` }`) - f.P() - f.P(` override fromJson(json: `, rt.JsonValue, `, options?: Partial<`, rt.JsonReadOptions, `>): this {`) - f.P(` if (!Array.isArray(json)) {`) - f.P(` throw new Error("cannot decode `, message.TypeName, ` from JSON " + `, rt.ProtoN, `.json.debug(json));`) - f.P(` }`) - f.P(` for (let e of json) {`) - f.P(` this.`, ref.Values.LocalName, `.push(`, ref.Values.Message.Symbol, `.fromJson(e));`) - f.P(` }`) - f.P(` return this;`) - f.P(` }`) - f.P() - } - if ok, ref := gencommon.MatchWktTimestamp(message); ok { - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(` if (typeof json !== "string") {`) - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: ${", rt.ProtoN, ".json.debug(json)}`);") - f.P(" }") - f.P(` const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);`) - f.P(" if (!matches) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: invalid RFC 3339 string`);") - f.P(" }") - f.P(` const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));`) - f.P(" if (Number.isNaN(ms)) {") - f.P(" throw new Error(`cannot decode ", message.TypeName, " from JSON: invalid RFC 3339 string`);") - f.P(" }") - f.P(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`) - f.P(" throw new Error(`cannot decode message ", message.TypeName, " from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);") - f.P(" }") - f.P(" this.", ref.Seconds.LocalName, " = ", rt.ProtoInt64, ".parse(ms / 1000);") - f.P(" this.", ref.Nanos.LocalName, " = 0;") - f.P(" if (matches[7]) {") - f.P(` this.`, ref.Nanos.LocalName, ` = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000);`) - f.P(" }") - f.P(" return this;") - f.P(" }") - f.P() - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): JsonValue {") - f.P(" const ms = Number(this.", ref.Seconds.LocalName, ") * 1000;") - f.P(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`) - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);") - f.P(" }") - f.P(" if (this.", ref.Nanos.LocalName, " < 0) {") - f.P(" throw new Error(`cannot encode ", message.TypeName, " to JSON: nanos must not be negative`);") - f.P(" }") - f.P(` let z = "Z";`) - f.P(" if (this.", ref.Nanos.LocalName, " > 0) {") - f.P(" const nanosStr = (this.", ref.Nanos.LocalName, " + 1000000000).toString().substring(1);") - f.P(` if (nanosStr.substring(3) === "000000") {`) - f.P(` z = "." + nanosStr.substring(0, 3) + "Z";`) - f.P(` } else if (nanosStr.substring(6) === "000") {`) - f.P(` z = "." + nanosStr.substring(0, 6) + "Z";`) - f.P(" } else {") - f.P(` z = "." + nanosStr + "Z";`) - f.P(" }") - f.P(" }") - f.P(` return new Date(ms).toISOString().replace(".000Z", z);`) - f.P(" }") - f.P() - f.P(" toDate(): Date {") - f.P(" return new Date(Number(this.", ref.Seconds.LocalName, ") * 1000 + Math.ceil(this.", ref.Nanos.LocalName, " / 1000000));") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktWrapper(message); ok { - t := strings.TrimPrefix(ref.Value.Scalar.String(), "TYPE_") - f.P(" override toJson(options?: Partial<", rt.JsonWriteOptions, ">): ", rt.JsonValue, " {") - f.P(" return proto3.json.writeScalar(", rt.ScalarType, ".", t, ", this.value, true)!;") - f.P(" }") - f.P() - f.P(" override fromJson(json: ", rt.JsonValue, ", options?: Partial<", rt.JsonReadOptions, ">): this {") - f.P(" try {") - f.P(" this.value = ", rt.ProtoN, ".json.readScalar(", rt.ScalarType, ".", t, ", json);") - f.P(" } catch (e) {") - f.P(" let m = `cannot decode message ", message.TypeName, " from JSON\"`;") - f.P(" if (e instanceof Error && e.message.length > 0) {") - f.P(" m += `: ${e.message}`") - f.P(" }") - f.P(" throw new Error(m);") - f.P(" }") - f.P(" return this;") - f.P(" }") - f.P() - } -} - -func generateWktStaticMethods(f *protoplugin.GeneratedFile, message *protoplugin.Message) { - rt := message.File.RuntimeSymbols - if ok, _ := gencommon.MatchWktAny(message); ok { - f.P(" static pack(message: Message): ", message.Symbol, " {") - f.P(" const any = new ", message.Symbol, "();") - f.P(" any.packFrom(message);") - f.P(" return any;") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktTimestamp(message); ok { - f.P(" static now(): ", message.Symbol, " {") - f.P(" return ", message.Symbol, ".fromDate(new Date())") - f.P(" }") - f.P() - f.P(" static fromDate(date: Date): ", message.Symbol, " {") - f.P(" const ms = date.getTime();") - f.P(" return new ", message.Symbol, "({") - f.P(" ", ref.Seconds.LocalName, ": ", rt.ProtoInt64, ".parse(Math.floor(ms / 1000)),") - f.P(" ", ref.Nanos.LocalName, ": (ms % 1000) * 1000000,") - f.P(" });") - f.P(" }") - f.P() - } - if ok, ref := gencommon.MatchWktWrapper(message); ok { - t := gencommon.ScalarTypeScriptType(ref.Value.Scalar) - f.P(" static readonly fieldWrapper = {") - f.P(" wrapField(value: ", t, " | ", message.Symbol, "): ", message.Symbol, " {") - f.P(" return value instanceof ", message.Symbol, " ? value : new ", message.Symbol, "({value});") - f.P(" },") - f.P(" unwrapField(value: ", message.Symbol, "): ", t, " {") - f.P(" return value.", ref.Value.LocalName, ";") - f.P(" }") - f.P(" };") - f.P() - } -} diff --git a/cmd/protoc-gen-es/main.go b/cmd/protoc-gen-es/main.go deleted file mode 100644 index 259959495..000000000 --- a/cmd/protoc-gen-es/main.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package main - -import ( - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/gendts" - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/genjs" - "github.com/bufbuild/protobuf-es/cmd/protoc-gen-es/internal/gents" - "github.com/bufbuild/protobuf-es/private/protoplugin" - "google.golang.org/protobuf/types/pluginpb" -) - -// version is the semantic version of the protobuf-es module. -const version = "v0.0.8" - -func main() { - protoplugin.Options{ - Name: "protoc-gen-es", - Version: version, - }.Pipe(func(gen *protoplugin.Generator) error { - gen.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) - for _, file := range gen.Files { - if !file.Generate { - continue - } - for _, target := range gen.Targets { - switch target { - case protoplugin.TargetTypeScript: - gents.GenerateFile(gen, file) - case protoplugin.TargetJavaScript: - genjs.GenerateFile(gen, file) - case protoplugin.TargetTypeDeclaration: - gendts.GenerateFile(gen, file) - } - } - } - return nil - }) -} diff --git a/docs/generated_code.md b/docs/generated_code.md index c09ee06c3..780817683 100644 --- a/docs/generated_code.md +++ b/docs/generated_code.md @@ -97,8 +97,7 @@ message Example {} we generate a class called `Example`, which extends the base class [Message](https://github.com/bufbuild/protobuf-es/blob/tstamm/add-docs/packages/protobuf/src/message.ts#L40) provided by [@bufbuild/protobuf](../packages/protobuf). See the [runtime API documentation](#runtime-api) for details. -Note that [some names](https://github.com/bufbuild/protobuf-es/blob/5609f7aab3dcfbb468871774c70d2343ac0f265e/private/protoplugin/names.go#L30-L94) -cannot be used as class names and will be escaped by adding the suffix `$`. +Note that some names cannot be used as class names and will be escaped by adding the suffix `$`. For example, a protobuf message `break` will become a class `break$`. @@ -113,8 +112,7 @@ While there is no official style for ECMAScript, most style guides [Node.js APIs](https://nodejs.org/dist/latest-v16.x/docs/api/child_process.html#child_processforkmodulepath-args-options) and [browser APIs](https://fetch.spec.whatwg.org/#request-class) use `lowerCamelCase`, and so do we. -Note that [some names](https://github.com/bufbuild/protobuf-es/blob/5609f7aab3dcfbb468871774c70d2343ac0f265e/private/protoplugin/names.go#L96-L118) -cannot be used as class properties and will be escaped by adding the suffix `$`. +Note that some names cannot be used as class properties and will be escaped by adding the suffix `$`. For example, a protobuf field `constructor` will become a class property `constructor$`. @@ -288,9 +286,9 @@ enum Foo { } ``` -Note that [some names](https://github.com/bufbuild/protobuf-es/blob/5609f7aab3dcfbb468871774c70d2343ac0f265e/private/protoplugin/names.go#L30-L94) -cannot be used as enum names and will be escaped by adding the suffix `$`. -For example, a protobuf enum `catch` will become a TypeScript enum `catch$`. +Note that some names cannot be used as enum names and will be escaped by +adding the suffix `$`. For example, a protobuf enum `catch` will become a +TypeScript enum `catch$`. If all enum values share a prefix that corresponds with the enum's name, the prefix is dropped from all enum value names. For example, for the following diff --git a/docs/migrating.md b/docs/migrating.md index 9985c2c41..aaba0383d 100644 --- a/docs/migrating.md +++ b/docs/migrating.md @@ -36,7 +36,7 @@ And if you dig a bit deeper, you'll notice it [does not implement the JSON forma [does not support TypeScript](https://github.com/protocolbuffers/protobuf/pull/9412), [does not have any reflection capabilities](https://github.com/protocolbuffers/protobuf/issues/1711), [does not use a standard module system](https://github.com/protocolbuffers/protobuf/issues/8389), -and produces rather [large bundles](https://github.com/bufbuild/protobuf-es/tree/main/packages/bench-codesize) +and produces rather [large bundles](https://github.com/bufbuild/protobuf-es/tree/main/packages/protobuf-bench) for the web. Protobuf-ES fixes those issues. It is a modern replacement for `protobuf-javascript`. The following steps show the changes needed to migrate: diff --git a/docs/releasing.md b/docs/releasing.md index be50f88cb..8ef097146 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -27,7 +27,7 @@ To update the version across the packages within the monorepo, run the following command: ```bash -make set-version SET_VERSION=1.2.3 +make setversion SET_VERSION=1.2.3 ``` Commit all changes, then run the following command to publish to npmjs.com: diff --git a/docs/runtime_api.md b/docs/runtime_api.md index f019b4163..fd1a6b9b6 100644 --- a/docs/runtime_api.md +++ b/docs/runtime_api.md @@ -19,7 +19,7 @@ provided by the library. - [64-bit-integral-types](#64-bit-integral-types) - [Reflection](#reflection) - [Iterating over message fields](#iterating-over-message-fields) - - [DescriptorRegistry](#descriptorregistry) + - [Registries](#registries) - [Advanced TypeScript types](#advanced-typescript-types) @@ -247,7 +247,7 @@ with the previous version. In general, the binary format is also more performant JSON. Conformance with the binary and the JSON format is ensured by the -[conformance tests](../packages/conformance-test). We do not implement the text format. +[conformance tests](../packages/protobuf-conformance). We do not implement the text format. @@ -492,21 +492,21 @@ quite a bit of code size. ## Reflection -### DescriptorRegistry +### Registries As you may know, a `.proto` file can also be represented by a [FileDescriptor](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto). Protobuf compilers such as [`buf`](https://github.com/bufbuild/buf) or `protoc` actually compile `.proto` files to a set of descriptors, and code generator plugins receive them when code is generated. -Using a [`DescriptorRegistry`](../packages/protobuf/src/descriptor-registry.ts#L88), you -can create types at run time from a set of descriptors created by a protocol buffers -compiler: - ```sh # generate an image (compatible to a `google.protobuf.FileDescriptorSet`) buf generate --output image.bin ``` +Using a [`DescriptorRegistry`](../packages/protobuf/src/legacy-descriptor-registry.ts#L88), you +can create types at run time from a set of descriptors created by a protocol buffers +compiler: + ```typescript const registry = new DescriptorRegistry.fromFileDescriptorSet( readFileSync("image.bin") diff --git a/go.mod b/go.mod deleted file mode 100644 index 0e562a740..000000000 --- a/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/bufbuild/protobuf-es - -go 1.17 - -require google.golang.org/protobuf v1.28.0 diff --git a/go.sum b/go.sum deleted file mode 100644 index 231604f73..000000000 --- a/go.sum +++ /dev/null @@ -1,8 +0,0 @@ -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/make/scripts/checknodiffgenerated.bash b/make/scripts/checknodiffgenerated.bash deleted file mode 100755 index 034fc4026..000000000 --- a/make/scripts/checknodiffgenerated.bash +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2021-2022 Buf Technologies, Inc. -# -# 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. - -set -euo pipefail - -fail() { - echo "error: $@" >&2 - exit 1 -} - -STATUS_SHORT_PRE_FILE="$(mktemp)" -STATUS_SHORT_POST_FILE="$(mktemp)" -STATUS_SHORT_DIFF_FILE="$(mktemp)" -trap 'rm -rf "${STATUS_SHORT_PRE_FILE}" "${STATUS_SHORT_POST_FILE}" "${STATUS_SHORT_DIFF_FILE}"' EXIT - -git status --short > "${STATUS_SHORT_PRE_FILE}" -"$@" -git status --short > "${STATUS_SHORT_POST_FILE}" -set +e -diff "${STATUS_SHORT_PRE_FILE}" "${STATUS_SHORT_POST_FILE}" > "${STATUS_SHORT_DIFF_FILE}" -set -e - -if [ -s "${STATUS_SHORT_DIFF_FILE}" ]; then - fail "$@ produced a diff, make sure to check these in: -$(grep '<\|>' "${STATUS_SHORT_DIFF_FILE}")" -fi diff --git a/make/scripts/go-build-npm-shim.cjs b/make/scripts/go-build-npm-shim.cjs deleted file mode 100755 index f6fd129f9..000000000 --- a/make/scripts/go-build-npm-shim.cjs +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env node - -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -const {basename, join, dirname} = require("path"); -const {existsSync, readFileSync} = require("fs"); -const {execFileSync} = require("child_process"); - -const baseDir = dirname(__dirname); -let basePkg; -try { - basePkg = readPackage(baseDir); -} catch (e) { - exitReadBasePackage(e); -} -const wantName = findPlatformPackageName(basePkg); -if (!basePkg.optionalDependencies[wantName]) { - exitUnsupportedPlatform(basePkg); -} -const binPath = Object.values(basePkg.bin)[0]; -let absBinPath; -try { - absBinPath = require.resolve(join(wantName, binPath)); -} catch (e) { - exitMissingPlatformBinary(basePkg); -} -execFileSync(absBinPath, process.argv.slice(2), {stdio: 'inherit', cwd: process.cwd(), env: process.env}); - -function exitReadBasePackage(error) { - const message = error instanceof Error ? error.message : String(error); - process.stderr.write(`${basename(__filename)}: ${message}\n`); - process.exit(1); -} - -function exitUnsupportedPlatform(basePkg) { - process.stderr.write(`${basePkg.name}: unsupported platform/architecture: ${process.platform}/${process.arch}\n`); - process.exit(1); -} - -function exitMissingPlatformBinary(basePkg) { - process.stderr.write(`${basePkg.name}: binary for ${process.platform}/${process.arch} is missing\n`); - process.exit(1); -} - -function readPackage(dir) { - const pkgPath = join(dir, "package.json"); - if (!existsSync(pkgPath)) { - throw new Error(`invalid npm-base: ${pkgPath} not found`); - } - const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")); - if (!pkg.name) { - throw new Error(`${pkgPath} is missing "name"`); - } - if (!pkg.bin) { - throw new Error(`${pkgPath} is missing "bin"`); - } - if (Object.keys(pkg.bin).length !== 1) { - throw new Error(`${pkgPath} is requires exactly one entry in "bin"`); - } - const binName = Object.keys(pkg.bin)[0]; - const binValue = Object.values(pkg.bin)[0]; - if ( - binName === undefined || - binValue === undefined || - binValue !== `bin/${binName}` - ) { - throw new Error( - `${pkgPath} is missing an entry in "bin" in the form of {"foo": "bin/foo"}` - ); - } - return pkg; -} - -function findPlatformPackageName() { - // prettier-ignore - const platforms = [ - { name: "darwin-64", npmOs: "darwin", npmCpu: "x64", }, - { name: "darwin-64", npmOs: "darwin", npmCpu: "x64", }, - { name: "darwin-arm64", npmOs: "darwin", npmCpu: "arm64", }, - { name: "windows-64", npmOs: "win32", npmCpu: "x64", }, - { name: "windows-arm64", npmOs: "win32", npmCpu: "arm64", }, - { name: "windows-32", npmOs: "win32", npmCpu: "ia32", }, - { name: "linux-64", npmOs: "linux", npmCpu: "x64", }, - { name: "linux-32", npmOs: "linux", npmCpu: "ia32", }, - { name: "linux-arm", npmOs: "linux", npmCpu: "arm", }, - { name: "linux-arm64", npmOs: "linux", npmCpu: "arm64", }, - { name: "freebsd-64", npmOs: "freebsd", npmCpu: "x64", }, - { name: "freebsd-arm64", npmOs: "freebsd", npmCpu: "arm64", }, - { name: "netbsd-64", npmOs: "netbsd", npmCpu: "x64", }, - { name: "openbsd-64", npmOs: "openbsd", npmCpu: "x64", }, - ]; - const platform = platforms.find(p => p.npmOs === process.platform && p.npmCpu === process.arch); - if (!platform) { - return undefined; - } - return `${basePkg.name}-${platform.name}`; -} diff --git a/make/scripts/go-build-npm.js b/make/scripts/go-build-npm.js deleted file mode 100755 index 8deffe3fc..000000000 --- a/make/scripts/go-build-npm.js +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env node - -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -import { exec } from "child_process"; -import { - existsSync, - mkdirSync, - readFileSync, - writeFileSync, - copyFileSync, -} from "fs"; -import { basename, dirname, join } from "path"; -import { fileURLToPath } from "url"; - -if (process.argv.length < 4) { - process.stderr.write( - [ - `USAGE: ${process.argv[1]} `, - "", - "Cross compiles a Go program for distribution via NPM", - "", - "npm-base: path to the base npm package, for example packages/foo", - "go-pkg: go package name to build, for example ./cmd/foo", - "", - ].join("\n") - ); - process.exit(1); -} - -const __dirname = dirname(fileURLToPath(import.meta.url)); -const npmBase = process.argv[2]; -const goPkg = process.argv[3]; -const goFlags = `-ldflags="-s -w" -trimpath`; -// prettier-ignore -const platforms = [ - { name: "darwin-64", npmOs: "darwin", npmCpu: "x64", goFlags, goEnv: { GOOS: "darwin", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "darwin-64", npmOs: "darwin", npmCpu: "x64", goFlags, goEnv: { GOOS: "darwin", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "darwin-arm64", npmOs: "darwin", npmCpu: "arm64", goFlags, goEnv: { GOOS: "darwin", GOARCH: "arm64", CGO_ENABLED: 0 } }, - { name: "windows-64", npmOs: "win32", npmCpu: "x64", goFlags, goEnv: { GOOS: "windows", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "windows-arm64", npmOs: "win32", npmCpu: "arm64", goFlags, goEnv: { GOOS: "windows", GOARCH: "arm64", CGO_ENABLED: 0 } }, - { name: "windows-32", npmOs: "win32", npmCpu: "ia32", goFlags, goEnv: { GOOS: "windows", GOARCH: "386" , CGO_ENABLED: 0 } }, - { name: "linux-64", npmOs: "linux", npmCpu: "x64", goFlags, goEnv: { GOOS: "linux", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "linux-32", npmOs: "linux", npmCpu: "ia32", goFlags, goEnv: { GOOS: "linux", GOARCH: "386" , CGO_ENABLED: 0 } }, - { name: "linux-arm", npmOs: "linux", npmCpu: "arm", goFlags, goEnv: { GOOS: "linux", GOARCH: "arm" , CGO_ENABLED: 0 } }, - { name: "linux-arm64", npmOs: "linux", npmCpu: "arm64", goFlags, goEnv: { GOOS: "linux", GOARCH: "arm64", CGO_ENABLED: 0 } }, - { name: "freebsd-64", npmOs: "freebsd", npmCpu: "x64", goFlags, goEnv: { GOOS: "freebsd", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "freebsd-arm64", npmOs: "freebsd", npmCpu: "arm64", goFlags, goEnv: { GOOS: "freebsd", GOARCH: "arm64", CGO_ENABLED: 0 } }, - { name: "netbsd-64", npmOs: "netbsd", npmCpu: "x64", goFlags, goEnv: { GOOS: "netbsd", GOARCH: "amd64", CGO_ENABLED: 0 } }, - { name: "openbsd-64", npmOs: "openbsd", npmCpu: "x64", goFlags, goEnv: { GOOS: "openbsd", GOARCH: "amd64", CGO_ENABLED: 0 } }, -]; - -try { - scaffold(npmBase, platforms); - const builds = platforms.map((platform) => - goBuild( - goPkg, - platform, - (successMessage) => { - process.stdout.write(successMessage + "\n"); - }, - (errorMessage) => { - for (const child of builds) { - if (!child.killed) { - child.kill("SIGABRT"); - } - } - process.stderr.write(errorMessage + "\n"); - process.exit(1); - } - ) - ); -} catch (e) { - process.stderr.write(String(e) + "\n"); - process.exit(1); -} - -function goBuild(goPkg, platform, onSuccess, onError) { - const platformDir = getPlatformDir(platform, npmBase); - let output = join(platformDir, "bin", basename(npmBase)); - { - if (platform.goEnv.GOOS === "windows") { - output += ".exe"; - } - } - const command = `go build -o ${output} ${platform.goFlags} ${goPkg}`; - return exec( - command, - { - encoding: "utf8", - shell: true, - env: { - ...process.env, - ...platform.goEnv, - }, - }, - (err, stdout, stderr) => { - if (err) { - onError( - `build ${platform.name} failed: command exited with status ${err.code}: ${command}\n${stderr}` - ); - } else { - onSuccess(`build ${platform.name} ok`); - } - } - ); -} - -function scaffold(npmBase, platforms) { - const optionalDependencies = {}; - for (const platform of platforms) { - const pkg = readBasePackage(npmBase); - delete pkg.dependencies; - delete pkg.devDependencies; - delete pkg.optionalDependencies; - delete pkg.bin; - delete pkg.scripts; - pkg.name = `${pkg.name}-${platform.name}`; - pkg.os = [platform.npmOs]; - pkg.cpu = [platform.npmCpu]; - if (pkg.description) { - pkg.description = `${pkg.description} (${platform.npmOs} / ${platform.npmCpu})`; - } - const platformDir = getPlatformDir(platform, npmBase); - writePackage(pkg, join(platformDir, "package.json")); - optionalDependencies[pkg.name] = pkg.version; - } - const pkg = readBasePackage(npmBase); - pkg.optionalDependencies = optionalDependencies; - const shimTarget = join(npmBase, Object.values(pkg.bin)[0]); - mkdirSync(dirname(shimTarget), { recursive: true }); - copyFileSync(join(__dirname, "go-build-npm-shim.cjs"), shimTarget); - writePackage(pkg, join(npmBase, "package.json")); -} - -function getPlatformDir(platform, npmBase) { - return join(dirname(npmBase), `${basename(npmBase)}-${platform.name}`); -} - -function readBasePackage(npmBase) { - const pkgPath = join(npmBase, "package.json"); - if (!existsSync(pkgPath)) { - throw new Error(`invalid npm-base: ${pkgPath} not found`); - } - const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")); - if (!pkg.name) { - throw new Error(`${pkgPath} is missing "name"`); - } - if (!pkg.bin) { - throw new Error(`${pkgPath} is missing "bin"`); - } - if (Object.keys(pkg.bin).length !== 1) { - throw new Error(`${pkgPath} is requires exactly one entry in "bin"`); - } - const binName = Object.keys(pkg.bin)[0]; - const binValue = Object.values(pkg.bin)[0]; - if ( - binName === undefined || - binValue === undefined || - binValue !== `bin/${binName}` - ) { - throw new Error( - `${pkgPath} is missing an entry in "bin" in the form of {"foo": "bin/foo"}` - ); - } - return pkg; -} - -function writePackage(pkg, path) { - mkdirSync(dirname(path), { recursive: true }); - writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n"); -} diff --git a/make/scripts/update-go-version-file.js b/make/scripts/update-go-version-file.js deleted file mode 100755 index 607eafdbc..000000000 --- a/make/scripts/update-go-version-file.js +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env node - -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -import { readFileSync, writeFileSync } from "fs"; -import { join } from "path"; - -if (process.argv.length < 4) { - process.stderr.write( - [ - `USAGE: ${process.argv[1]} `, - "", - "Updates the version number in a main.go file", - "", - ].join("\n") - ); - process.exit(1); -} - -try { - const projectDir = new URL("../../", import.meta.url).pathname; - const goVersionPath = join(projectDir, process.argv[2]); - const newVersionVLess = process.argv[3].startsWith("v") - ? process.argv[3].substring(1) - : process.argv[3]; - const newVersionV = "v" + newVersionVLess; - const goUpdates = updateGoVersion(goVersionPath, newVersionV); - for (let u of goUpdates) { - process.stdout.write(u + "\n"); - } -} catch (e) { - process.stderr.write(String(e) + "\n"); - process.exit(1); -} - -function updateGoVersion(path, newVersion) { - const updates = []; - const go = readFileSync(path, "utf-8"); - const matches = /.*version = "(v?\d+\.\d+\.\d+.*)".*/.exec(go); - if (!matches) { - throw "no version found in go file " + path; - } - const oldVersion = matches[1]; - if (oldVersion !== newVersion) { - const newGo = go.replace(oldVersion, newVersion); - writeFileSync(path, newGo); - updates.push(`${path}:`); - updates.push(` updated version from ${oldVersion} to ${newVersion}`); - } - return updates; -} diff --git a/package-lock.json b/package-lock.json index ee58a9a5b..9f7832c83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,11 @@ "workspaces": [ "./packages/protobuf", "./packages/protobuf-test", - "./packages/conformance-test", - "./packages/bench-codesize", + "./packages/protobuf-conformance", + "./packages/protobuf-bench", "./packages/example", + "./packages/protoplugin", + "./packages/protoplugin-test", "./packages/protoc-gen-es*" ], "devDependencies": { @@ -559,12 +561,12 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, - "node_modules/@bufbuild/bench-codesize": { - "resolved": "packages/bench-codesize", + "node_modules/@bufbuild/protobuf-bench": { + "resolved": "packages/protobuf-bench", "link": true }, - "node_modules/@bufbuild/conformance-test": { - "resolved": "packages/conformance-test", + "node_modules/@bufbuild/protobuf-conformance": { + "resolved": "packages/protobuf-conformance", "link": true }, "node_modules/@bufbuild/example": { @@ -635,6 +637,14 @@ "resolved": "packages/protoc-gen-es-windows-arm64", "link": true }, + "node_modules/@bufbuild/protoplugin": { + "resolved": "packages/protoplugin", + "link": true + }, + "node_modules/@bufbuild/protoplugin-test": { + "resolved": "packages/protoplugin-test", + "link": true + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "dev": true, @@ -5490,16 +5500,16 @@ "node": ">=12" } }, - "packages/bench-codesize": { - "name": "@bufbuild/bench-codesize", + "packages/protobuf-bench": { + "name": "@bufbuild/protobuf-bench", "dependencies": { "@bufbuild/protobuf": "0.0.8", "esbuild": "^0.14.48", "google-protobuf": "^3.20.1" } }, - "packages/conformance-test": { - "name": "@bufbuild/conformance-test", + "packages/protobuf-conformance": { + "name": "@bufbuild/protobuf-conformance", "version": "0.0.8", "dependencies": { "@bufbuild/protobuf": "0.0.8", @@ -5541,23 +5551,14 @@ "name": "@bufbuild/protoc-gen-es", "version": "0.0.8", "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protoplugin": "^0.0.8" + }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" }, - "optionalDependencies": { - "@bufbuild/protoc-gen-es-darwin-64": "0.0.8", - "@bufbuild/protoc-gen-es-darwin-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-linux-32": "0.0.8", - "@bufbuild/protoc-gen-es-linux-64": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-netbsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-openbsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-32": "0.0.8", - "@bufbuild/protoc-gen-es-windows-64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-arm64": "0.0.8" + "engines": { + "node": ">=14" }, "peerDependencies": { "@bufbuild/protobuf": "^0.0.8" @@ -5814,6 +5815,29 @@ "optional": true } } + }, + "packages/protoplugin": { + "name": "@bufbuild/protoplugin", + "version": "0.0.8", + "license": "(Apache-2.0 AND BSD-3-Clause)", + "dependencies": { + "@bufbuild/protobuf": "^0.0.8" + }, + "devDependencies": { + "typescript": "^4.7.4" + } + }, + "packages/protoplugin-test": { + "name": "@bufbuild/protoplugin-test", + "version": "0.0.8", + "dependencies": { + "@bufbuild/protoplugin": "0.0.8", + "@types/jest": "^28.1.4", + "jest": "^28.1.2" + }, + "devDependencies": { + "typescript": "^4.7.4" + } } }, "dependencies": { @@ -6212,16 +6236,16 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, - "@bufbuild/bench-codesize": { - "version": "file:packages/bench-codesize", + "@bufbuild/protobuf-bench": { + "version": "file:packages/protobuf-bench", "requires": { "@bufbuild/protobuf": "0.0.8", "esbuild": "^0.14.48", "google-protobuf": "^3.20.1" } }, - "@bufbuild/conformance-test": { - "version": "file:packages/conformance-test", + "@bufbuild/protobuf-conformance": { + "version": "file:packages/protobuf-conformance", "requires": { "@bufbuild/protobuf": "0.0.8", "@types/node": "^18.0.1", @@ -6255,19 +6279,7 @@ "@bufbuild/protoc-gen-es": { "version": "file:packages/protoc-gen-es", "requires": { - "@bufbuild/protoc-gen-es-darwin-64": "0.0.8", - "@bufbuild/protoc-gen-es-darwin-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-linux-32": "0.0.8", - "@bufbuild/protoc-gen-es-linux-64": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-netbsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-openbsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-32": "0.0.8", - "@bufbuild/protoc-gen-es-windows-64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-arm64": "0.0.8" + "@bufbuild/protoplugin": "^0.0.8" } }, "@bufbuild/protoc-gen-es-darwin-64": { @@ -6322,6 +6334,22 @@ "version": "file:packages/protoc-gen-es-windows-arm64", "requires": {} }, + "@bufbuild/protoplugin": { + "version": "file:packages/protoplugin", + "requires": { + "@bufbuild/protobuf": "^0.0.8", + "typescript": "^4.7.4" + } + }, + "@bufbuild/protoplugin-test": { + "version": "file:packages/protoplugin-test", + "requires": { + "@bufbuild/protoplugin": "0.0.8", + "@types/jest": "^28.1.4", + "jest": "^28.1.2", + "typescript": "^4.7.4" + } + }, "@eslint/eslintrc": { "version": "1.3.0", "dev": true, diff --git a/package.json b/package.json index 8898c2000..4055d0d82 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "private": true, "workspaces": [ "./packages/protobuf", + "./packages/protoc-gen-es", + "./packages/protoplugin", "./packages/protobuf-test", - "./packages/conformance-test", - "./packages/bench-codesize", - "./packages/example", - "./packages/protoc-gen-es*" + "./packages/protobuf-conformance", + "./packages/protobuf-bench", + "./packages/example" ], "type": "module", "engineStrict": true, diff --git a/packages/README.md b/packages/README.md deleted file mode 100644 index 1715e2625..000000000 --- a/packages/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# What's all this? - - -### [`protobuf`](./protobuf) - -This is the npm package [`@bufbuild/protobuf`](https://www.npmjs.com/package/@bufbuild/protobuf), -the runtime library for the code generator plugin. - -### [`protoc-gen-es`](./protoc-gen-es) - -This is the npm package [`@bufbuild/protoc-gen-es`](https://www.npmjs.com/package/@bufbuild/protoc-gen-es) -for the code generator plugin. - -### [`example`](./example) - -A code example that uses protocol buffers to manage an address book. - -### [`bench-codesize`](./bench-codesize) - -This is a simple code size comparison between protobuf-es and google-protobuf. - -### [`conformance-test`](./conformance-test) - -This package implements a testee for the protocol buffers conformance -test suite. -It is used to make sure we are compatible with all the other language -implementations. - -### [`protobuf-test`](./protobuf-test) - -This package provides test coverage for @bufbuild/protobuf with Jest. diff --git a/packages/example/src/gen/addressbook_pb.ts b/packages/example/src/gen/addressbook_pb.ts index 478bbd65b..7150e9a14 100644 --- a/packages/example/src/gen/addressbook_pb.ts +++ b/packages/example/src/gen/addressbook_pb.ts @@ -18,7 +18,7 @@ /* @ts-nocheck */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from message example.Person diff --git a/packages/bench-codesize/README.md b/packages/protobuf-bench/README.md similarity index 92% rename from packages/bench-codesize/README.md rename to packages/protobuf-bench/README.md index d0e12fd9d..39a3eafe4 100644 --- a/packages/bench-codesize/README.md +++ b/packages/protobuf-bench/README.md @@ -10,5 +10,5 @@ server would usually do. | code generator | bundle size | minified | compressed | |---------------------|------------------------:|-----------------------:|-------------------:| -| protobuf-es | 73,175 b | 36,430 b | 9,481 b | +| protobuf-es | 73,756 b | 36,834 b | 9,562 b | | protobuf-javascript | 368,088 b | 270,868 b | 43,782 b | diff --git a/packages/protobuf-bench/buf.gen.yaml b/packages/protobuf-bench/buf.gen.yaml new file mode 100644 index 000000000..4d8e87d7d --- /dev/null +++ b/packages/protobuf-bench/buf.gen.yaml @@ -0,0 +1,13 @@ +# The buf.gen.yaml file defines a local generation template, and is used +# by the buf generate command to generate code for the language(s) of +# your choice. +# Learn more: https://docs.buf.build/configuration/v1/buf-gen-yaml +version: v1 +plugins: + - name: es + path: packages/protoc-gen-es/bin/protoc-gen-es + opt: ts_nocheck=false,target=ts + out: src/gen/protobuf-es + - remote: buf.build/protocolbuffers/plugins/js:v3.19.3-1 + out: src/gen/google-protobuf + opt: import_style=commonjs diff --git a/packages/bench-codesize/package.json b/packages/protobuf-bench/package.json similarity index 86% rename from packages/bench-codesize/package.json rename to packages/protobuf-bench/package.json index c17c77d86..b8e8c1169 100644 --- a/packages/bench-codesize/package.json +++ b/packages/protobuf-bench/package.json @@ -1,5 +1,5 @@ { - "name": "@bufbuild/bench-codesize", + "name": "@bufbuild/protobuf-bench", "private": true, "scripts": { "report": "node report.mjs > README.md", diff --git a/packages/bench-codesize/report.mjs b/packages/protobuf-bench/report.mjs similarity index 100% rename from packages/bench-codesize/report.mjs rename to packages/protobuf-bench/report.mjs diff --git a/packages/bench-codesize/src/entry-google-protobuf.js b/packages/protobuf-bench/src/entry-google-protobuf.js similarity index 100% rename from packages/bench-codesize/src/entry-google-protobuf.js rename to packages/protobuf-bench/src/entry-google-protobuf.js diff --git a/packages/bench-codesize/src/entry-protobuf-es.ts b/packages/protobuf-bench/src/entry-protobuf-es.ts similarity index 100% rename from packages/bench-codesize/src/entry-protobuf-es.ts rename to packages/protobuf-bench/src/entry-protobuf-es.ts diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/envelope_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/envelope_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/envelope_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/envelope_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/module_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/module_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/module_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/module_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/plugin_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/plugin_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/plugin_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/plugin_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/repository_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/repository_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/repository_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/repository_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/role_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/role_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/role_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/role_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/search_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/search_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/search_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/search_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/user_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/user_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/user_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/audit/v1alpha1/user_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/breaking/v1/config_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/breaking/v1/config_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/breaking/v1/config_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/breaking/v1/config_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/image/v1/image_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/image/v1/image_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/image/v1/image_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/image/v1/image_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/lint/v1/config_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/lint/v1/config_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/lint/v1/config_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/lint/v1/config_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/module/v1alpha1/module_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/module/v1alpha1/module_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/module/v1alpha1/module_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/module/v1alpha1/module_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/admin_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/admin_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/admin_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/admin_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/audit_logs_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/audit_logs_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/audit_logs_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/audit_logs_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authn_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authn_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authn_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authn_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authz_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authz_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authz_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/authz_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/display_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/display_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/display_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/display_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/doc_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/doc_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/doc_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/doc_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/download_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/download_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/download_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/download_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/generate_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/generate_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/generate_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/generate_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/image_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/image_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/image_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/image_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/jsonschema_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/jsonschema_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/jsonschema_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/jsonschema_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/module_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/module_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/module_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/module_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/organization_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/organization_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/organization_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/organization_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/owner_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/owner_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/owner_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/owner_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/plugin_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/plugin_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/plugin_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/plugin_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/push_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/push_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/push_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/push_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/recommendation_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/recommendation_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/recommendation_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/recommendation_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/reference_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/reference_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/reference_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/reference_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_branch_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_branch_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_branch_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_branch_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_commit_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_commit_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_commit_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_commit_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_tag_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_tag_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_tag_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_tag_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_commit_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_commit_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_commit_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_commit_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/repository_track_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/resolve_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/resolve_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/resolve_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/resolve_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/role_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/role_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/role_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/role_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/search_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/search_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/search_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/search_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/token_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/token_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/token_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/token_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/user_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/user_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/user_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/registry/v1alpha1/user_pb.js diff --git a/packages/bench-codesize/src/gen/google-protobuf/buf/alpha/rpc/v1alpha1/error_pb.js b/packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/rpc/v1alpha1/error_pb.js similarity index 100% rename from packages/bench-codesize/src/gen/google-protobuf/buf/alpha/rpc/v1alpha1/error_pb.js rename to packages/protobuf-bench/src/gen/google-protobuf/buf/alpha/rpc/v1alpha1/error_pb.js diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts index 4871bef92..76710fe66 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/envelope_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64, Timestamp} from "@bufbuild/protobuf"; import {BufAlphaRegistryV1Alpha1OrganizationRole, BufAlphaRegistryV1Alpha1PluginRole, BufAlphaRegistryV1Alpha1RepositoryRole, BufAlphaRegistryV1Alpha1ServerRole, BufAlphaRegistryV1Alpha1TemplateRole} from "./role_pb.js"; import {BufAlphaRegistryV1Alpha1PluginConfig, BufAlphaRegistryV1Alpha1PluginVersionMapping, BufAlphaRegistryV1Alpha1PluginVersionRuntimeLibrary, BufAlphaRegistryV1Alpha1PluginVisibility} from "./plugin_pb.js"; import {BufAlphaRegistryV1Alpha1RepositoryBranch, BufAlphaRegistryV1Alpha1RepositoryCommit, BufAlphaRegistryV1Alpha1RepositoryTag, BufAlphaRegistryV1Alpha1RepositoryTrack, BufAlphaRegistryV1Alpha1Visibility} from "./repository_pb.js"; @@ -1156,7 +1156,7 @@ export class ActionBufAlphaRegistryV1Alpha1AddOrganizationMemberInfo extends Mes /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1OrganizationRole organization_role = 3; */ - organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_UNSPECIFIED; + organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -1209,7 +1209,7 @@ export class ActionBufAlphaRegistryV1Alpha1UpdateOrganizationMemberInfo extends /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1OrganizationRole organization_role = 3; */ - organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_UNSPECIFIED; + organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -1302,17 +1302,17 @@ export class ActionBufAlphaRegistryV1Alpha1UpdateOrganizationSettingsInfo extend /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1RepositoryRole repository_base_role = 2; */ - repositoryBaseRole = BufAlphaRegistryV1Alpha1RepositoryRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_UNSPECIFIED; + repositoryBaseRole = BufAlphaRegistryV1Alpha1RepositoryRole.UNSPECIFIED; /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1PluginRole plugin_base_role = 3; */ - pluginBaseRole = BufAlphaRegistryV1Alpha1PluginRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_UNSPECIFIED; + pluginBaseRole = BufAlphaRegistryV1Alpha1PluginRole.UNSPECIFIED; /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1TemplateRole template_base_role = 4; */ - templateBaseRole = BufAlphaRegistryV1Alpha1TemplateRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_UNSPECIFIED; + templateBaseRole = BufAlphaRegistryV1Alpha1TemplateRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -1365,7 +1365,7 @@ export class ActionBufAlphaRegistryV1Alpha1CreatePluginInfo extends Message) { super(); @@ -1504,7 +1504,7 @@ export class ActionBufAlphaRegistryV1Alpha1CreateTemplateInfo extends Message) { super(); @@ -2573,7 +2573,7 @@ export class ActionBufAlphaRegistryV1Alpha1ListUsersInfo extends Message) { super(); @@ -2659,7 +2659,7 @@ export class ActionBufAlphaRegistryV1Alpha1UpdateUserServerRoleInfo extends Mess /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1ServerRole server_role = 2; */ - serverRole = BufAlphaRegistryV1Alpha1ServerRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_UNSPECIFIED; + serverRole = BufAlphaRegistryV1Alpha1ServerRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -2844,7 +2844,7 @@ export class ActionBufAlphaRegistryV1Alpha1SetRepositoryContributorInfo extends /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1RepositoryRole repository_role = 1; */ - repositoryRole = BufAlphaRegistryV1Alpha1RepositoryRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_UNSPECIFIED; + repositoryRole = BufAlphaRegistryV1Alpha1RepositoryRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -2884,7 +2884,7 @@ export class ActionBufAlphaRegistryV1Alpha1SetPluginContributorInfo extends Mess /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1PluginRole plugin_role = 1; */ - pluginRole = BufAlphaRegistryV1Alpha1PluginRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_UNSPECIFIED; + pluginRole = BufAlphaRegistryV1Alpha1PluginRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -2924,7 +2924,7 @@ export class ActionBufAlphaRegistryV1Alpha1SetTemplateContributorInfo extends Me /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1TemplateRole template_role = 1; */ - templateRole = BufAlphaRegistryV1Alpha1TemplateRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_UNSPECIFIED; + templateRole = BufAlphaRegistryV1Alpha1TemplateRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); @@ -3004,7 +3004,7 @@ export class ActionBufAlphaRegistryV1Alpha1SetOrganizationMemberInfo extends Mes /** * @generated from field: buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1OrganizationRole organization_role = 1; */ - organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_UNSPECIFIED; + organizationRole = BufAlphaRegistryV1Alpha1OrganizationRole.UNSPECIFIED; constructor(data?: PartialMessage) { super(); diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts similarity index 95% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts index 2b3ac8f89..0b13dcdfb 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/module_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from enum buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1ResolvedReferenceType @@ -26,27 +26,27 @@ export enum BufAlphaRegistryV1Alpha1ResolvedReferenceType { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_COMMIT = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_COMMIT = 1, + COMMIT = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_BRANCH = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_BRANCH = 2, + BRANCH = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_TAG = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_TAG = 3, + TAG = 3, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_TRACK = 4; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_RESOLVED_REFERENCE_TYPE_TRACK = 4, + TRACK = 4, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1ResolvedReferenceType) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1ResolvedReferenceType, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1ResolvedReferenceType", [ @@ -190,7 +190,7 @@ export class BufAlphaRegistryV1Alpha1LocalModuleResolveResult extends Message) { super(); diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts similarity index 97% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts index 94e42655b..4a1630df6 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/plugin_pb.ts @@ -26,17 +26,17 @@ export enum BufAlphaRegistryV1Alpha1PluginVisibility { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_PUBLIC = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_PUBLIC = 1, + PUBLIC = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_PRIVATE = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_VISIBILITY_PRIVATE = 2, + PRIVATE = 2, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1PluginVisibility) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1PluginVisibility, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1PluginVisibility", [ diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts similarity index 98% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts index 7ae3e3928..6dc681c15 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/repository_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64, Timestamp} from "@bufbuild/protobuf"; /** * @generated from enum buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1Visibility @@ -26,17 +26,17 @@ export enum BufAlphaRegistryV1Alpha1Visibility { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_PUBLIC = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_PUBLIC = 1, + PUBLIC = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_PRIVATE = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_VISIBILITY_PRIVATE = 2, + PRIVATE = 2, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1Visibility) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1Visibility, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1Visibility", [ diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts similarity index 83% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts index 5db4992aa..7798d0cf5 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/role_pb.ts @@ -25,17 +25,17 @@ export enum BufAlphaRegistryV1Alpha1ServerRole { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_ADMIN = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_ADMIN = 1, + ADMIN = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_MEMBER = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SERVER_ROLE_MEMBER = 2, + MEMBER = 2, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1ServerRole) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1ServerRole, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1ServerRole", [ @@ -51,22 +51,22 @@ export enum BufAlphaRegistryV1Alpha1OrganizationRole { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_OWNER = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_OWNER = 1, + OWNER = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_ADMIN = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_ADMIN = 2, + ADMIN = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_MEMBER = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_ORGANIZATION_ROLE_MEMBER = 3, + MEMBER = 3, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1OrganizationRole) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1OrganizationRole, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1OrganizationRole", [ @@ -83,27 +83,27 @@ export enum BufAlphaRegistryV1Alpha1RepositoryRole { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_OWNER = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_OWNER = 1, + OWNER = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_ADMIN = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_ADMIN = 2, + ADMIN = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_WRITE = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_WRITE = 3, + WRITE = 3, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_READ = 4; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_REPOSITORY_ROLE_READ = 4, + READ = 4, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1RepositoryRole) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1RepositoryRole, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1RepositoryRole", [ @@ -121,27 +121,27 @@ export enum BufAlphaRegistryV1Alpha1TemplateRole { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_OWNER = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_OWNER = 1, + OWNER = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_ADMIN = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_ADMIN = 2, + ADMIN = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_WRITE = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_WRITE = 3, + WRITE = 3, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_READ = 4; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_TEMPLATE_ROLE_READ = 4, + READ = 4, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1TemplateRole) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1TemplateRole, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1TemplateRole", [ @@ -159,27 +159,27 @@ export enum BufAlphaRegistryV1Alpha1PluginRole { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_OWNER = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_OWNER = 1, + OWNER = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_ADMIN = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_ADMIN = 2, + ADMIN = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_WRITE = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_WRITE = 3, + WRITE = 3, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_READ = 4; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_PLUGIN_ROLE_READ = 4, + READ = 4, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1PluginRole) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1PluginRole, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1PluginRole", [ diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts similarity index 85% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts index 88923db0d..7a3437d06 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/search_pb.ts @@ -25,37 +25,37 @@ export enum BufAlphaRegistryV1Alpha1SearchFilter { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_USER = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_USER = 1, + USER = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_ORGANIZATION = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_ORGANIZATION = 2, + ORGANIZATION = 2, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_REPOSITORY = 3; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_REPOSITORY = 3, + REPOSITORY = 3, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_PLUGIN = 4; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_PLUGIN = 4, + PLUGIN = 4, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_TEMPLATE = 5; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_TEMPLATE = 5, + TEMPLATE = 5, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_TEAM = 6; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_SEARCH_FILTER_TEAM = 6, + TEAM = 6, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1SearchFilter) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1SearchFilter, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1SearchFilter", [ diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts similarity index 90% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts index 51fcf4d6b..feca3b859 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/audit/v1alpha1/user_pb.ts @@ -25,17 +25,17 @@ export enum BufAlphaRegistryV1Alpha1UserState { /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_UNSPECIFIED = 0; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_UNSPECIFIED = 0, + UNSPECIFIED = 0, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_ACTIVE = 1; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_ACTIVE = 1, + ACTIVE = 1, /** * @generated from enum value: BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_DEACTIVATED = 2; */ - BUF_ALPHA_REGISTRY_V1_ALPHA1_USER_STATE_DEACTIVATED = 2, + DEACTIVATED = 2, } // Retrieve enum metadata with: proto3.getEnumType(BufAlphaRegistryV1Alpha1UserState) proto3.util.setEnumType(BufAlphaRegistryV1Alpha1UserState, "buf.alpha.audit.v1alpha1.BufAlphaRegistryV1Alpha1UserState", [ diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/breaking/v1/config_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/breaking/v1/config_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/breaking/v1/config_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/breaking/v1/config_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts index 254894b2f..f2b4ea29f 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/image/v1/image_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FileOptions, Message, ServiceDescriptorProto, SourceCodeInfo, proto2} from "@bufbuild/protobuf"; +import {DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FileOptions, Message, proto2, ServiceDescriptorProto, SourceCodeInfo} from "@bufbuild/protobuf"; /** * Image is an extended FileDescriptorSet. diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/lint/v1/config_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/lint/v1/config_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/lint/v1/config_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/lint/v1/config_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts index 88688bfd1..2a00e7284 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/module/v1alpha1/module_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; import {Config} from "../../breaking/v1/config_pb.js"; import {Config as Config$1} from "../../lint/v1/config_pb.js"; diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/admin_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/admin_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/admin_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/admin_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts similarity index 98% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts index f8886abf9..487cbe065 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/audit_logs_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; import {Event} from "../../audit/v1alpha1/envelope_pb.js"; /** diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authn_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authn_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authn_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authn_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authz_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authz_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authz_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/authz_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/display_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/display_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/display_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/display_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/doc_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/doc_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/doc_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/doc_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/download_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/download_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/download_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/download_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/generate_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/generate_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/generate_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/generate_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts index 147e780f9..782166b59 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/image_pb.ts @@ -102,7 +102,7 @@ export class GetImageRequest extends Message { * descriptors in those files to describe these types. Accepts messages, enums * and services. All types must be defined in the buf module, types in * dependencies are not accepted. - * + * * At this time specifying `types` requires `exclude_source_info` to be set to * true. * diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/jsonschema_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/jsonschema_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/jsonschema_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/jsonschema_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts similarity index 98% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts index 3d2803ff9..3eaa53e62 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/module_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * LocalModuleReference is a local module reference. diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts index 23e30138b..082a3d995 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/organization_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; import {OrganizationRole, PluginRole, RepositoryRole, TemplateRole} from "./role_pb.js"; /** diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/owner_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/owner_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/owner_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/owner_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/plugin_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/plugin_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/plugin_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/plugin_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/push_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/push_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/push_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/push_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts index 8970d858b..b6ebe4c03 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/recommendation_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * RecommendedRepository is the information about a repository needed to link to diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/reference_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/reference_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/reference_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/reference_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts index 6bc36ce3d..95ee01bee 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_branch_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from message buf.alpha.registry.v1alpha1.RepositoryBranch diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts index c058bca0f..5f65c3afb 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_commit_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64, Timestamp} from "@bufbuild/protobuf"; import {RepositoryTag} from "./repository_tag_pb.js"; /** diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts index 48d75d596..31184d9b4 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; import {User} from "./user_pb.js"; import {RepositoryRole} from "./role_pb.js"; diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts index cbd6fdeff..672dcc83b 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_tag_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from message buf.alpha.registry.v1alpha1.RepositoryTag diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts index 56ea4cf02..2d8ecb2b8 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_commit_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64, Timestamp} from "@bufbuild/protobuf"; /** * RepositoryTrackCommit is the existance of a RepositoryCommit on a RepositoryTrack. Currently its only purpose is diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts index ab2818062..851456014 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/repository_track_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from message buf.alpha.registry.v1alpha1.RepositoryTrack diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/resolve_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/resolve_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/resolve_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/resolve_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/role_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/role_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/role_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/role_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/search_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/search_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/search_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/search_pb.ts diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts index 6051909ae..9f3d8c19e 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/token_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; /** * @generated from message buf.alpha.registry.v1alpha1.Token diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts similarity index 99% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts index 6f8c6562e..45408d57a 100644 --- a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts +++ b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/registry/v1alpha1/user_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Message, Timestamp, proto3} from "@bufbuild/protobuf"; +import {Message, proto3, Timestamp} from "@bufbuild/protobuf"; import {OrganizationRole, ServerRole} from "./role_pb.js"; /** diff --git a/packages/bench-codesize/src/gen/protobuf-es/buf/alpha/rpc/v1alpha1/error_pb.ts b/packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/rpc/v1alpha1/error_pb.ts similarity index 100% rename from packages/bench-codesize/src/gen/protobuf-es/buf/alpha/rpc/v1alpha1/error_pb.ts rename to packages/protobuf-bench/src/gen/protobuf-es/buf/alpha/rpc/v1alpha1/error_pb.ts diff --git a/packages/bench-codesize/tsconfig.json b/packages/protobuf-bench/tsconfig.json similarity index 100% rename from packages/bench-codesize/tsconfig.json rename to packages/protobuf-bench/tsconfig.json diff --git a/packages/conformance-test/README.md b/packages/protobuf-conformance/README.md similarity index 100% rename from packages/conformance-test/README.md rename to packages/protobuf-conformance/README.md diff --git a/packages/conformance-test/bin/conformance_esm.js b/packages/protobuf-conformance/bin/conformance_esm.js similarity index 100% rename from packages/conformance-test/bin/conformance_esm.js rename to packages/protobuf-conformance/bin/conformance_esm.js diff --git a/packages/conformance-test/conformance_failing_tests.txt b/packages/protobuf-conformance/conformance_failing_tests.txt similarity index 100% rename from packages/conformance-test/conformance_failing_tests.txt rename to packages/protobuf-conformance/conformance_failing_tests.txt diff --git a/packages/conformance-test/conformance_failing_tests_text_format.txt b/packages/protobuf-conformance/conformance_failing_tests_text_format.txt similarity index 100% rename from packages/conformance-test/conformance_failing_tests_text_format.txt rename to packages/protobuf-conformance/conformance_failing_tests_text_format.txt diff --git a/packages/conformance-test/package.json b/packages/protobuf-conformance/package.json similarity index 92% rename from packages/conformance-test/package.json rename to packages/protobuf-conformance/package.json index 15a166561..759dce8db 100644 --- a/packages/conformance-test/package.json +++ b/packages/protobuf-conformance/package.json @@ -1,5 +1,5 @@ { - "name": "@bufbuild/conformance-test", + "name": "@bufbuild/protobuf-conformance", "version": "0.0.8", "private": true, "scripts": { diff --git a/packages/conformance-test/src/conformance.ts b/packages/protobuf-conformance/src/conformance.ts similarity index 97% rename from packages/conformance-test/src/conformance.ts rename to packages/protobuf-conformance/src/conformance.ts index 2a4a90816..b4e12c0a0 100644 --- a/packages/conformance-test/src/conformance.ts +++ b/packages/protobuf-conformance/src/conformance.ts @@ -24,17 +24,17 @@ import { TestAllTypesProto2 } from "./gen/google/protobuf/test_messages_proto2_p import { readSync, writeSync } from "fs"; import { Any, + createRegistry, Duration, FieldMask, Int32Value, Message, Struct, Timestamp, - TypeRegistry, Value, } from "@bufbuild/protobuf"; -const typeRegistry = TypeRegistry.from( +const registry = createRegistry( Value, Struct, FieldMask, @@ -69,7 +69,7 @@ function test(request: ConformanceRequest): ConformanceResponse["result"] { return { case: "protobufPayload", value: failureSet.toBinary() }; } - const payloadType = typeRegistry.findMessage(request.messageType); + const payloadType = registry.findMessage(request.messageType); if (!payloadType) { return { case: "runtimeError", @@ -90,7 +90,7 @@ function test(request: ConformanceRequest): ConformanceResponse["result"] { ignoreUnknownFields: request.testCategory === TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST, - typeRegistry, + typeRegistry: registry, }); break; @@ -122,7 +122,7 @@ function test(request: ConformanceRequest): ConformanceResponse["result"] { return { case: "jsonPayload", value: payload.toJsonString({ - typeRegistry, + typeRegistry: registry, }), }; diff --git a/packages/conformance-test/src/gen/conformance/conformance_pb.ts b/packages/protobuf-conformance/src/gen/conformance/conformance_pb.ts similarity index 100% rename from packages/conformance-test/src/gen/conformance/conformance_pb.ts rename to packages/protobuf-conformance/src/gen/conformance/conformance_pb.ts diff --git a/packages/conformance-test/src/gen/google/protobuf/test_messages_proto2_pb.ts b/packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto2_pb.ts similarity index 99% rename from packages/conformance-test/src/gen/google/protobuf/test_messages_proto2_pb.ts rename to packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto2_pb.ts index 9d4afaf26..f79d9bf10 100644 --- a/packages/conformance-test/src/gen/google/protobuf/test_messages_proto2_pb.ts +++ b/packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto2_pb.ts @@ -892,11 +892,11 @@ export class TestAllTypesProto2 extends Message { { no: 248, name: "default_fixed64", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true, default: protoInt64.uParse("10123456789123456789") }, { no: 249, name: "default_sfixed32", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true, default: -123456789 }, { no: 250, name: "default_sfixed64", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true, default: protoInt64.parse("-9123456789123456789") }, - { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9e+09 }, + { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9000000000 }, { no: 252, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 7e+22 }, { no: 253, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 254, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "Rosebud" }, - { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61, ]) }, + { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61]) }, { no: 401, name: "fieldname1", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 402, name: "field_name2", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 403, name: "_field_name3", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, diff --git a/packages/conformance-test/src/gen/google/protobuf/test_messages_proto3_pb.ts b/packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto3_pb.ts similarity index 99% rename from packages/conformance-test/src/gen/google/protobuf/test_messages_proto3_pb.ts rename to packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto3_pb.ts index afc4166d6..6c4c262de 100644 --- a/packages/conformance-test/src/gen/google/protobuf/test_messages_proto3_pb.ts +++ b/packages/protobuf-conformance/src/gen/google/protobuf/test_messages_proto3_pb.ts @@ -40,7 +40,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, Message, NullValue, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, Message, NullValue, proto3, protoInt64, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value} from "@bufbuild/protobuf"; /** * @generated from enum protobuf_test_messages.proto3.ForeignEnum diff --git a/packages/conformance-test/tsconfig.json b/packages/protobuf-conformance/tsconfig.json similarity index 100% rename from packages/conformance-test/tsconfig.json rename to packages/protobuf-conformance/tsconfig.json diff --git a/packages/protobuf-test/extra/enum-annotated.proto b/packages/protobuf-test/extra/enum.proto similarity index 66% rename from packages/protobuf-test/extra/enum-annotated.proto rename to packages/protobuf-test/extra/enum.proto index e0aa169e0..448c34b9f 100644 --- a/packages/protobuf-test/extra/enum-annotated.proto +++ b/packages/protobuf-test/extra/enum.proto @@ -26,11 +26,35 @@ extend google.protobuf.EnumValueOptions { bool enum_value_opt_bool = 3001; } - enum AnnotatedEnum { - option (spec.enum_opt_bool) = true; - UNSPECIFIED = 0; FOO = 1 [(spec.enum_value_opt_bool) = true]; } + +message EnumMessage { + enum NestedEnum { + NESTED_ZERO = 0; + NESTED_ONE = 1; + } +} + +enum SimpleEnum { + SIMPLE_ZERO = 0; + SIMPLE_ONE = 1; +} + +enum AliasEnum { + option allow_alias = true; + ALIAS_ZERO = 0; + ALIAS_ONE = 1; + ALIAS_ONE_ALIASED = 1; +} + +// The generated enum values should drop the "PREFIX_" +// part at the top if the target language allows +// (basically every language except C++). +enum PrefixEnum { + PREFIX_ENUM_ZERO = 0; + PREFIX_ENUM_ONE = 1; +} diff --git a/packages/protobuf-test/src/create-registry-from-desc.test.ts b/packages/protobuf-test/src/create-registry-from-desc.test.ts new file mode 100644 index 000000000..713ede26a --- /dev/null +++ b/packages/protobuf-test/src/create-registry-from-desc.test.ts @@ -0,0 +1,51 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { readFileSync } from "fs"; +import { + createDescriptorSet, + createRegistryFromDescriptors, + FileDescriptorSet, +} from "@bufbuild/protobuf"; +import { TestAllTypes } from "./gen/ts/google/protobuf/unittest_proto3_pb.js"; +import { assertMessageTypeEquals } from "./helpers.js"; + +const fdsBytes = readFileSync("./descriptorset.bin"); +const fds = FileDescriptorSet.fromBinary(fdsBytes); + +describe("createRegistryFromDescriptors()", () => { + test("finds nothing if empty", () => { + const dr = createRegistryFromDescriptors(createDescriptorSet([])); + expect(dr.findMessage("foo.Foo")).toBeUndefined(); + expect(dr.findEnum("foo.Foo")).toBeUndefined(); + }); + test("from google.protobuf.FileDescriptorSet", () => { + const dr = createRegistryFromDescriptors(fds); + expect(dr.findEnum("foo.Foo")).toBeUndefined(); + const mt = dr.findMessage(TestAllTypes.typeName); + expect(mt).toBeDefined(); + if (mt) { + assertMessageTypeEquals(mt, TestAllTypes); + } + }); + test("from serialized google.protobuf.FileDescriptorSet", () => { + const dr = createRegistryFromDescriptors(fdsBytes); + expect(dr.findEnum("foo.Foo")).toBeUndefined(); + const mt = dr.findMessage(TestAllTypes.typeName); + expect(mt).toBeDefined(); + if (mt) { + assertMessageTypeEquals(mt, TestAllTypes); + } + }); +}); diff --git a/packages/protobuf-test/src/create-registry.test.ts b/packages/protobuf-test/src/create-registry.test.ts new file mode 100644 index 000000000..7133e8488 --- /dev/null +++ b/packages/protobuf-test/src/create-registry.test.ts @@ -0,0 +1,38 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { createRegistry } from "@bufbuild/protobuf"; +import { + MessageFieldMessage, + MessageFieldMessage_TestMessage, +} from "./gen/ts/extra/msg-message_pb.js"; + +describe("createRegistry()", () => { + test("finds nothing if empty", () => { + const reg = createRegistry(); + expect(reg.findMessage(MessageFieldMessage.typeName)).toBeUndefined(); + }); + test("finds message", () => { + const reg = createRegistry(MessageFieldMessage); + expect(reg.findMessage(MessageFieldMessage.typeName)).toBe( + MessageFieldMessage + ); + }); + test("finds message through field", () => { + const reg = createRegistry(MessageFieldMessage); + expect(reg.findMessage(MessageFieldMessage_TestMessage.typeName)).toBe( + MessageFieldMessage_TestMessage + ); + }); +}); diff --git a/packages/protobuf-test/src/descriptor-set.test.ts b/packages/protobuf-test/src/descriptor-set.test.ts new file mode 100644 index 000000000..5eda22107 --- /dev/null +++ b/packages/protobuf-test/src/descriptor-set.test.ts @@ -0,0 +1,166 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { readFileSync } from "fs"; +import { createDescriptorSet, proto3, ScalarType } from "@bufbuild/protobuf"; +import { JsonNamesMessage } from "./gen/ts/extra/msg-json-names_pb.js"; +import { MapsMessage } from "./gen/ts/extra/msg-maps_pb.js"; +import { RepeatedScalarValuesMessage } from "./gen/ts/extra/msg-scalar_pb.js"; +import { MessageWithComments } from "./gen/ts/extra/comments_pb.js"; +import { SimpleEnum } from "./gen/ts/extra/enum_pb.js"; +import { + TestAllExtensions, + TestNestedExtension, +} from "./gen/ts/google/protobuf/unittest_pb.js"; + +const fdsBytes = readFileSync("./descriptorset.bin"); + +describe("DescriptorSet", () => { + const set = createDescriptorSet(fdsBytes); + test("knows extension", () => { + const ext = set.extensions.get( + "protobuf_unittest.optional_int32_extension" + ); + expect(ext).toBeDefined(); + expect(ext?.name).toBe("optional_int32_extension"); + expect(ext?.typeName).toBe("protobuf_unittest.optional_int32_extension"); + expect(ext?.extendee.typeName).toBe(TestAllExtensions.typeName); + expect(ext?.optional).toBe(true); + expect(ext?.kind).toBe("scalar_field"); + expect(ext?.scalar).toBe(ScalarType.INT32); + expect(ext?.toString()).toBe( + "extension protobuf_unittest.optional_int32_extension" + ); + expect(ext?.declarationString()).toBe( + "optional int32 optional_int32_extension = 1" + ); + }); + test("knows nested extension", () => { + const ext = set.extensions.get( + "protobuf_unittest.TestNestedExtension.nested_string_extension" + ); + expect(ext).toBeDefined(); + expect(ext?.name).toBe("nested_string_extension"); + expect(ext?.typeName).toBe( + "protobuf_unittest.TestNestedExtension.nested_string_extension" + ); + expect(ext?.extendee.typeName).toBe(TestAllExtensions.typeName); + expect(ext?.scalar).toBe(ScalarType.STRING); + expect(ext?.toString()).toBe( + "extension protobuf_unittest.TestNestedExtension.nested_string_extension" + ); + expect(ext?.declarationString()).toBe( + "optional string nested_string_extension = 1003" + ); + const ext2 = set.messages + .get(TestNestedExtension.typeName) + ?.nestedExtensions.find((ext) => ext.name === "nested_string_extension"); + expect(ext2).toBe(ext); + }); + describe("declarationString()", () => { + test("for field with options", () => { + const message = set.messages.get(JsonNamesMessage.typeName); + expect(message).toBeDefined(); + if (message !== undefined) { + const field = message.fields.find((f) => f.number === 1); + expect(field?.declarationString()).toBe( + 'string scalar_field = 1 [json_name = "scalarFieldJsonName"]' + ); + } + }); + test("for field with labels", () => { + const message = set.messages.get(RepeatedScalarValuesMessage.typeName); + expect(message).toBeDefined(); + if (message !== undefined) { + const field = message.fields.find((f) => f.number === 1); + expect(field?.declarationString()).toBe( + "repeated double double_field = 1" + ); + } + }); + test("for map field", () => { + const message = set.messages.get(MapsMessage.typeName); + const got = message?.fields + .find((f) => f.name === "int32_msg_field") + ?.declarationString(); + expect(got).toBe("map int32_msg_field = 10"); + }); + test("for enum value", () => { + const e = set.enums.get(proto3.getEnumType(SimpleEnum).typeName); + const got = e?.values + .find((v) => v.name === "SIMPLE_ZERO") + ?.declarationString(); + expect(got).toBe("SIMPLE_ZERO = 0"); + }); + }); + describe("getComments()", () => { + describe("for file", () => { + const file = set.files.find((file) => + file.messages.some( + (message) => message.typeName === MessageWithComments.typeName + ) + ); + test("syntax", () => { + const comments = file?.getSyntaxComments(); + expect(comments).toBeDefined(); + if (comments) { + expect(comments.leadingDetached[0]).toMatch( + / Copyright .* Buf Technologies/ + ); + expect(comments.leading).toBe(" Comment before syntax.\n"); + expect(comments.trailing).toBe(" Comment next to syntax.\n"); + } + }); + test("package", () => { + const comments = file?.getPackageComments(); + expect(comments).toBeDefined(); + if (comments) { + expect(comments.leadingDetached[0]).toBe(" Comment after syntax.\n"); + expect(comments.leading).toBe(" Comment before package.\n"); + expect(comments.trailing).toBe(" Comment next to package.\n"); + } + }); + }); + }); + describe("for message", () => { + const message = set.messages.get(MessageWithComments.typeName); + test("itself", () => { + const comments = message?.getComments(); + expect(comments).toBeDefined(); + if (comments) { + expect(comments.leadingDetached).toStrictEqual([ + " Comment after package.\n", + " Comment between package and message.\n", + ]); + expect(comments.leading).toBe(" Comment before message.\n"); + expect(comments.trailing).toBeUndefined(); + } + }); + test("field", () => { + const comments = message?.fields + .find((field) => field.name === "foo") + ?.getComments(); + expect(comments).toBeDefined(); + if (comments) { + expect(comments.leadingDetached).toStrictEqual([ + "\n Comment after start of message,\n with funny indentation,\n and empty lines on start and end.\n\n", + ]); + expect(comments.leading).toBe( + " Comment before field with 5 lines:\n line 2, next is empty\n\n line 4, next is empty\n\n" + ); + expect(comments.trailing).toBe(" Comment next to field.\n"); + } + }); + }); +}); diff --git a/packages/protobuf-test/src/enum.test.ts b/packages/protobuf-test/src/enum.test.ts new file mode 100644 index 000000000..48da33453 --- /dev/null +++ b/packages/protobuf-test/src/enum.test.ts @@ -0,0 +1,116 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { SimpleEnum as SimpleEnum_TS } from "./gen/ts/extra/enum_pb.js"; +import { SimpleEnum as SimpleEnum_JS } from "./gen/js/extra/enum_pb.js"; +import { AliasEnum as AliasEnum_TS } from "./gen/ts/extra/enum_pb.js"; +import { AliasEnum as AliasEnum_JS } from "./gen/js/extra/enum_pb.js"; +import { PrefixEnum as PrefixEnum_TS } from "./gen/ts/extra/enum_pb.js"; +import { PrefixEnum as PrefixEnum_JS } from "./gen/js/extra/enum_pb.js"; +import { proto3 } from "@bufbuild/protobuf"; + +describe("simple enum", () => { + describe("generated as TS", () => { + test("has expected values", () => { + expect(SimpleEnum_TS.SIMPLE_ZERO).toBe(0); + expect(SimpleEnum_TS.SIMPLE_ONE).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(SimpleEnum_TS); + const value0 = type.findName("SIMPLE_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("SIMPLE_ZERO"); + expect(value0?.localName).toBe("SIMPLE_ZERO"); + }); + }); + describe("generated as JS", () => { + test("has expected values", () => { + expect(SimpleEnum_JS.SIMPLE_ZERO).toBe(0); + expect(SimpleEnum_JS.SIMPLE_ONE).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(SimpleEnum_JS); + const value0 = type.findName("SIMPLE_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("SIMPLE_ZERO"); + expect(value0?.localName).toBe("SIMPLE_ZERO"); + }); + }); +}); + +describe("prefixed enum", () => { + describe("generated as TS", () => { + test("has expected values", () => { + expect(PrefixEnum_TS.ZERO).toBe(0); + expect(PrefixEnum_TS.ONE).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(PrefixEnum_TS); + const value0 = type.findName("PREFIX_ENUM_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("PREFIX_ENUM_ZERO"); + expect(value0?.localName).toBe("ZERO"); + }); + }); + describe("generated as JS", () => { + test("has expected values", () => { + expect(PrefixEnum_JS.ZERO).toBe(0); + expect(PrefixEnum_JS.ONE).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(PrefixEnum_JS); + const value0 = type.findName("PREFIX_ENUM_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("PREFIX_ENUM_ZERO"); + expect(value0?.localName).toBe("ZERO"); + }); + }); +}); + +describe("alias enum", () => { + describe("generated as TS", () => { + test("has expected values", () => { + expect(AliasEnum_TS.ALIAS_ZERO).toBe(0); + expect(AliasEnum_TS.ALIAS_ONE).toBe(1); + expect(AliasEnum_TS.ALIAS_ONE_ALIASED).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(AliasEnum_TS); + const value0 = type.findName("ALIAS_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("ALIAS_ZERO"); + expect(value0?.localName).toBe("ALIAS_ZERO"); + }); + }); + describe("generated as JS", () => { + test("has expected values", () => { + expect(AliasEnum_JS.ALIAS_ZERO).toBe(0); + expect(AliasEnum_JS.ALIAS_ONE).toBe(1); + expect(AliasEnum_JS.ALIAS_ONE_ALIASED).toBe(1); + }); + test("has enum type", () => { + const type = proto3.getEnumType(AliasEnum_JS); + const value0 = type.findName("ALIAS_ZERO"); + expect(value0).toBeDefined(); + expect(value0?.no).toBe(0); + expect(value0?.name).toBe("ALIAS_ZERO"); + expect(value0?.localName).toBe("ALIAS_ZERO"); + }); + }); +}); diff --git a/packages/protobuf-test/src/gen/js/extra/comments_pb.d.ts b/packages/protobuf-test/src/gen/js/extra/comments_pb.d.ts index ba86c1f83..3621ae4d5 100644 --- a/packages/protobuf-test/src/gen/js/extra/comments_pb.d.ts +++ b/packages/protobuf-test/src/gen/js/extra/comments_pb.d.ts @@ -124,8 +124,6 @@ export declare class MessageWithComments extends Message { } | { case: undefined; value?: undefined }; /** - * - * * @generated from field: string this_field_has_an_empty_comment = 4; */ thisFieldHasAnEmptyComment: string; diff --git a/packages/protobuf-test/src/gen/js/extra/comments_pb.js b/packages/protobuf-test/src/gen/js/extra/comments_pb.js index 2bc77e23c..b16f34bb7 100644 --- a/packages/protobuf-test/src/gen/js/extra/comments_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/comments_pb.js @@ -49,10 +49,9 @@ export const EnumWithComments = proto3.makeEnum( export const DeprecatedEnumWithComment = proto3.makeEnum( "spec.DeprecatedEnumWithComment", [ - {no: 0, name: "DEPRECATED_ENUM_WITH_COMMENT_A"}, - {no: 1, name: "DEPRECATED_ENUM_WITH_COMMENT_B"}, + {no: 0, name: "DEPRECATED_ENUM_WITH_COMMENT_A", localName: "A"}, + {no: 1, name: "DEPRECATED_ENUM_WITH_COMMENT_B", localName: "B"}, ], - {sharedPrefix: "DEPRECATED_ENUM_WITH_COMMENT_"}, ); /** @@ -62,10 +61,9 @@ export const DeprecatedEnumWithComment = proto3.makeEnum( export const DeprecatedEnumNoComment = proto3.makeEnum( "spec.DeprecatedEnumNoComment", [ - {no: 0, name: "DEPRECATED_ENUM_NO_COMMENT_A"}, - {no: 1, name: "DEPRECATED_ENUM_NO_COMMENT_B"}, + {no: 0, name: "DEPRECATED_ENUM_NO_COMMENT_A", localName: "A"}, + {no: 1, name: "DEPRECATED_ENUM_NO_COMMENT_B", localName: "B"}, ], - {sharedPrefix: "DEPRECATED_ENUM_NO_COMMENT_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/extra/deprecation-explicit_pb.js b/packages/protobuf-test/src/gen/js/extra/deprecation-explicit_pb.js index 634443f99..c028f9552 100644 --- a/packages/protobuf-test/src/gen/js/extra/deprecation-explicit_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/deprecation-explicit_pb.js @@ -27,10 +27,9 @@ import {proto3} from "@bufbuild/protobuf"; export const DeprecatedEnum = proto3.makeEnum( "spec.DeprecatedEnum", [ - {no: 0, name: "DEPRECATED_ENUM_A"}, - {no: 1, name: "DEPRECATED_ENUM_B"}, + {no: 0, name: "DEPRECATED_ENUM_A", localName: "A"}, + {no: 1, name: "DEPRECATED_ENUM_B", localName: "B"}, ], - {sharedPrefix: "DEPRECATED_ENUM_"}, ); /** @@ -41,10 +40,9 @@ export const DeprecatedEnum = proto3.makeEnum( export const DeprecatedValueEnum = proto3.makeEnum( "spec.DeprecatedValueEnum", [ - {no: 0, name: "DEPRECATED_VALUE_ENUM_UNSPECIFIED"}, - {no: 1, name: "DEPRECATED_VALUE_ENUM_DEPRECATED_VALUE"}, + {no: 0, name: "DEPRECATED_VALUE_ENUM_UNSPECIFIED", localName: "UNSPECIFIED"}, + {no: 1, name: "DEPRECATED_VALUE_ENUM_DEPRECATED_VALUE", localName: "DEPRECATED_VALUE"}, ], - {sharedPrefix: "DEPRECATED_VALUE_ENUM_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/extra/enum_pb.d.ts b/packages/protobuf-test/src/gen/js/extra/enum_pb.d.ts new file mode 100644 index 000000000..4099cc460 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/extra/enum_pb.d.ts @@ -0,0 +1,124 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file extra/enum.proto (package spec, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * @generated from enum spec.AnnotatedEnum + */ +export declare enum AnnotatedEnum { + /** + * @generated from enum value: UNSPECIFIED = 0; + */ + UNSPECIFIED = 0, + + /** + * @generated from enum value: FOO = 1; + */ + FOO = 1, +} + +/** + * @generated from enum spec.SimpleEnum + */ +export declare enum SimpleEnum { + /** + * @generated from enum value: SIMPLE_ZERO = 0; + */ + SIMPLE_ZERO = 0, + + /** + * @generated from enum value: SIMPLE_ONE = 1; + */ + SIMPLE_ONE = 1, +} + +/** + * @generated from enum spec.AliasEnum + */ +export declare enum AliasEnum { + /** + * @generated from enum value: ALIAS_ZERO = 0; + */ + ALIAS_ZERO = 0, + + /** + * @generated from enum value: ALIAS_ONE = 1; + */ + ALIAS_ONE = 1, + + /** + * @generated from enum value: ALIAS_ONE_ALIASED = 1; + */ + ALIAS_ONE_ALIASED = 1, +} + +/** + * The generated enum values should drop the "PREFIX_" + * part at the top if the target language allows + * (basically every language except C++). + * + * @generated from enum spec.PrefixEnum + */ +export declare enum PrefixEnum { + /** + * @generated from enum value: PREFIX_ENUM_ZERO = 0; + */ + ZERO = 0, + + /** + * @generated from enum value: PREFIX_ENUM_ONE = 1; + */ + ONE = 1, +} + +/** + * @generated from message spec.EnumMessage + */ +export declare class EnumMessage extends Message { + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "spec.EnumMessage"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumMessage; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumMessage; + + static fromJsonString(jsonString: string, options?: Partial): EnumMessage; + + static equals(a: EnumMessage | PlainMessage | undefined, b: EnumMessage | PlainMessage | undefined): boolean; +} + +/** + * @generated from enum spec.EnumMessage.NestedEnum + */ +export declare enum EnumMessage_NestedEnum { + /** + * @generated from enum value: NESTED_ZERO = 0; + */ + NESTED_ZERO = 0, + + /** + * @generated from enum value: NESTED_ONE = 1; + */ + NESTED_ONE = 1, +} + diff --git a/packages/protobuf-test/src/gen/js/extra/enum_pb.js b/packages/protobuf-test/src/gen/js/extra/enum_pb.js new file mode 100644 index 000000000..13bc10ff9 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/extra/enum_pb.js @@ -0,0 +1,88 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file extra/enum.proto (package spec, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * @generated from enum spec.AnnotatedEnum + */ +export const AnnotatedEnum = proto3.makeEnum( + "spec.AnnotatedEnum", + [ + {no: 0, name: "UNSPECIFIED"}, + {no: 1, name: "FOO"}, + ], +); + +/** + * @generated from enum spec.SimpleEnum + */ +export const SimpleEnum = proto3.makeEnum( + "spec.SimpleEnum", + [ + {no: 0, name: "SIMPLE_ZERO"}, + {no: 1, name: "SIMPLE_ONE"}, + ], +); + +/** + * @generated from enum spec.AliasEnum + */ +export const AliasEnum = proto3.makeEnum( + "spec.AliasEnum", + [ + {no: 0, name: "ALIAS_ZERO"}, + {no: 1, name: "ALIAS_ONE"}, + {no: 1, name: "ALIAS_ONE_ALIASED"}, + ], +); + +/** + * The generated enum values should drop the "PREFIX_" + * part at the top if the target language allows + * (basically every language except C++). + * + * @generated from enum spec.PrefixEnum + */ +export const PrefixEnum = proto3.makeEnum( + "spec.PrefixEnum", + [ + {no: 0, name: "PREFIX_ENUM_ZERO", localName: "ZERO"}, + {no: 1, name: "PREFIX_ENUM_ONE", localName: "ONE"}, + ], +); + +/** + * @generated from message spec.EnumMessage + */ +export const EnumMessage = proto3.makeMessageType( + "spec.EnumMessage", + [], +); + +/** + * @generated from enum spec.EnumMessage.NestedEnum + */ +export const EnumMessage_NestedEnum = proto3.makeEnum( + "spec.EnumMessage.NestedEnum", + [ + {no: 0, name: "NESTED_ZERO"}, + {no: 1, name: "NESTED_ONE"}, + ], +); + diff --git a/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.d.ts b/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.d.ts index 0115c12ef..4250ebeb6 100644 --- a/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.d.ts +++ b/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.d.ts @@ -54,7 +54,7 @@ export declare class JsonNamesMessage extends Message { d: string; /** - * @generated from field: string e = 7; + * @generated from field: string e = 7 [json_name = ""]; */ e: string; diff --git a/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.js b/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.js index f3fb56f32..91d1ed5af 100644 --- a/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/msg-json-names_pb.js @@ -30,7 +30,7 @@ export const JsonNamesMessage = proto3.makeMessageType( { no: 4, name: "b", jsonName: "sameJsonName", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 5, name: "c", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 6, name: "d", jsonName: "c", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 7, name: "e", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "e", jsonName: "", kind: "scalar", T: 9 /* ScalarType.STRING */ }, ], ); diff --git a/packages/protobuf-test/src/gen/js/extra/msg-maps_pb.js b/packages/protobuf-test/src/gen/js/extra/msg-maps_pb.js index 533fe8491..e1b063803 100644 --- a/packages/protobuf-test/src/gen/js/extra/msg-maps_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/msg-maps_pb.js @@ -24,11 +24,10 @@ import {proto3} from "@bufbuild/protobuf"; export const MapsEnum = proto3.makeEnum( "spec.MapsEnum", [ - {no: 0, name: "MAPS_ENUM_ANY"}, - {no: 1, name: "MAPS_ENUM_YES"}, - {no: 2, name: "MAPS_ENUM_NO"}, + {no: 0, name: "MAPS_ENUM_ANY", localName: "ANY"}, + {no: 1, name: "MAPS_ENUM_YES", localName: "YES"}, + {no: 2, name: "MAPS_ENUM_NO", localName: "NO"}, ], - {sharedPrefix: "MAPS_ENUM_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/extra/msg-oneof_pb.js b/packages/protobuf-test/src/gen/js/extra/msg-oneof_pb.js index 19ad1d497..7dec0bfc1 100644 --- a/packages/protobuf-test/src/gen/js/extra/msg-oneof_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/msg-oneof_pb.js @@ -24,11 +24,10 @@ import {proto3} from "@bufbuild/protobuf"; export const OneofEnum = proto3.makeEnum( "spec.OneofEnum", [ - {no: 0, name: "ONEOF_ENUM_UNSPECIFIED"}, - {no: 1, name: "ONEOF_ENUM_A"}, - {no: 2, name: "ONEOF_ENUM_B"}, + {no: 0, name: "ONEOF_ENUM_UNSPECIFIED", localName: "UNSPECIFIED"}, + {no: 1, name: "ONEOF_ENUM_A", localName: "A"}, + {no: 2, name: "ONEOF_ENUM_B", localName: "B"}, ], - {sharedPrefix: "ONEOF_ENUM_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/extra/proto2_pb.js b/packages/protobuf-test/src/gen/js/extra/proto2_pb.js index 1c9678004..aa206caa7 100644 --- a/packages/protobuf-test/src/gen/js/extra/proto2_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/proto2_pb.js @@ -24,10 +24,9 @@ import {proto2, protoInt64} from "@bufbuild/protobuf"; export const Proto2Enum = proto2.makeEnum( "spec.Proto2Enum", [ - {no: 1, name: "PROTO2_ENUM_YES"}, - {no: 2, name: "PROTO2_ENUM_NO"}, + {no: 1, name: "PROTO2_ENUM_YES", localName: "YES"}, + {no: 2, name: "PROTO2_ENUM_NO", localName: "NO"}, ], - {sharedPrefix: "PROTO2_ENUM_"}, ); /** @@ -99,7 +98,7 @@ export const Proto2RequiredDefaultsMessage = proto2.makeMessageType( "spec.Proto2RequiredDefaultsMessage", () => [ { no: 1, name: "string_field", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "hello \" */ " }, - { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, ]) }, + { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B]) }, { no: 3, name: "enum_field", kind: "enum", T: proto2.getEnumType(Proto2Enum), default: Proto2Enum.YES }, { no: 4, name: "message_field", kind: "message", T: Proto2ChildMessage }, ], @@ -112,7 +111,7 @@ export const Proto2DefaultsMessage = proto2.makeMessageType( "spec.Proto2DefaultsMessage", () => [ { no: 1, name: "string_field", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello \" */ " }, - { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, ]) }, + { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B]) }, { no: 3, name: "int32_field", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true, default: 128 }, { no: 4, name: "int46_field", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true, default: protoInt64.parse("-256") }, { no: 5, name: "float_field", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -512.13 }, diff --git a/packages/protobuf-test/src/gen/js/extra/proto3_pb.js b/packages/protobuf-test/src/gen/js/extra/proto3_pb.js index aecde0f51..f282f7346 100644 --- a/packages/protobuf-test/src/gen/js/extra/proto3_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/proto3_pb.js @@ -24,11 +24,10 @@ import {proto3} from "@bufbuild/protobuf"; export const Proto3Enum = proto3.makeEnum( "spec.Proto3Enum", [ - {no: 0, name: "PROTO3_ENUM_UNSPECIFIED"}, - {no: 1, name: "PROTO3_ENUM_YES"}, - {no: 2, name: "PROTO3_ENUM_NO"}, + {no: 0, name: "PROTO3_ENUM_UNSPECIFIED", localName: "UNSPECIFIED"}, + {no: 1, name: "PROTO3_ENUM_YES", localName: "YES"}, + {no: 2, name: "PROTO3_ENUM_NO", localName: "NO"}, ], - {sharedPrefix: "PROTO3_ENUM_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/extra/wkt-wrappers_pb.js b/packages/protobuf-test/src/gen/js/extra/wkt-wrappers_pb.js index e7b8ec1a4..1526e27e2 100644 --- a/packages/protobuf-test/src/gen/js/extra/wkt-wrappers_pb.js +++ b/packages/protobuf-test/src/gen/js/extra/wkt-wrappers_pb.js @@ -16,7 +16,7 @@ // @generated from file extra/wkt-wrappers.proto (package spec, syntax proto3) /* eslint-disable */ -import {BoolValue, BytesValue, DoubleValue, FloatValue, Int32Value, Int64Value, StringValue, UInt32Value, UInt64Value, proto3} from "@bufbuild/protobuf"; +import {BoolValue, BytesValue, DoubleValue, FloatValue, Int32Value, Int64Value, proto3, StringValue, UInt32Value, UInt64Value} from "@bufbuild/protobuf"; /** * @generated from message spec.WrappersMessage diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.d.ts new file mode 100644 index 000000000..a7f25149f --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.d.ts @@ -0,0 +1,193 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/any.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, MessageType, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := anypb.New(foo) + * if err != nil { + * ... + * } + * ... + * foo := &pb.Foo{} + * if err := any.UnmarshalTo(foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + * + * + * @generated from message google.protobuf.Any + */ +export declare class Any extends Message { + /** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * + * + * @generated from field: string type_url = 1; + */ + typeUrl: string; + + /** + * Must be a valid serialized protocol buffer of the above specified type. + * + * @generated from field: bytes value = 2; + */ + value: Uint8Array; + + constructor(data?: PartialMessage); + + packFrom(message: Message): void; + + unpackTo(target: Message): boolean; + + is(type: MessageType): boolean; + + private typeNameToUrl(name: string): string; + + private typeUrlToName(url: string): string; + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Any"; + static readonly fields: FieldList; + + static pack(message: Message): Any; + + static fromBinary(bytes: Uint8Array, options?: Partial): Any; + + static fromJson(jsonValue: JsonValue, options?: Partial): Any; + + static fromJsonString(jsonString: string, options?: Partial): Any; + + static equals(a: Any | PlainMessage | undefined, b: Any | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.js new file mode 100644 index 000000000..700cd3f0e --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/any_pb.js @@ -0,0 +1,212 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/any.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := anypb.New(foo) + * if err != nil { + * ... + * } + * ... + * foo := &pb.Foo{} + * if err := any.UnmarshalTo(foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + * + * + * @generated from message google.protobuf.Any + */ +export const Any = proto3.makeMessageType( + "google.protobuf.Any", + () => [ + { no: 1, name: "type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "value", kind: "scalar", T: 12 /* ScalarType.BYTES */ }, + ], +); + +Any.prototype.toJson = function toJson(options) { + if (this.typeUrl === "") { + return {}; + } + const typeName = this.typeUrlToName(this.typeUrl); + const messageType = options?.typeRegistry?.findMessage(typeName); + if (!messageType) { + throw new Error(`cannot encode message google.protobuf.Any to JSON: "${this.typeUrl}" is not in the type registry`); + } + const message = messageType.fromBinary(this.value); + let json = message.toJson(options); + if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) { + json = {value: json}; + } + json["@type"] = this.typeUrl; + return json; +}; + +Any.prototype.fromJson = function fromJson(json, options) { + if (json === null || Array.isArray(json) || typeof json != "object") { + throw new Error(`cannot decode message google.protobuf.Any from JSON: expected object but got ${json === null ? "null" : Array.isArray(json) ? "array" : typeof json}`); + } + const typeUrl = json["@type"]; + if (typeof typeUrl != "string" || typeUrl == "") { + throw new Error(`cannot decode message google.protobuf.Any from JSON: "@type" is empty`); + } + const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName); + if (!messageType) { + throw new Error(`cannot decode message google.protobuf.Any from JSON: ${typeUrl} is not in the type registry`); + } + let message; + if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) { + message = messageType.fromJson(json["value"], options); + } else { + const copy = Object.assign({}, json); + delete copy["@type"]; + message = messageType.fromJson(copy, options); + } + this.packFrom(message); + return this; +}; + +Any.prototype.packFrom = function packFrom(message) { + this.value = message.toBinary(); + this.typeUrl = this.typeNameToUrl(message.getType().typeName); +}; + +Any.prototype.unpackTo = function unpackTo(target) { + if (!this.is(target.getType())) { + return false; + } + target.fromBinary(this.value); + return true; +}; + +Any.prototype.is = function is(type) { + return this.typeUrl === this.typeNameToUrl(type.typeName); +}; + +Any.prototype.typeNameToUrl = function typeNameToUrl(name) { + return `type.googleapis.com/${name}`; +}; + +Any.prototype.typeUrlToName = function typeUrlToName(url) { + if (!url.length) { + throw new Error(`invalid type url: ${url}`); + } + const slash = url.lastIndexOf("/"); + const name = slash > 0 ? url.substring(slash + 1) : url; + if (!name.length) { + throw new Error(`invalid type url: ${url}`); + } + return name; +}; + +Any.pack = function pack(message) { + const any = new Any(); + any.packFrom(message); + return any; +}; + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.d.ts new file mode 100644 index 000000000..26af9f092 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.d.ts @@ -0,0 +1,322 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/api.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; +import type {Option, Syntax} from "./type_pb.js"; +import type {SourceContext} from "./source_context_pb.js"; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + * + * @generated from message google.protobuf.Api + */ +export declare class Api extends Message { + /** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * + * @generated from field: string name = 1; + */ + name: string; + + /** + * The methods of this interface, in unspecified order. + * + * @generated from field: repeated google.protobuf.Method methods = 2; + */ + methods: Method[]; + + /** + * Any metadata attached to the interface. + * + * @generated from field: repeated google.protobuf.Option options = 3; + */ + options: Option[]; + + /** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * + * + * + * @generated from field: string version = 4; + */ + version: string; + + /** + * Source context for the protocol buffer service represented by this + * message. + * + * @generated from field: google.protobuf.SourceContext source_context = 5; + */ + sourceContext?: SourceContext; + + /** + * Included interfaces. See [Mixin][]. + * + * @generated from field: repeated google.protobuf.Mixin mixins = 6; + */ + mixins: Mixin[]; + + /** + * The source syntax of the service. + * + * @generated from field: google.protobuf.Syntax syntax = 7; + */ + syntax: Syntax; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Api"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Api; + + static fromJson(jsonValue: JsonValue, options?: Partial): Api; + + static fromJsonString(jsonString: string, options?: Partial): Api; + + static equals(a: Api | PlainMessage | undefined, b: Api | PlainMessage | undefined): boolean; +} + +/** + * Method represents a method of an API interface. + * + * @generated from message google.protobuf.Method + */ +export declare class Method extends Message { + /** + * The simple name of this method. + * + * @generated from field: string name = 1; + */ + name: string; + + /** + * A URL of the input message type. + * + * @generated from field: string request_type_url = 2; + */ + requestTypeUrl: string; + + /** + * If true, the request is streamed. + * + * @generated from field: bool request_streaming = 3; + */ + requestStreaming: boolean; + + /** + * The URL of the output message type. + * + * @generated from field: string response_type_url = 4; + */ + responseTypeUrl: string; + + /** + * If true, the response is streamed. + * + * @generated from field: bool response_streaming = 5; + */ + responseStreaming: boolean; + + /** + * Any metadata attached to the method. + * + * @generated from field: repeated google.protobuf.Option options = 6; + */ + options: Option[]; + + /** + * The source syntax of this method. + * + * @generated from field: google.protobuf.Syntax syntax = 7; + */ + syntax: Syntax; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Method"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Method; + + static fromJson(jsonValue: JsonValue, options?: Partial): Method; + + static fromJsonString(jsonString: string, options?: Partial): Method; + + static equals(a: Method | PlainMessage | undefined, b: Method | PlainMessage | undefined): boolean; +} + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inheriting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + * + * @generated from message google.protobuf.Mixin + */ +export declare class Mixin extends Message { + /** + * The fully qualified name of the interface which is included. + * + * @generated from field: string name = 1; + */ + name: string; + + /** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * + * @generated from field: string root = 2; + */ + root: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Mixin"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Mixin; + + static fromJson(jsonValue: JsonValue, options?: Partial): Mixin; + + static fromJsonString(jsonString: string, options?: Partial): Mixin; + + static equals(a: Mixin | PlainMessage | undefined, b: Mixin | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.js new file mode 100644 index 000000000..62aec32ab --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/api_pb.js @@ -0,0 +1,172 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/api.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; +import {Option, Syntax} from "./type_pb.js"; +import {SourceContext} from "./source_context_pb.js"; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + * + * @generated from message google.protobuf.Api + */ +export const Api = proto3.makeMessageType( + "google.protobuf.Api", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "methods", kind: "message", T: Method, repeated: true }, + { no: 3, name: "options", kind: "message", T: Option, repeated: true }, + { no: 4, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "source_context", kind: "message", T: SourceContext }, + { no: 6, name: "mixins", kind: "message", T: Mixin, repeated: true }, + { no: 7, name: "syntax", kind: "enum", T: proto3.getEnumType(Syntax) }, + ], +); + +/** + * Method represents a method of an API interface. + * + * @generated from message google.protobuf.Method + */ +export const Method = proto3.makeMessageType( + "google.protobuf.Method", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "request_type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "request_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 4, name: "response_type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "response_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 6, name: "options", kind: "message", T: Option, repeated: true }, + { no: 7, name: "syntax", kind: "enum", T: proto3.getEnumType(Syntax) }, + ], +); + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inheriting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + * + * @generated from message google.protobuf.Mixin + */ +export const Mixin = proto3.makeMessageType( + "google.protobuf.Mixin", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "root", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ], +); + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.d.ts new file mode 100644 index 000000000..bb971df22 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.d.ts @@ -0,0 +1,324 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/compiler/plugin.proto (package google.protobuf.compiler, syntax proto2) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto2} from "@bufbuild/protobuf"; +import type {FileDescriptorProto, GeneratedCodeInfo} from "../descriptor_pb.js"; + +/** + * The version number of protocol compiler. + * + * @generated from message google.protobuf.compiler.Version + */ +export declare class Version extends Message { + /** + * @generated from field: optional int32 major = 1; + */ + major?: number; + + /** + * @generated from field: optional int32 minor = 2; + */ + minor?: number; + + /** + * @generated from field: optional int32 patch = 3; + */ + patch?: number; + + /** + * A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + * be empty for mainline stable releases. + * + * @generated from field: optional string suffix = 4; + */ + suffix?: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.compiler.Version"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Version; + + static fromJson(jsonValue: JsonValue, options?: Partial): Version; + + static fromJsonString(jsonString: string, options?: Partial): Version; + + static equals(a: Version | PlainMessage | undefined, b: Version | PlainMessage | undefined): boolean; +} + +/** + * An encoded CodeGeneratorRequest is written to the plugin's stdin. + * + * @generated from message google.protobuf.compiler.CodeGeneratorRequest + */ +export declare class CodeGeneratorRequest extends Message { + /** + * The .proto files that were explicitly listed on the command-line. The + * code generator should generate code only for these files. Each file's + * descriptor will be included in proto_file, below. + * + * @generated from field: repeated string file_to_generate = 1; + */ + fileToGenerate: string[]; + + /** + * The generator parameter passed on the command-line. + * + * @generated from field: optional string parameter = 2; + */ + parameter?: string; + + /** + * FileDescriptorProtos for all files in files_to_generate and everything + * they import. The files will appear in topological order, so each file + * appears before any file that imports it. + * + * protoc guarantees that all proto_files will be written after + * the fields above, even though this is not technically guaranteed by the + * protobuf wire format. This theoretically could allow a plugin to stream + * in the FileDescriptorProtos and handle them one by one rather than read + * the entire set into memory at once. However, as of this writing, this + * is not similarly optimized on protoc's end -- it will store all fields in + * memory at once before sending them to the plugin. + * + * Type names of fields and extensions in the FileDescriptorProto are always + * fully qualified. + * + * @generated from field: repeated google.protobuf.FileDescriptorProto proto_file = 15; + */ + protoFile: FileDescriptorProto[]; + + /** + * The version number of protocol compiler. + * + * @generated from field: optional google.protobuf.compiler.Version compiler_version = 3; + */ + compilerVersion?: Version; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorRequest"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorRequest; + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorRequest; + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorRequest; + + static equals(a: CodeGeneratorRequest | PlainMessage | undefined, b: CodeGeneratorRequest | PlainMessage | undefined): boolean; +} + +/** + * The plugin writes an encoded CodeGeneratorResponse to stdout. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse + */ +export declare class CodeGeneratorResponse extends Message { + /** + * Error message. If non-empty, code generation failed. The plugin process + * should exit with status code zero even if it reports an error in this way. + * + * This should be used to indicate errors in .proto files which prevent the + * code generator from generating correct code. Errors which indicate a + * problem in protoc itself -- such as the input CodeGeneratorRequest being + * unparseable -- should be reported by writing a message to stderr and + * exiting with a non-zero status code. + * + * @generated from field: optional string error = 1; + */ + error?: string; + + /** + * A bitmask of supported features that the code generator supports. + * This is a bitwise "or" of values from the Feature enum. + * + * @generated from field: optional uint64 supported_features = 2; + */ + supportedFeatures?: bigint; + + /** + * @generated from field: repeated google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + */ + file: CodeGeneratorResponse_File[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorResponse"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorResponse; + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorResponse; + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorResponse; + + static equals(a: CodeGeneratorResponse | PlainMessage | undefined, b: CodeGeneratorResponse | PlainMessage | undefined): boolean; +} + +/** + * Sync with code_generator.h. + * + * @generated from enum google.protobuf.compiler.CodeGeneratorResponse.Feature + */ +export declare enum CodeGeneratorResponse_Feature { + /** + * @generated from enum value: FEATURE_NONE = 0; + */ + NONE = 0, + + /** + * @generated from enum value: FEATURE_PROTO3_OPTIONAL = 1; + */ + PROTO3_OPTIONAL = 1, +} + +/** + * Represents a single generated file. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse.File + */ +export declare class CodeGeneratorResponse_File extends Message { + /** + * The file name, relative to the output directory. The name must not + * contain "." or ".." components and must be relative, not be absolute (so, + * the file cannot lie outside the output directory). "/" must be used as + * the path separator, not "\". + * + * If the name is omitted, the content will be appended to the previous + * file. This allows the generator to break large files into small chunks, + * and allows the generated text to be streamed back to protoc so that large + * files need not reside completely in memory at one time. Note that as of + * this writing protoc does not optimize for this -- it will read the entire + * CodeGeneratorResponse before writing files to disk. + * + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * If non-empty, indicates that the named file should already exist, and the + * content here is to be inserted into that file at a defined insertion + * point. This feature allows a code generator to extend the output + * produced by another code generator. The original generator may provide + * insertion points by placing special annotations in the file that look + * like: + * @@protoc_insertion_point(NAME) + * The annotation can have arbitrary text before and after it on the line, + * which allows it to be placed in a comment. NAME should be replaced with + * an identifier naming the point -- this is what other generators will use + * as the insertion_point. Code inserted at this point will be placed + * immediately above the line containing the insertion point (thus multiple + * insertions to the same point will come out in the order they were added). + * The double-@ is intended to make it unlikely that the generated code + * could contain things that look like insertion points by accident. + * + * For example, the C++ code generator places the following line in the + * .pb.h files that it generates: + * // @@protoc_insertion_point(namespace_scope) + * This line appears within the scope of the file's package namespace, but + * outside of any particular class. Another plugin can then specify the + * insertion_point "namespace_scope" to generate additional classes or + * other declarations that should be placed in this scope. + * + * Note that if the line containing the insertion point begins with + * whitespace, the same whitespace will be added to every line of the + * inserted text. This is useful for languages like Python, where + * indentation matters. In these languages, the insertion point comment + * should be indented the same amount as any inserted code will need to be + * in order to work correctly in that context. + * + * The code generator that generates the initial file and the one which + * inserts into it must both run as part of a single invocation of protoc. + * Code generators are executed in the order in which they appear on the + * command line. + * + * If |insertion_point| is present, |name| must also be present. + * + * @generated from field: optional string insertion_point = 2; + */ + insertionPoint?: string; + + /** + * The file contents. + * + * @generated from field: optional string content = 15; + */ + content?: string; + + /** + * Information describing the file content being inserted. If an insertion + * point is used, this information will be appropriately offset and inserted + * into the code generation metadata for the generated files. + * + * @generated from field: optional google.protobuf.GeneratedCodeInfo generated_code_info = 16; + */ + generatedCodeInfo?: GeneratedCodeInfo; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorResponse.File"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorResponse_File; + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorResponse_File; + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorResponse_File; + + static equals(a: CodeGeneratorResponse_File | PlainMessage | undefined, b: CodeGeneratorResponse_File | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.js new file mode 100644 index 000000000..d564d8684 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/compiler/plugin_pb.js @@ -0,0 +1,126 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/compiler/plugin.proto (package google.protobuf.compiler, syntax proto2) +/* eslint-disable */ + +import {proto2} from "@bufbuild/protobuf"; +import {FileDescriptorProto, GeneratedCodeInfo} from "../descriptor_pb.js"; + +/** + * The version number of protocol compiler. + * + * @generated from message google.protobuf.compiler.Version + */ +export const Version = proto2.makeMessageType( + "google.protobuf.compiler.Version", + () => [ + { no: 1, name: "major", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "minor", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "patch", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "suffix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ], +); + +/** + * An encoded CodeGeneratorRequest is written to the plugin's stdin. + * + * @generated from message google.protobuf.compiler.CodeGeneratorRequest + */ +export const CodeGeneratorRequest = proto2.makeMessageType( + "google.protobuf.compiler.CodeGeneratorRequest", + () => [ + { no: 1, name: "file_to_generate", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 2, name: "parameter", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 15, name: "proto_file", kind: "message", T: FileDescriptorProto, repeated: true }, + { no: 3, name: "compiler_version", kind: "message", T: Version, opt: true }, + ], +); + +/** + * The plugin writes an encoded CodeGeneratorResponse to stdout. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse + */ +export const CodeGeneratorResponse = proto2.makeMessageType( + "google.protobuf.compiler.CodeGeneratorResponse", + () => [ + { no: 1, name: "error", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "supported_features", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 15, name: "file", kind: "message", T: CodeGeneratorResponse_File, repeated: true }, + ], +); + +/** + * Sync with code_generator.h. + * + * @generated from enum google.protobuf.compiler.CodeGeneratorResponse.Feature + */ +export const CodeGeneratorResponse_Feature = proto2.makeEnum( + "google.protobuf.compiler.CodeGeneratorResponse.Feature", + [ + {no: 0, name: "FEATURE_NONE", localName: "NONE"}, + {no: 1, name: "FEATURE_PROTO3_OPTIONAL", localName: "PROTO3_OPTIONAL"}, + ], +); + +/** + * Represents a single generated file. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse.File + */ +export const CodeGeneratorResponse_File = proto2.makeMessageType( + "google.protobuf.compiler.CodeGeneratorResponse.File", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "insertion_point", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 15, name: "content", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 16, name: "generated_code_info", kind: "message", T: GeneratedCodeInfo, opt: true }, + ], + {localName: "CodeGeneratorResponse_File"}, +); + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.d.ts new file mode 100644 index 000000000..9ac0d0df9 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.d.ts @@ -0,0 +1,1959 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/descriptor.proto (package google.protobuf, syntax proto2) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto2} from "@bufbuild/protobuf"; + +/** + * The protocol compiler can output a FileDescriptorSet containing the .proto + * files it parses. + * + * @generated from message google.protobuf.FileDescriptorSet + */ +export declare class FileDescriptorSet extends Message { + /** + * @generated from field: repeated google.protobuf.FileDescriptorProto file = 1; + */ + file: FileDescriptorProto[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.FileDescriptorSet"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FileDescriptorSet; + + static fromJson(jsonValue: JsonValue, options?: Partial): FileDescriptorSet; + + static fromJsonString(jsonString: string, options?: Partial): FileDescriptorSet; + + static equals(a: FileDescriptorSet | PlainMessage | undefined, b: FileDescriptorSet | PlainMessage | undefined): boolean; +} + +/** + * Describes a complete .proto file. + * + * @generated from message google.protobuf.FileDescriptorProto + */ +export declare class FileDescriptorProto extends Message { + /** + * file name, relative to root of source tree + * + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * e.g. "foo", "foo.bar", etc. + * + * @generated from field: optional string package = 2; + */ + package?: string; + + /** + * Names of files imported by this file. + * + * @generated from field: repeated string dependency = 3; + */ + dependency: string[]; + + /** + * Indexes of the public imported files in the dependency list above. + * + * @generated from field: repeated int32 public_dependency = 10; + */ + publicDependency: number[]; + + /** + * Indexes of the weak imported files in the dependency list. + * For Google-internal migration only. Do not use. + * + * @generated from field: repeated int32 weak_dependency = 11; + */ + weakDependency: number[]; + + /** + * All top-level definitions in this file. + * + * @generated from field: repeated google.protobuf.DescriptorProto message_type = 4; + */ + messageType: DescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.EnumDescriptorProto enum_type = 5; + */ + enumType: EnumDescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.ServiceDescriptorProto service = 6; + */ + service: ServiceDescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto extension = 7; + */ + extension: FieldDescriptorProto[]; + + /** + * @generated from field: optional google.protobuf.FileOptions options = 8; + */ + options?: FileOptions; + + /** + * This field contains optional information about the original source code. + * You may safely remove this entire field without harming runtime + * functionality of the descriptors -- the information is needed only by + * development tools. + * + * @generated from field: optional google.protobuf.SourceCodeInfo source_code_info = 9; + */ + sourceCodeInfo?: SourceCodeInfo; + + /** + * The syntax of the proto file. + * The supported values are "proto2" and "proto3". + * + * @generated from field: optional string syntax = 12; + */ + syntax?: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.FileDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FileDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): FileDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): FileDescriptorProto; + + static equals(a: FileDescriptorProto | PlainMessage | undefined, b: FileDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * Describes a message type. + * + * @generated from message google.protobuf.DescriptorProto + */ +export declare class DescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto field = 2; + */ + field: FieldDescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto extension = 6; + */ + extension: FieldDescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto nested_type = 3; + */ + nestedType: DescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.EnumDescriptorProto enum_type = 4; + */ + enumType: EnumDescriptorProto[]; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + extensionRange: DescriptorProto_ExtensionRange[]; + + /** + * @generated from field: repeated google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + oneofDecl: OneofDescriptorProto[]; + + /** + * @generated from field: optional google.protobuf.MessageOptions options = 7; + */ + options?: MessageOptions; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + reservedRange: DescriptorProto_ReservedRange[]; + + /** + * Reserved field names, which may not be used by fields in the same message. + * A given name may only be reserved once. + * + * @generated from field: repeated string reserved_name = 10; + */ + reservedName: string[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.DescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto; + + static equals(a: DescriptorProto | PlainMessage | undefined, b: DescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.DescriptorProto.ExtensionRange + */ +export declare class DescriptorProto_ExtensionRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Exclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + /** + * @generated from field: optional google.protobuf.ExtensionRangeOptions options = 3; + */ + options?: ExtensionRangeOptions; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.DescriptorProto.ExtensionRange"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto_ExtensionRange; + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto_ExtensionRange; + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto_ExtensionRange; + + static equals(a: DescriptorProto_ExtensionRange | PlainMessage | undefined, b: DescriptorProto_ExtensionRange | PlainMessage | undefined): boolean; +} + +/** + * Range of reserved tag numbers. Reserved tag numbers may not be used by + * fields or extension ranges in the same message. Reserved ranges may + * not overlap. + * + * @generated from message google.protobuf.DescriptorProto.ReservedRange + */ +export declare class DescriptorProto_ReservedRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Exclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.DescriptorProto.ReservedRange"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto_ReservedRange; + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto_ReservedRange; + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto_ReservedRange; + + static equals(a: DescriptorProto_ReservedRange | PlainMessage | undefined, b: DescriptorProto_ReservedRange | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.ExtensionRangeOptions + */ +export declare class ExtensionRangeOptions extends Message { + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.ExtensionRangeOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): ExtensionRangeOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): ExtensionRangeOptions; + + static fromJsonString(jsonString: string, options?: Partial): ExtensionRangeOptions; + + static equals(a: ExtensionRangeOptions | PlainMessage | undefined, b: ExtensionRangeOptions | PlainMessage | undefined): boolean; +} + +/** + * Describes a field within a message. + * + * @generated from message google.protobuf.FieldDescriptorProto + */ +export declare class FieldDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional int32 number = 3; + */ + number?: number; + + /** + * @generated from field: optional google.protobuf.FieldDescriptorProto.Label label = 4; + */ + label?: FieldDescriptorProto_Label; + + /** + * If type_name is set, this need not be set. If both this and type_name + * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + * + * @generated from field: optional google.protobuf.FieldDescriptorProto.Type type = 5; + */ + type?: FieldDescriptorProto_Type; + + /** + * For message and enum types, this is the name of the type. If the name + * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + * rules are used to find the type (i.e. first the nested types within this + * message are searched, then within the parent, on up to the root + * namespace). + * + * @generated from field: optional string type_name = 6; + */ + typeName?: string; + + /** + * For extensions, this is the name of the type being extended. It is + * resolved in the same manner as type_name. + * + * @generated from field: optional string extendee = 2; + */ + extendee?: string; + + /** + * For numeric types, contains the original text representation of the value. + * For booleans, "true" or "false". + * For strings, contains the default text contents (not escaped in any way). + * For bytes, contains the C escaped value. All bytes >= 128 are escaped. + * + * @generated from field: optional string default_value = 7; + */ + defaultValue?: string; + + /** + * If set, gives the index of a oneof in the containing type's oneof_decl + * list. This field is a member of that oneof. + * + * @generated from field: optional int32 oneof_index = 9; + */ + oneofIndex?: number; + + /** + * JSON name of this field. The value is set by protocol compiler. If the + * user has set a "json_name" option on this field, that option's value + * will be used. Otherwise, it's deduced from the field's name by converting + * it to camelCase. + * + * @generated from field: optional string json_name = 10; + */ + jsonName?: string; + + /** + * @generated from field: optional google.protobuf.FieldOptions options = 8; + */ + options?: FieldOptions; + + /** + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * + * @generated from field: optional bool proto3_optional = 17; + */ + proto3Optional?: boolean; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.FieldDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): FieldDescriptorProto; + + static equals(a: FieldDescriptorProto | PlainMessage | undefined, b: FieldDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Type + */ +export declare enum FieldDescriptorProto_Type { + /** + * 0 is reserved for errors. + * Order is weird for historical reasons. + * + * @generated from enum value: TYPE_DOUBLE = 1; + */ + DOUBLE = 1, + + /** + * @generated from enum value: TYPE_FLOAT = 2; + */ + FLOAT = 2, + + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + * negative values are likely. + * + * @generated from enum value: TYPE_INT64 = 3; + */ + INT64 = 3, + + /** + * @generated from enum value: TYPE_UINT64 = 4; + */ + UINT64 = 4, + + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + * negative values are likely. + * + * @generated from enum value: TYPE_INT32 = 5; + */ + INT32 = 5, + + /** + * @generated from enum value: TYPE_FIXED64 = 6; + */ + FIXED64 = 6, + + /** + * @generated from enum value: TYPE_FIXED32 = 7; + */ + FIXED32 = 7, + + /** + * @generated from enum value: TYPE_BOOL = 8; + */ + BOOL = 8, + + /** + * @generated from enum value: TYPE_STRING = 9; + */ + STRING = 9, + + /** + * Tag-delimited aggregate. + * Group type is deprecated and not supported in proto3. However, Proto3 + * implementations should still be able to parse the group wire format and + * treat group fields as unknown fields. + * + * @generated from enum value: TYPE_GROUP = 10; + */ + GROUP = 10, + + /** + * Length-delimited aggregate. + * + * @generated from enum value: TYPE_MESSAGE = 11; + */ + MESSAGE = 11, + + /** + * New in version 2. + * + * @generated from enum value: TYPE_BYTES = 12; + */ + BYTES = 12, + + /** + * @generated from enum value: TYPE_UINT32 = 13; + */ + UINT32 = 13, + + /** + * @generated from enum value: TYPE_ENUM = 14; + */ + ENUM = 14, + + /** + * @generated from enum value: TYPE_SFIXED32 = 15; + */ + SFIXED32 = 15, + + /** + * @generated from enum value: TYPE_SFIXED64 = 16; + */ + SFIXED64 = 16, + + /** + * Uses ZigZag encoding. + * + * @generated from enum value: TYPE_SINT32 = 17; + */ + SINT32 = 17, + + /** + * Uses ZigZag encoding. + * + * @generated from enum value: TYPE_SINT64 = 18; + */ + SINT64 = 18, +} + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Label + */ +export declare enum FieldDescriptorProto_Label { + /** + * 0 is reserved for errors + * + * @generated from enum value: LABEL_OPTIONAL = 1; + */ + OPTIONAL = 1, + + /** + * @generated from enum value: LABEL_REQUIRED = 2; + */ + REQUIRED = 2, + + /** + * @generated from enum value: LABEL_REPEATED = 3; + */ + REPEATED = 3, +} + +/** + * Describes a oneof. + * + * @generated from message google.protobuf.OneofDescriptorProto + */ +export declare class OneofDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional google.protobuf.OneofOptions options = 2; + */ + options?: OneofOptions; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.OneofDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): OneofDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): OneofDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): OneofDescriptorProto; + + static equals(a: OneofDescriptorProto | PlainMessage | undefined, b: OneofDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * Describes an enum type. + * + * @generated from message google.protobuf.EnumDescriptorProto + */ +export declare class EnumDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.EnumValueDescriptorProto value = 2; + */ + value: EnumValueDescriptorProto[]; + + /** + * @generated from field: optional google.protobuf.EnumOptions options = 3; + */ + options?: EnumOptions; + + /** + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * + * @generated from field: repeated google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + */ + reservedRange: EnumDescriptorProto_EnumReservedRange[]; + + /** + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * + * @generated from field: repeated string reserved_name = 5; + */ + reservedName: string[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.EnumDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): EnumDescriptorProto; + + static equals(a: EnumDescriptorProto | PlainMessage | undefined, b: EnumDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * Range of reserved numeric values. Reserved values may not be used by + * entries in the same enum. Reserved ranges may not overlap. + * + * Note that this is distinct from DescriptorProto.ReservedRange in that it + * is inclusive such that it can appropriately represent the entire int32 + * domain. + * + * @generated from message google.protobuf.EnumDescriptorProto.EnumReservedRange + */ +export declare class EnumDescriptorProto_EnumReservedRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Inclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.EnumDescriptorProto.EnumReservedRange"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumDescriptorProto_EnumReservedRange; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumDescriptorProto_EnumReservedRange; + + static fromJsonString(jsonString: string, options?: Partial): EnumDescriptorProto_EnumReservedRange; + + static equals(a: EnumDescriptorProto_EnumReservedRange | PlainMessage | undefined, b: EnumDescriptorProto_EnumReservedRange | PlainMessage | undefined): boolean; +} + +/** + * Describes a value within an enum. + * + * @generated from message google.protobuf.EnumValueDescriptorProto + */ +export declare class EnumValueDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional int32 number = 2; + */ + number?: number; + + /** + * @generated from field: optional google.protobuf.EnumValueOptions options = 3; + */ + options?: EnumValueOptions; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.EnumValueDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumValueDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumValueDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): EnumValueDescriptorProto; + + static equals(a: EnumValueDescriptorProto | PlainMessage | undefined, b: EnumValueDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * Describes a service. + * + * @generated from message google.protobuf.ServiceDescriptorProto + */ +export declare class ServiceDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.MethodDescriptorProto method = 2; + */ + method: MethodDescriptorProto[]; + + /** + * @generated from field: optional google.protobuf.ServiceOptions options = 3; + */ + options?: ServiceOptions; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.ServiceDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): ServiceDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): ServiceDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): ServiceDescriptorProto; + + static equals(a: ServiceDescriptorProto | PlainMessage | undefined, b: ServiceDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * Describes a method of a service. + * + * @generated from message google.protobuf.MethodDescriptorProto + */ +export declare class MethodDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * Input and output type names. These are resolved in the same way as + * FieldDescriptorProto.type_name, but must refer to a message type. + * + * @generated from field: optional string input_type = 2; + */ + inputType?: string; + + /** + * @generated from field: optional string output_type = 3; + */ + outputType?: string; + + /** + * @generated from field: optional google.protobuf.MethodOptions options = 4; + */ + options?: MethodOptions; + + /** + * Identifies if client streams multiple client messages + * + * @generated from field: optional bool client_streaming = 5 [default = false]; + */ + clientStreaming?: boolean; + + /** + * Identifies if server streams multiple server messages + * + * @generated from field: optional bool server_streaming = 6 [default = false]; + */ + serverStreaming?: boolean; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.MethodDescriptorProto"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): MethodDescriptorProto; + + static fromJson(jsonValue: JsonValue, options?: Partial): MethodDescriptorProto; + + static fromJsonString(jsonString: string, options?: Partial): MethodDescriptorProto; + + static equals(a: MethodDescriptorProto | PlainMessage | undefined, b: MethodDescriptorProto | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.FileOptions + */ +export declare class FileOptions extends Message { + /** + * Sets the Java package where classes generated from this .proto will be + * placed. By default, the proto package is used, but this is often + * inappropriate because proto packages do not normally start with backwards + * domain names. + * + * @generated from field: optional string java_package = 1; + */ + javaPackage?: string; + + /** + * Controls the name of the wrapper Java class generated for the .proto file. + * That class will always contain the .proto file's getDescriptor() method as + * well as any top-level extensions defined in the .proto file. + * If java_multiple_files is disabled, then all the other classes from the + * .proto file will be nested inside the single wrapper outer class. + * + * @generated from field: optional string java_outer_classname = 8; + */ + javaOuterClassname?: string; + + /** + * If enabled, then the Java code generator will generate a separate .java + * file for each top-level message, enum, and service defined in the .proto + * file. Thus, these types will *not* be nested inside the wrapper class + * named by java_outer_classname. However, the wrapper class will still be + * generated to contain the file's getDescriptor() method as well as any + * top-level extensions defined in the file. + * + * @generated from field: optional bool java_multiple_files = 10 [default = false]; + */ + javaMultipleFiles?: boolean; + + /** + * This option does nothing. + * + * @generated from field: optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + * @deprecated + */ + javaGenerateEqualsAndHash?: boolean; + + /** + * If set true, then the Java2 code generator will generate code that + * throws an exception whenever an attempt is made to assign a non-UTF-8 + * byte sequence to a string field. + * Message reflection will do the same. + * However, an extension field still accepts non-UTF-8 byte sequences. + * This option has no effect on when used with the lite runtime. + * + * @generated from field: optional bool java_string_check_utf8 = 27 [default = false]; + */ + javaStringCheckUtf8?: boolean; + + /** + * @generated from field: optional google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + */ + optimizeFor?: FileOptions_OptimizeMode; + + /** + * Sets the Go package where structs generated from this .proto will be + * placed. If omitted, the Go package will be derived from the following: + * - The basename of the package import path, if provided. + * - Otherwise, the package statement in the .proto file, if present. + * - Otherwise, the basename of the .proto file, without extension. + * + * @generated from field: optional string go_package = 11; + */ + goPackage?: string; + + /** + * Should generic services be generated in each language? "Generic" services + * are not specific to any particular RPC system. They are generated by the + * main code generators in each language (without additional plugins). + * Generic services were the only kind of service generation supported by + * early versions of google.protobuf. + * + * Generic services are now considered deprecated in favor of using plugins + * that generate code specific to your particular RPC system. Therefore, + * these default to false. Old code which depends on generic services should + * explicitly set them to true. + * + * @generated from field: optional bool cc_generic_services = 16 [default = false]; + */ + ccGenericServices?: boolean; + + /** + * @generated from field: optional bool java_generic_services = 17 [default = false]; + */ + javaGenericServices?: boolean; + + /** + * @generated from field: optional bool py_generic_services = 18 [default = false]; + */ + pyGenericServices?: boolean; + + /** + * @generated from field: optional bool php_generic_services = 42 [default = false]; + */ + phpGenericServices?: boolean; + + /** + * Is this file deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for everything in the file, or it will be completely ignored; in the very + * least, this is a formalization for deprecating files. + * + * @generated from field: optional bool deprecated = 23 [default = false]; + */ + deprecated?: boolean; + + /** + * Enables the use of arenas for the proto messages in this file. This applies + * only to generated classes for C++. + * + * @generated from field: optional bool cc_enable_arenas = 31 [default = true]; + */ + ccEnableArenas?: boolean; + + /** + * Sets the objective c class prefix which is prepended to all objective c + * generated classes from this .proto. There is no default. + * + * @generated from field: optional string objc_class_prefix = 36; + */ + objcClassPrefix?: string; + + /** + * Namespace for generated classes; defaults to the package. + * + * @generated from field: optional string csharp_namespace = 37; + */ + csharpNamespace?: string; + + /** + * By default Swift generators will take the proto package and CamelCase it + * replacing '.' with underscore and use that to prefix the types/symbols + * defined. When this options is provided, they will use this value instead + * to prefix the types/symbols defined. + * + * @generated from field: optional string swift_prefix = 39; + */ + swiftPrefix?: string; + + /** + * Sets the php class prefix which is prepended to all php generated classes + * from this .proto. Default is empty. + * + * @generated from field: optional string php_class_prefix = 40; + */ + phpClassPrefix?: string; + + /** + * Use this option to change the namespace of php generated classes. Default + * is empty. When this option is empty, the package name will be used for + * determining the namespace. + * + * @generated from field: optional string php_namespace = 41; + */ + phpNamespace?: string; + + /** + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * + * @generated from field: optional string php_metadata_namespace = 44; + */ + phpMetadataNamespace?: string; + + /** + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * + * @generated from field: optional string ruby_package = 45; + */ + rubyPackage?: string; + + /** + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.FileOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FileOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): FileOptions; + + static fromJsonString(jsonString: string, options?: Partial): FileOptions; + + static equals(a: FileOptions | PlainMessage | undefined, b: FileOptions | PlainMessage | undefined): boolean; +} + +/** + * Generated classes can be optimized for speed or code size. + * + * @generated from enum google.protobuf.FileOptions.OptimizeMode + */ +export declare enum FileOptions_OptimizeMode { + /** + * Generate complete code for parsing, serialization, + * + * @generated from enum value: SPEED = 1; + */ + SPEED = 1, + + /** + * etc. + * + * Use ReflectionOps to implement these methods. + * + * @generated from enum value: CODE_SIZE = 2; + */ + CODE_SIZE = 2, + + /** + * Generate code using MessageLite and the lite runtime. + * + * @generated from enum value: LITE_RUNTIME = 3; + */ + LITE_RUNTIME = 3, +} + +/** + * @generated from message google.protobuf.MessageOptions + */ +export declare class MessageOptions extends Message { + /** + * Set true to use the old proto1 MessageSet wire format for extensions. + * This is provided for backwards-compatibility with the MessageSet wire + * format. You should not use this for any other reason: It's less + * efficient, has fewer features, and is more complicated. + * + * The message must be defined exactly as follows: + * message Foo { + * option message_set_wire_format = true; + * extensions 4 to max; + * } + * Note that the message cannot have any defined fields; MessageSets only + * have extensions. + * + * All extensions of your type must be singular messages; e.g. they cannot + * be int32s, enums, or repeated messages. + * + * Because this is an option, the above two restrictions are not enforced by + * the protocol compiler. + * + * @generated from field: optional bool message_set_wire_format = 1 [default = false]; + */ + messageSetWireFormat?: boolean; + + /** + * Disables the generation of the standard "descriptor()" accessor, which can + * conflict with a field of the same name. This is meant to make migration + * from proto1 easier; new code should avoid fields named "descriptor". + * + * @generated from field: optional bool no_standard_descriptor_accessor = 2 [default = false]; + */ + noStandardDescriptorAccessor?: boolean; + + /** + * Is this message deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the message, or it will be completely ignored; in the very least, + * this is a formalization for deprecating messages. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * Whether the message is an automatically generated map entry type for the + * maps field. + * + * For maps fields: + * map map_field = 1; + * The parsed descriptor looks like: + * message MapFieldEntry { + * option map_entry = true; + * optional KeyType key = 1; + * optional ValueType value = 2; + * } + * repeated MapFieldEntry map_field = 1; + * + * Implementations may choose not to generate the map_entry=true message, but + * use a native map in the target language to hold the keys and values. + * The reflection APIs in such implementations still need to work as + * if the field is a repeated message field. + * + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. + * + * @generated from field: optional bool map_entry = 7; + */ + mapEntry?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.MessageOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): MessageOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): MessageOptions; + + static fromJsonString(jsonString: string, options?: Partial): MessageOptions; + + static equals(a: MessageOptions | PlainMessage | undefined, b: MessageOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.FieldOptions + */ +export declare class FieldOptions extends Message { + /** + * The ctype option instructs the C++ code generator to use a different + * representation of the field than it normally would. See the specific + * options below. This option is not yet implemented in the open source + * release -- sorry, we'll try to include it in a future version! + * + * @generated from field: optional google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + */ + ctype?: FieldOptions_CType; + + /** + * The packed option can be enabled for repeated primitive fields to enable + * a more efficient representation on the wire. Rather than repeatedly + * writing the tag and type for each element, the entire array is encoded as + * a single length-delimited blob. In proto3, only explicit setting it to + * false will avoid using packed encoding. + * + * @generated from field: optional bool packed = 2; + */ + packed?: boolean; + + /** + * The jstype option determines the JavaScript type used for values of the + * field. The option is permitted only for 64 bit integral and fixed types + * (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + * is represented as JavaScript string, which avoids loss of precision that + * can happen when a large value is converted to a floating point JavaScript. + * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + * use the JavaScript "number" type. The behavior of the default option + * JS_NORMAL is implementation dependent. + * + * This option is an enum to permit additional types to be added, e.g. + * goog.math.Integer. + * + * @generated from field: optional google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + */ + jstype?: FieldOptions_JSType; + + /** + * Should this field be parsed lazily? Lazy applies only to message-type + * fields. It means that when the outer message is initially parsed, the + * inner message's contents will not be parsed but instead stored in encoded + * form. The inner message will actually be parsed when it is first accessed. + * + * This is only a hint. Implementations are free to choose whether to use + * eager or lazy parsing regardless of the value of this option. However, + * setting this option true suggests that the protocol author believes that + * using lazy parsing on this field is worth the additional bookkeeping + * overhead typically needed to implement it. + * + * This option does not affect the public interface of any generated code; + * all method signatures remain the same. Furthermore, thread-safety of the + * interface is not affected by this option; const methods remain safe to + * call from multiple threads concurrently, while non-const methods continue + * to require exclusive access. + * + * + * Note that implementations may choose not to check required fields within + * a lazy sub-message. That is, calling IsInitialized() on the outer message + * may return true even if the inner message has missing required fields. + * This is necessary because otherwise the inner message would have to be + * parsed in order to perform the check, defeating the purpose of lazy + * parsing. An implementation which chooses not to check required fields + * must be consistent about it. That is, for any particular sub-message, the + * implementation must either *always* check its required fields, or *never* + * check its required fields, regardless of whether or not the message has + * been parsed. + * + * As of 2021, lazy does no correctness checks on the byte stream during + * parsing. This may lead to crashes if and when an invalid byte stream is + * finally parsed upon access. + * + * TODO(b/211906113): Enable validation on lazy fields. + * + * @generated from field: optional bool lazy = 5 [default = false]; + */ + lazy?: boolean; + + /** + * unverified_lazy does no correctness checks on the byte stream. This should + * only be used where lazy with verification is prohibitive for performance + * reasons. + * + * @generated from field: optional bool unverified_lazy = 15 [default = false]; + */ + unverifiedLazy?: boolean; + + /** + * Is this field deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for accessors, or it will be completely ignored; in the very least, this + * is a formalization for deprecating fields. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * For Google-internal migration only. Do not use. + * + * @generated from field: optional bool weak = 10 [default = false]; + */ + weak?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.FieldOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldOptions; + + static fromJsonString(jsonString: string, options?: Partial): FieldOptions; + + static equals(a: FieldOptions | PlainMessage | undefined, b: FieldOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from enum google.protobuf.FieldOptions.CType + */ +export declare enum FieldOptions_CType { + /** + * Default mode. + * + * @generated from enum value: STRING = 0; + */ + STRING = 0, + + /** + * @generated from enum value: CORD = 1; + */ + CORD = 1, + + /** + * @generated from enum value: STRING_PIECE = 2; + */ + STRING_PIECE = 2, +} + +/** + * @generated from enum google.protobuf.FieldOptions.JSType + */ +export declare enum FieldOptions_JSType { + /** + * Use the default type. + * + * @generated from enum value: JS_NORMAL = 0; + */ + JS_NORMAL = 0, + + /** + * Use JavaScript strings. + * + * @generated from enum value: JS_STRING = 1; + */ + JS_STRING = 1, + + /** + * Use JavaScript numbers. + * + * @generated from enum value: JS_NUMBER = 2; + */ + JS_NUMBER = 2, +} + +/** + * @generated from message google.protobuf.OneofOptions + */ +export declare class OneofOptions extends Message { + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.OneofOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): OneofOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): OneofOptions; + + static fromJsonString(jsonString: string, options?: Partial): OneofOptions; + + static equals(a: OneofOptions | PlainMessage | undefined, b: OneofOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.EnumOptions + */ +export declare class EnumOptions extends Message { + /** + * Set this option to true to allow mapping different tag names to the same + * value. + * + * @generated from field: optional bool allow_alias = 2; + */ + allowAlias?: boolean; + + /** + * Is this enum deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum, or it will be completely ignored; in the very least, this + * is a formalization for deprecating enums. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.EnumOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumOptions; + + static fromJsonString(jsonString: string, options?: Partial): EnumOptions; + + static equals(a: EnumOptions | PlainMessage | undefined, b: EnumOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.EnumValueOptions + */ +export declare class EnumValueOptions extends Message { + /** + * Is this enum value deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum value, or it will be completely ignored; in the very least, + * this is a formalization for deprecating enum values. + * + * @generated from field: optional bool deprecated = 1 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.EnumValueOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumValueOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumValueOptions; + + static fromJsonString(jsonString: string, options?: Partial): EnumValueOptions; + + static equals(a: EnumValueOptions | PlainMessage | undefined, b: EnumValueOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.ServiceOptions + */ +export declare class ServiceOptions extends Message { + /** + * Is this service deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the service, or it will be completely ignored; in the very least, + * this is a formalization for deprecating services. + * + * @generated from field: optional bool deprecated = 33 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.ServiceOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): ServiceOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): ServiceOptions; + + static fromJsonString(jsonString: string, options?: Partial): ServiceOptions; + + static equals(a: ServiceOptions | PlainMessage | undefined, b: ServiceOptions | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.MethodOptions + */ +export declare class MethodOptions extends Message { + /** + * Is this method deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the method, or it will be completely ignored; in the very least, + * this is a formalization for deprecating methods. + * + * @generated from field: optional bool deprecated = 33 [default = false]; + */ + deprecated?: boolean; + + /** + * @generated from field: optional google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + */ + idempotencyLevel?: MethodOptions_IdempotencyLevel; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.MethodOptions"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): MethodOptions; + + static fromJson(jsonValue: JsonValue, options?: Partial): MethodOptions; + + static fromJsonString(jsonString: string, options?: Partial): MethodOptions; + + static equals(a: MethodOptions | PlainMessage | undefined, b: MethodOptions | PlainMessage | undefined): boolean; +} + +/** + * Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + * or neither? HTTP based RPC implementation may choose GET verb for safe + * methods, and PUT verb for idempotent methods instead of the default POST. + * + * @generated from enum google.protobuf.MethodOptions.IdempotencyLevel + */ +export declare enum MethodOptions_IdempotencyLevel { + /** + * @generated from enum value: IDEMPOTENCY_UNKNOWN = 0; + */ + IDEMPOTENCY_UNKNOWN = 0, + + /** + * implies idempotent + * + * @generated from enum value: NO_SIDE_EFFECTS = 1; + */ + NO_SIDE_EFFECTS = 1, + + /** + * idempotent, but may have side effects + * + * @generated from enum value: IDEMPOTENT = 2; + */ + IDEMPOTENT = 2, +} + +/** + * A message representing a option the parser does not recognize. This only + * appears in options protos created by the compiler::Parser class. + * DescriptorPool resolves these when building Descriptor objects. Therefore, + * options protos in descriptor objects (e.g. returned by Descriptor::options(), + * or produced by Descriptor::CopyTo()) will never have UninterpretedOptions + * in them. + * + * @generated from message google.protobuf.UninterpretedOption + */ +export declare class UninterpretedOption extends Message { + /** + * @generated from field: repeated google.protobuf.UninterpretedOption.NamePart name = 2; + */ + name: UninterpretedOption_NamePart[]; + + /** + * The value of the uninterpreted option, in whatever type the tokenizer + * identified it as during parsing. Exactly one of these should be set. + * + * @generated from field: optional string identifier_value = 3; + */ + identifierValue?: string; + + /** + * @generated from field: optional uint64 positive_int_value = 4; + */ + positiveIntValue?: bigint; + + /** + * @generated from field: optional int64 negative_int_value = 5; + */ + negativeIntValue?: bigint; + + /** + * @generated from field: optional double double_value = 6; + */ + doubleValue?: number; + + /** + * @generated from field: optional bytes string_value = 7; + */ + stringValue?: Uint8Array; + + /** + * @generated from field: optional string aggregate_value = 8; + */ + aggregateValue?: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.UninterpretedOption"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): UninterpretedOption; + + static fromJson(jsonValue: JsonValue, options?: Partial): UninterpretedOption; + + static fromJsonString(jsonString: string, options?: Partial): UninterpretedOption; + + static equals(a: UninterpretedOption | PlainMessage | undefined, b: UninterpretedOption | PlainMessage | undefined): boolean; +} + +/** + * The name of the uninterpreted option. Each string represents a segment in + * a dot-separated name. is_extension is true iff a segment represents an + * extension (denoted with parentheses in options specs in .proto files). + * E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + * "foo.(bar.baz).qux". + * + * @generated from message google.protobuf.UninterpretedOption.NamePart + */ +export declare class UninterpretedOption_NamePart extends Message { + /** + * @generated from field: required string name_part = 1; + */ + namePart: string; + + /** + * @generated from field: required bool is_extension = 2; + */ + isExtension: boolean; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.UninterpretedOption.NamePart"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): UninterpretedOption_NamePart; + + static fromJson(jsonValue: JsonValue, options?: Partial): UninterpretedOption_NamePart; + + static fromJsonString(jsonString: string, options?: Partial): UninterpretedOption_NamePart; + + static equals(a: UninterpretedOption_NamePart | PlainMessage | undefined, b: UninterpretedOption_NamePart | PlainMessage | undefined): boolean; +} + +/** + * Encapsulates information about the original source file from which a + * FileDescriptorProto was generated. + * + * @generated from message google.protobuf.SourceCodeInfo + */ +export declare class SourceCodeInfo extends Message { + /** + * A Location identifies a piece of source code in a .proto file which + * corresponds to a particular definition. This information is intended + * to be useful to IDEs, code indexers, documentation generators, and similar + * tools. + * + * For example, say we have a file like: + * message Foo { + * optional string foo = 1; + * } + * Let's look at just the field definition: + * optional string foo = 1; + * ^ ^^ ^^ ^ ^^^ + * a bc de f ghi + * We have the following locations: + * span path represents + * [a,i) [ 4, 0, 2, 0 ] The whole field definition. + * [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + * [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + * [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + * [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + * + * Notes: + * - A location may refer to a repeated field itself (i.e. not to any + * particular index within it). This is used whenever a set of elements are + * logically enclosed in a single code segment. For example, an entire + * extend block (possibly containing multiple extension definitions) will + * have an outer location whose path refers to the "extensions" repeated + * field without an index. + * - Multiple locations may have the same path. This happens when a single + * logical declaration is spread out across multiple places. The most + * obvious example is the "extend" block again -- there may be multiple + * extend blocks in the same scope, each of which will have the same path. + * - A location's span is not always a subset of its parent's span. For + * example, the "extendee" of an extension declaration appears at the + * beginning of the "extend" block and is shared by all extensions within + * the block. + * - Just because a location's span is a subset of some other location's span + * does not mean that it is a descendant. For example, a "group" defines + * both a type and a field in a single declaration. Thus, the locations + * corresponding to the type and field and their components will overlap. + * - Code which tries to interpret locations should probably be designed to + * ignore those that it doesn't understand, as more types of locations could + * be recorded in the future. + * + * @generated from field: repeated google.protobuf.SourceCodeInfo.Location location = 1; + */ + location: SourceCodeInfo_Location[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.SourceCodeInfo"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceCodeInfo; + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceCodeInfo; + + static fromJsonString(jsonString: string, options?: Partial): SourceCodeInfo; + + static equals(a: SourceCodeInfo | PlainMessage | undefined, b: SourceCodeInfo | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.SourceCodeInfo.Location + */ +export declare class SourceCodeInfo_Location extends Message { + /** + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition occurs. + * For example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * + * @generated from field: repeated int32 path = 1 [packed = true]; + */ + path: number[]; + + /** + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * + * @generated from field: repeated int32 span = 2 [packed = true]; + */ + span: number[]; + + /** + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * + * Examples: + * + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * + * // Detached comment for corge paragraph 2. + * + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. *\/ + * /* Block comment attached to + * * grault. *\/ + * optional int32 grault = 6; + * + * // ignored detached comments. + * + * @generated from field: optional string leading_comments = 3; + */ + leadingComments?: string; + + /** + * @generated from field: optional string trailing_comments = 4; + */ + trailingComments?: string; + + /** + * @generated from field: repeated string leading_detached_comments = 6; + */ + leadingDetachedComments: string[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.SourceCodeInfo.Location"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceCodeInfo_Location; + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceCodeInfo_Location; + + static fromJsonString(jsonString: string, options?: Partial): SourceCodeInfo_Location; + + static equals(a: SourceCodeInfo_Location | PlainMessage | undefined, b: SourceCodeInfo_Location | PlainMessage | undefined): boolean; +} + +/** + * Describes the relationship between generated code and its original source + * file. A GeneratedCodeInfo message is associated with only one generated + * source file, but may contain references to different source .proto files. + * + * @generated from message google.protobuf.GeneratedCodeInfo + */ +export declare class GeneratedCodeInfo extends Message { + /** + * An Annotation connects some span of text in generated code to an element + * of its generating .proto file. + * + * @generated from field: repeated google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + */ + annotation: GeneratedCodeInfo_Annotation[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.GeneratedCodeInfo"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): GeneratedCodeInfo; + + static fromJson(jsonValue: JsonValue, options?: Partial): GeneratedCodeInfo; + + static fromJsonString(jsonString: string, options?: Partial): GeneratedCodeInfo; + + static equals(a: GeneratedCodeInfo | PlainMessage | undefined, b: GeneratedCodeInfo | PlainMessage | undefined): boolean; +} + +/** + * @generated from message google.protobuf.GeneratedCodeInfo.Annotation + */ +export declare class GeneratedCodeInfo_Annotation extends Message { + /** + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * + * @generated from field: repeated int32 path = 1 [packed = true]; + */ + path: number[]; + + /** + * Identifies the filesystem path to the original source .proto. + * + * @generated from field: optional string source_file = 2; + */ + sourceFile?: string; + + /** + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * + * @generated from field: optional int32 begin = 3; + */ + begin?: number; + + /** + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * + * @generated from field: optional int32 end = 4; + */ + end?: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto2; + static readonly typeName = "google.protobuf.GeneratedCodeInfo.Annotation"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): GeneratedCodeInfo_Annotation; + + static fromJson(jsonValue: JsonValue, options?: Partial): GeneratedCodeInfo_Annotation; + + static fromJsonString(jsonString: string, options?: Partial): GeneratedCodeInfo_Annotation; + + static equals(a: GeneratedCodeInfo_Annotation | PlainMessage | undefined, b: GeneratedCodeInfo_Annotation | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.js new file mode 100644 index 000000000..f7fb1622d --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/descriptor_pb.js @@ -0,0 +1,562 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/descriptor.proto (package google.protobuf, syntax proto2) +/* eslint-disable */ + +import {proto2} from "@bufbuild/protobuf"; + +/** + * The protocol compiler can output a FileDescriptorSet containing the .proto + * files it parses. + * + * @generated from message google.protobuf.FileDescriptorSet + */ +export const FileDescriptorSet = proto2.makeMessageType( + "google.protobuf.FileDescriptorSet", + () => [ + { no: 1, name: "file", kind: "message", T: FileDescriptorProto, repeated: true }, + ], +); + +/** + * Describes a complete .proto file. + * + * @generated from message google.protobuf.FileDescriptorProto + */ +export const FileDescriptorProto = proto2.makeMessageType( + "google.protobuf.FileDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "dependency", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 10, name: "public_dependency", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 11, name: "weak_dependency", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 4, name: "message_type", kind: "message", T: DescriptorProto, repeated: true }, + { no: 5, name: "enum_type", kind: "message", T: EnumDescriptorProto, repeated: true }, + { no: 6, name: "service", kind: "message", T: ServiceDescriptorProto, repeated: true }, + { no: 7, name: "extension", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 8, name: "options", kind: "message", T: FileOptions, opt: true }, + { no: 9, name: "source_code_info", kind: "message", T: SourceCodeInfo, opt: true }, + { no: 12, name: "syntax", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ], +); + +/** + * Describes a message type. + * + * @generated from message google.protobuf.DescriptorProto + */ +export const DescriptorProto = proto2.makeMessageType( + "google.protobuf.DescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "field", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 6, name: "extension", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 3, name: "nested_type", kind: "message", T: DescriptorProto, repeated: true }, + { no: 4, name: "enum_type", kind: "message", T: EnumDescriptorProto, repeated: true }, + { no: 5, name: "extension_range", kind: "message", T: DescriptorProto_ExtensionRange, repeated: true }, + { no: 8, name: "oneof_decl", kind: "message", T: OneofDescriptorProto, repeated: true }, + { no: 7, name: "options", kind: "message", T: MessageOptions, opt: true }, + { no: 9, name: "reserved_range", kind: "message", T: DescriptorProto_ReservedRange, repeated: true }, + { no: 10, name: "reserved_name", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.DescriptorProto.ExtensionRange + */ +export const DescriptorProto_ExtensionRange = proto2.makeMessageType( + "google.protobuf.DescriptorProto.ExtensionRange", + () => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "options", kind: "message", T: ExtensionRangeOptions, opt: true }, + ], + {localName: "DescriptorProto_ExtensionRange"}, +); + +/** + * Range of reserved tag numbers. Reserved tag numbers may not be used by + * fields or extension ranges in the same message. Reserved ranges may + * not overlap. + * + * @generated from message google.protobuf.DescriptorProto.ReservedRange + */ +export const DescriptorProto_ReservedRange = proto2.makeMessageType( + "google.protobuf.DescriptorProto.ReservedRange", + () => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ], + {localName: "DescriptorProto_ReservedRange"}, +); + +/** + * @generated from message google.protobuf.ExtensionRangeOptions + */ +export const ExtensionRangeOptions = proto2.makeMessageType( + "google.protobuf.ExtensionRangeOptions", + () => [ + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * Describes a field within a message. + * + * @generated from message google.protobuf.FieldDescriptorProto + */ +export const FieldDescriptorProto = proto2.makeMessageType( + "google.protobuf.FieldDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "number", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "label", kind: "enum", T: proto2.getEnumType(FieldDescriptorProto_Label), opt: true }, + { no: 5, name: "type", kind: "enum", T: proto2.getEnumType(FieldDescriptorProto_Type), opt: true }, + { no: 6, name: "type_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "extendee", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 7, name: "default_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 9, name: "oneof_index", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 10, name: "json_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 8, name: "options", kind: "message", T: FieldOptions, opt: true }, + { no: 17, name: "proto3_optional", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ], +); + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Type + */ +export const FieldDescriptorProto_Type = proto2.makeEnum( + "google.protobuf.FieldDescriptorProto.Type", + [ + {no: 1, name: "TYPE_DOUBLE", localName: "DOUBLE"}, + {no: 2, name: "TYPE_FLOAT", localName: "FLOAT"}, + {no: 3, name: "TYPE_INT64", localName: "INT64"}, + {no: 4, name: "TYPE_UINT64", localName: "UINT64"}, + {no: 5, name: "TYPE_INT32", localName: "INT32"}, + {no: 6, name: "TYPE_FIXED64", localName: "FIXED64"}, + {no: 7, name: "TYPE_FIXED32", localName: "FIXED32"}, + {no: 8, name: "TYPE_BOOL", localName: "BOOL"}, + {no: 9, name: "TYPE_STRING", localName: "STRING"}, + {no: 10, name: "TYPE_GROUP", localName: "GROUP"}, + {no: 11, name: "TYPE_MESSAGE", localName: "MESSAGE"}, + {no: 12, name: "TYPE_BYTES", localName: "BYTES"}, + {no: 13, name: "TYPE_UINT32", localName: "UINT32"}, + {no: 14, name: "TYPE_ENUM", localName: "ENUM"}, + {no: 15, name: "TYPE_SFIXED32", localName: "SFIXED32"}, + {no: 16, name: "TYPE_SFIXED64", localName: "SFIXED64"}, + {no: 17, name: "TYPE_SINT32", localName: "SINT32"}, + {no: 18, name: "TYPE_SINT64", localName: "SINT64"}, + ], +); + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Label + */ +export const FieldDescriptorProto_Label = proto2.makeEnum( + "google.protobuf.FieldDescriptorProto.Label", + [ + {no: 1, name: "LABEL_OPTIONAL", localName: "OPTIONAL"}, + {no: 2, name: "LABEL_REQUIRED", localName: "REQUIRED"}, + {no: 3, name: "LABEL_REPEATED", localName: "REPEATED"}, + ], +); + +/** + * Describes a oneof. + * + * @generated from message google.protobuf.OneofDescriptorProto + */ +export const OneofDescriptorProto = proto2.makeMessageType( + "google.protobuf.OneofDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "options", kind: "message", T: OneofOptions, opt: true }, + ], +); + +/** + * Describes an enum type. + * + * @generated from message google.protobuf.EnumDescriptorProto + */ +export const EnumDescriptorProto = proto2.makeMessageType( + "google.protobuf.EnumDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "value", kind: "message", T: EnumValueDescriptorProto, repeated: true }, + { no: 3, name: "options", kind: "message", T: EnumOptions, opt: true }, + { no: 4, name: "reserved_range", kind: "message", T: EnumDescriptorProto_EnumReservedRange, repeated: true }, + { no: 5, name: "reserved_name", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ], +); + +/** + * Range of reserved numeric values. Reserved values may not be used by + * entries in the same enum. Reserved ranges may not overlap. + * + * Note that this is distinct from DescriptorProto.ReservedRange in that it + * is inclusive such that it can appropriately represent the entire int32 + * domain. + * + * @generated from message google.protobuf.EnumDescriptorProto.EnumReservedRange + */ +export const EnumDescriptorProto_EnumReservedRange = proto2.makeMessageType( + "google.protobuf.EnumDescriptorProto.EnumReservedRange", + () => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ], + {localName: "EnumDescriptorProto_EnumReservedRange"}, +); + +/** + * Describes a value within an enum. + * + * @generated from message google.protobuf.EnumValueDescriptorProto + */ +export const EnumValueDescriptorProto = proto2.makeMessageType( + "google.protobuf.EnumValueDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "number", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "options", kind: "message", T: EnumValueOptions, opt: true }, + ], +); + +/** + * Describes a service. + * + * @generated from message google.protobuf.ServiceDescriptorProto + */ +export const ServiceDescriptorProto = proto2.makeMessageType( + "google.protobuf.ServiceDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "method", kind: "message", T: MethodDescriptorProto, repeated: true }, + { no: 3, name: "options", kind: "message", T: ServiceOptions, opt: true }, + ], +); + +/** + * Describes a method of a service. + * + * @generated from message google.protobuf.MethodDescriptorProto + */ +export const MethodDescriptorProto = proto2.makeMessageType( + "google.protobuf.MethodDescriptorProto", + () => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "input_type", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "output_type", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "options", kind: "message", T: MethodOptions, opt: true }, + { no: 5, name: "client_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 6, name: "server_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + ], +); + +/** + * @generated from message google.protobuf.FileOptions + */ +export const FileOptions = proto2.makeMessageType( + "google.protobuf.FileOptions", + () => [ + { no: 1, name: "java_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 8, name: "java_outer_classname", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 10, name: "java_multiple_files", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 20, name: "java_generate_equals_and_hash", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 27, name: "java_string_check_utf8", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 9, name: "optimize_for", kind: "enum", T: proto2.getEnumType(FileOptions_OptimizeMode), opt: true, default: FileOptions_OptimizeMode.SPEED }, + { no: 11, name: "go_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 16, name: "cc_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 17, name: "java_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 18, name: "py_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 42, name: "php_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 23, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 31, name: "cc_enable_arenas", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, + { no: 36, name: "objc_class_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 37, name: "csharp_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 39, name: "swift_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 40, name: "php_class_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 41, name: "php_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 44, name: "php_metadata_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 45, name: "ruby_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * Generated classes can be optimized for speed or code size. + * + * @generated from enum google.protobuf.FileOptions.OptimizeMode + */ +export const FileOptions_OptimizeMode = proto2.makeEnum( + "google.protobuf.FileOptions.OptimizeMode", + [ + {no: 1, name: "SPEED"}, + {no: 2, name: "CODE_SIZE"}, + {no: 3, name: "LITE_RUNTIME"}, + ], +); + +/** + * @generated from message google.protobuf.MessageOptions + */ +export const MessageOptions = proto2.makeMessageType( + "google.protobuf.MessageOptions", + () => [ + { no: 1, name: "message_set_wire_format", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 2, name: "no_standard_descriptor_accessor", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 7, name: "map_entry", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.FieldOptions + */ +export const FieldOptions = proto2.makeMessageType( + "google.protobuf.FieldOptions", + () => [ + { no: 1, name: "ctype", kind: "enum", T: proto2.getEnumType(FieldOptions_CType), opt: true, default: FieldOptions_CType.STRING }, + { no: 2, name: "packed", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 6, name: "jstype", kind: "enum", T: proto2.getEnumType(FieldOptions_JSType), opt: true, default: FieldOptions_JSType.JS_NORMAL }, + { no: 5, name: "lazy", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 15, name: "unverified_lazy", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 10, name: "weak", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from enum google.protobuf.FieldOptions.CType + */ +export const FieldOptions_CType = proto2.makeEnum( + "google.protobuf.FieldOptions.CType", + [ + {no: 0, name: "STRING"}, + {no: 1, name: "CORD"}, + {no: 2, name: "STRING_PIECE"}, + ], +); + +/** + * @generated from enum google.protobuf.FieldOptions.JSType + */ +export const FieldOptions_JSType = proto2.makeEnum( + "google.protobuf.FieldOptions.JSType", + [ + {no: 0, name: "JS_NORMAL"}, + {no: 1, name: "JS_STRING"}, + {no: 2, name: "JS_NUMBER"}, + ], +); + +/** + * @generated from message google.protobuf.OneofOptions + */ +export const OneofOptions = proto2.makeMessageType( + "google.protobuf.OneofOptions", + () => [ + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.EnumOptions + */ +export const EnumOptions = proto2.makeMessageType( + "google.protobuf.EnumOptions", + () => [ + { no: 2, name: "allow_alias", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.EnumValueOptions + */ +export const EnumValueOptions = proto2.makeMessageType( + "google.protobuf.EnumValueOptions", + () => [ + { no: 1, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.ServiceOptions + */ +export const ServiceOptions = proto2.makeMessageType( + "google.protobuf.ServiceOptions", + () => [ + { no: 33, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.MethodOptions + */ +export const MethodOptions = proto2.makeMessageType( + "google.protobuf.MethodOptions", + () => [ + { no: 33, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 34, name: "idempotency_level", kind: "enum", T: proto2.getEnumType(MethodOptions_IdempotencyLevel), opt: true, default: MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ], +); + +/** + * Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + * or neither? HTTP based RPC implementation may choose GET verb for safe + * methods, and PUT verb for idempotent methods instead of the default POST. + * + * @generated from enum google.protobuf.MethodOptions.IdempotencyLevel + */ +export const MethodOptions_IdempotencyLevel = proto2.makeEnum( + "google.protobuf.MethodOptions.IdempotencyLevel", + [ + {no: 0, name: "IDEMPOTENCY_UNKNOWN"}, + {no: 1, name: "NO_SIDE_EFFECTS"}, + {no: 2, name: "IDEMPOTENT"}, + ], +); + +/** + * A message representing a option the parser does not recognize. This only + * appears in options protos created by the compiler::Parser class. + * DescriptorPool resolves these when building Descriptor objects. Therefore, + * options protos in descriptor objects (e.g. returned by Descriptor::options(), + * or produced by Descriptor::CopyTo()) will never have UninterpretedOptions + * in them. + * + * @generated from message google.protobuf.UninterpretedOption + */ +export const UninterpretedOption = proto2.makeMessageType( + "google.protobuf.UninterpretedOption", + () => [ + { no: 2, name: "name", kind: "message", T: UninterpretedOption_NamePart, repeated: true }, + { no: 3, name: "identifier_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "positive_int_value", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 5, name: "negative_int_value", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 6, name: "double_value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 7, name: "string_value", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 8, name: "aggregate_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ], +); + +/** + * The name of the uninterpreted option. Each string represents a segment in + * a dot-separated name. is_extension is true iff a segment represents an + * extension (denoted with parentheses in options specs in .proto files). + * E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + * "foo.(bar.baz).qux". + * + * @generated from message google.protobuf.UninterpretedOption.NamePart + */ +export const UninterpretedOption_NamePart = proto2.makeMessageType( + "google.protobuf.UninterpretedOption.NamePart", + () => [ + { no: 1, name: "name_part", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "is_extension", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ], + {localName: "UninterpretedOption_NamePart"}, +); + +/** + * Encapsulates information about the original source file from which a + * FileDescriptorProto was generated. + * + * @generated from message google.protobuf.SourceCodeInfo + */ +export const SourceCodeInfo = proto2.makeMessageType( + "google.protobuf.SourceCodeInfo", + () => [ + { no: 1, name: "location", kind: "message", T: SourceCodeInfo_Location, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.SourceCodeInfo.Location + */ +export const SourceCodeInfo_Location = proto2.makeMessageType( + "google.protobuf.SourceCodeInfo.Location", + () => [ + { no: 1, name: "path", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 2, name: "span", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 3, name: "leading_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "trailing_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 6, name: "leading_detached_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ], + {localName: "SourceCodeInfo_Location"}, +); + +/** + * Describes the relationship between generated code and its original source + * file. A GeneratedCodeInfo message is associated with only one generated + * source file, but may contain references to different source .proto files. + * + * @generated from message google.protobuf.GeneratedCodeInfo + */ +export const GeneratedCodeInfo = proto2.makeMessageType( + "google.protobuf.GeneratedCodeInfo", + () => [ + { no: 1, name: "annotation", kind: "message", T: GeneratedCodeInfo_Annotation, repeated: true }, + ], +); + +/** + * @generated from message google.protobuf.GeneratedCodeInfo.Annotation + */ +export const GeneratedCodeInfo_Annotation = proto2.makeMessageType( + "google.protobuf.GeneratedCodeInfo.Annotation", + () => [ + { no: 1, name: "path", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 2, name: "source_file", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "begin", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ], + {localName: "GeneratedCodeInfo_Annotation"}, +); + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.d.ts new file mode 100644 index 000000000..2b1fa104f --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.d.ts @@ -0,0 +1,138 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/duration.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (duration.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + * + * + * + * @generated from message google.protobuf.Duration + */ +export declare class Duration extends Message { + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * @generated from field: int64 seconds = 1; + */ + seconds: bigint; + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * @generated from field: int32 nanos = 2; + */ + nanos: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Duration"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Duration; + + static fromJson(jsonValue: JsonValue, options?: Partial): Duration; + + static fromJsonString(jsonString: string, options?: Partial): Duration; + + static equals(a: Duration | PlainMessage | undefined, b: Duration | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.js new file mode 100644 index 000000000..dd944dcb0 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/duration_pb.js @@ -0,0 +1,149 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/duration.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3, protoInt64} from "@bufbuild/protobuf"; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (duration.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + * + * + * + * @generated from message google.protobuf.Duration + */ +export const Duration = proto3.makeMessageType( + "google.protobuf.Duration", + () => [ + { no: 1, name: "seconds", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "nanos", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ], +); + +Duration.prototype.fromJson = function fromJson(json, options) { + if (typeof json !== "string") { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + const match = json.match(/^(-?[0-9]+)(?:\.([0-9]+))?s/); + if (match === null) { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + const longSeconds = Number(match[1]); + if (longSeconds > 315576000000 || longSeconds < -315576000000) { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + this.seconds = protoInt64.parse(longSeconds); + if (typeof match[2] == "string") { + const nanosStr = match[2] + "0".repeat(9 - match[2].length); + this.nanos = parseInt(nanosStr); + if (longSeconds < protoInt64.zero) { + this.nanos = -this.nanos; + } + } + return this; +}; + +Duration.prototype.toJson = function toJson(options) { + if (Number(this.seconds) > 315576000000 || Number(this.seconds) < -315576000000) { + throw new Error(`cannot encode google.protobuf.Duration to JSON: value out of range`); + } + let text = this.seconds.toString(); + if (this.nanos !== 0) { + let nanosStr = Math.abs(this.nanos).toString(); + nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr; + if (nanosStr.substring(3) === "000000") { + nanosStr = nanosStr.substring(0, 3); + } else if (nanosStr.substring(6) === "000") { + nanosStr = nanosStr.substring(0, 6); + } + text += "." + nanosStr; + } + return text + "s"; +}; + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.d.ts new file mode 100644 index 000000000..021fc62cf --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.d.ts @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/empty.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + * + * @generated from message google.protobuf.Empty + */ +export declare class Empty extends Message { + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Empty"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Empty; + + static fromJson(jsonValue: JsonValue, options?: Partial): Empty; + + static fromJsonString(jsonString: string, options?: Partial): Empty; + + static equals(a: Empty | PlainMessage | undefined, b: Empty | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.js new file mode 100644 index 000000000..5a47753a0 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/empty_pb.js @@ -0,0 +1,54 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/empty.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + * + * @generated from message google.protobuf.Empty + */ +export const Empty = proto3.makeMessageType( + "google.protobuf.Empty", + [], +); + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.d.ts new file mode 100644 index 000000000..c35a3f6d6 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.d.ts @@ -0,0 +1,263 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/field_mask.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is unmappable. + * + * @generated from message google.protobuf.FieldMask + */ +export declare class FieldMask extends Message { + /** + * The set of field mask paths. + * + * @generated from field: repeated string paths = 1; + */ + paths: string[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.FieldMask"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldMask; + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldMask; + + static fromJsonString(jsonString: string, options?: Partial): FieldMask; + + static equals(a: FieldMask | PlainMessage | undefined, b: FieldMask | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.js new file mode 100644 index 000000000..2d5fd930d --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/field_mask_pb.js @@ -0,0 +1,308 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/field_mask.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is unmappable. + * + * @generated from message google.protobuf.FieldMask + */ +export const FieldMask = proto3.makeMessageType( + "google.protobuf.FieldMask", + () => [ + { no: 1, name: "paths", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ], +); + +FieldMask.prototype.toJson = function toJson(options) { + // Converts snake_case to protoCamelCase according to the convention + // used by protoc to convert a field name to a JSON name. + function protoCamelCase(snakeCase) { + let capNext = false; + const b = []; + for (let i = 0; i < snakeCase.length; i++) { + let c = snakeCase.charAt(i); + switch (c) { + case '_': + capNext = true; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + b.push(c); + capNext = false; + break; + default: + if (capNext) { + capNext = false; + c = c.toUpperCase(); + } + b.push(c); + break; + } + } + return b.join(''); + } + return this.paths.map(p => { + if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: lowerCamelCase of path name \"" + p + "\" is irreversible"); + } + return protoCamelCase(p); + }).join(","); +}; + +FieldMask.prototype.fromJson = function fromJson(json, options) { + if (typeof json !== "string") { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: " + proto3.json.debug(json)); + } + if (json === "") { + return this; + } + function camelToSnake (str) { + if (str.includes("_")) { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: path names must be lowerCamelCase"); + } + const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase()); + return (sc[0] === "_") ? sc.substring(1) : sc; + } + this.paths = json.split(",").map(camelToSnake); + return this; +}; + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.d.ts new file mode 100644 index 000000000..58b10a9b8 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.d.ts @@ -0,0 +1,67 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/source_context.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + * + * @generated from message google.protobuf.SourceContext + */ +export declare class SourceContext extends Message { + /** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * + * @generated from field: string file_name = 1; + */ + fileName: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.SourceContext"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceContext; + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceContext; + + static fromJsonString(jsonString: string, options?: Partial): SourceContext; + + static equals(a: SourceContext | PlainMessage | undefined, b: SourceContext | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.js new file mode 100644 index 000000000..c79f01aa6 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/source_context_pb.js @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/source_context.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + * + * @generated from message google.protobuf.SourceContext + */ +export const SourceContext = proto3.makeMessageType( + "google.protobuf.SourceContext", + () => [ + { no: 1, name: "file_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ], +); + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.d.ts new file mode 100644 index 000000000..3858950ef --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.d.ts @@ -0,0 +1,200 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + * + * @generated from enum google.protobuf.NullValue + */ +export declare enum NullValue { + /** + * Null value. + * + * @generated from enum value: NULL_VALUE = 0; + */ + NULL_VALUE = 0, +} + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + * + * @generated from message google.protobuf.Struct + */ +export declare class Struct extends Message { + /** + * Unordered map of dynamically typed values. + * + * @generated from field: map fields = 1; + */ + fields: { [key: string]: Value }; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Struct"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Struct; + + static fromJson(jsonValue: JsonValue, options?: Partial): Struct; + + static fromJsonString(jsonString: string, options?: Partial): Struct; + + static equals(a: Struct | PlainMessage | undefined, b: Struct | PlainMessage | undefined): boolean; +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + * + * @generated from message google.protobuf.Value + */ +export declare class Value extends Message { + /** + * The kind of value. + * + * @generated from oneof google.protobuf.Value.kind + */ + kind: { + /** + * Represents a null value. + * + * @generated from field: google.protobuf.NullValue null_value = 1; + */ + value: NullValue; + case: "nullValue"; + } | { + /** + * Represents a double value. + * + * @generated from field: double number_value = 2; + */ + value: number; + case: "numberValue"; + } | { + /** + * Represents a string value. + * + * @generated from field: string string_value = 3; + */ + value: string; + case: "stringValue"; + } | { + /** + * Represents a boolean value. + * + * @generated from field: bool bool_value = 4; + */ + value: boolean; + case: "boolValue"; + } | { + /** + * Represents a structured value. + * + * @generated from field: google.protobuf.Struct struct_value = 5; + */ + value: Struct; + case: "structValue"; + } | { + /** + * Represents a repeated `Value`. + * + * @generated from field: google.protobuf.ListValue list_value = 6; + */ + value: ListValue; + case: "listValue"; + } | { case: undefined; value?: undefined }; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Value"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): Value; + + static fromJson(jsonValue: JsonValue, options?: Partial): Value; + + static fromJsonString(jsonString: string, options?: Partial): Value; + + static equals(a: Value | PlainMessage | undefined, b: Value | PlainMessage | undefined): boolean; +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + * + * @generated from message google.protobuf.ListValue + */ +export declare class ListValue extends Message { + /** + * Repeated field of dynamically typed values. + * + * @generated from field: repeated google.protobuf.Value values = 1; + */ + values: Value[]; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.ListValue"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): ListValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): ListValue; + + static fromJsonString(jsonString: string, options?: Partial): ListValue; + + static equals(a: ListValue | PlainMessage | undefined, b: ListValue | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.js new file mode 100644 index 000000000..46d7ca13b --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/struct_pb.js @@ -0,0 +1,179 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3} from "@bufbuild/protobuf"; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + * + * @generated from enum google.protobuf.NullValue + */ +export const NullValue = proto3.makeEnum( + "google.protobuf.NullValue", + [ + {no: 0, name: "NULL_VALUE"}, + ], +); + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + * + * @generated from message google.protobuf.Struct + */ +export const Struct = proto3.makeMessageType( + "google.protobuf.Struct", + () => [ + { no: 1, name: "fields", kind: "map", K: 9 /* ScalarType.STRING */, V: {kind: "message", T: Value} }, + ], +); + +Struct.prototype.toJson = function toJson(options) { + const json = {} + for (const [k, v] of Object.entries(this.fields)) { + json[k] = v.toJson(options); + } + return json; +}; + +Struct.prototype.fromJson = function fromJson(json, options) { + if (typeof json != "object" || json == null || Array.isArray(json)) { + throw new Error("cannot decode google.protobuf.Struct from JSON " + proto3.json.debug(json)); + } + for (const [k, v] of Object.entries(json)) { + this.fields[k] = Value.fromJson(v); + } + return this; +}; + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + * + * @generated from message google.protobuf.Value + */ +export const Value = proto3.makeMessageType( + "google.protobuf.Value", + () => [ + { no: 1, name: "null_value", kind: "enum", T: proto3.getEnumType(NullValue), oneof: "kind" }, + { no: 2, name: "number_value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, oneof: "kind" }, + { no: 3, name: "string_value", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "kind" }, + { no: 4, name: "bool_value", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "kind" }, + { no: 5, name: "struct_value", kind: "message", T: Struct, oneof: "kind" }, + { no: 6, name: "list_value", kind: "message", T: ListValue, oneof: "kind" }, + ], +); + +Value.prototype.toJson = function toJson(options) { + switch (this.kind.case) { + case "nullValue": + return null; + case "boolValue": + case "numberValue": + case "stringValue": + return this.kind.value; + case "structValue": + case "listValue": + return this.kind.value.toJson({...options, emitDefaultValues: true}); + } + throw new Error("google.protobuf.Value must have a value"); +}; + +Value.prototype.fromJson = function fromJson(json, options) { + switch (typeof json) { + case "number": + this.kind = { case: "numberValue", value: json }; + break; + case "string": + this.kind = { case: "stringValue", value: json }; + break; + case "boolean": + this.kind = { case: "boolValue", value: json }; + break; + case "object": + if (json === null) { + this.kind = { case: "nullValue", value: NullValue.NULL_VALUE }; + } else if (Array.isArray(json)) { + this.kind = { case: "listValue", value: ListValue.fromJson(json) }; + } else { + this.kind = { case: "structValue", value: Struct.fromJson(json) }; + } + break; + default: + throw new Error("cannot decode google.protobuf.Value from JSON " + proto3.json.debug(json)); + } + return this; +}; + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + * + * @generated from message google.protobuf.ListValue + */ +export const ListValue = proto3.makeMessageType( + "google.protobuf.ListValue", + () => [ + { no: 1, name: "values", kind: "message", T: Value, repeated: true }, + ], +); + +ListValue.prototype.toJson = function toJson(options) { + return this.values.map(v => v.toJson()); +} + +ListValue.prototype.fromJson = function fromJson(json, options) { + if (!Array.isArray(json)) { + throw new Error("cannot decode google.protobuf.ListValue from JSON " + proto3.json.debug(json)); + } + for (let e of json) { + this.values.push(Value.fromJson(e)); + } + return this; +}; + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto2_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto2_pb.js index bac23b2ce..932efddc0 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto2_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto2_pb.js @@ -177,11 +177,11 @@ export const TestAllTypesProto2 = proto2.makeMessageType( { no: 248, name: "default_fixed64", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true, default: protoInt64.uParse("10123456789123456789") }, { no: 249, name: "default_sfixed32", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true, default: -123456789 }, { no: 250, name: "default_sfixed64", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true, default: protoInt64.parse("-9123456789123456789") }, - { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9e+09 }, + { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9000000000 }, { no: 252, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 7e+22 }, { no: 253, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 254, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "Rosebud" }, - { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61, ]) }, + { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61]) }, { no: 401, name: "fieldname1", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 402, name: "field_name2", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 403, name: "_field_name3", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto3_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto3_pb.js index e1b05d501..da09eed2c 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto3_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/test_messages_proto3_pb.js @@ -39,7 +39,7 @@ // @generated from file google/protobuf/test_messages_proto3.proto (package protobuf_test_messages.proto3, syntax proto3) /* eslint-disable */ -import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, NullValue, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value, proto3} from "@bufbuild/protobuf"; +import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, NullValue, proto3, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value} from "@bufbuild/protobuf"; /** * @generated from enum protobuf_test_messages.proto3.ForeignEnum diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.d.ts new file mode 100644 index 000000000..1a39160bf --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.d.ts @@ -0,0 +1,175 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/timestamp.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + * + * + * + * @generated from message google.protobuf.Timestamp + */ +export declare class Timestamp extends Message { + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * + * @generated from field: int64 seconds = 1; + */ + seconds: bigint; + + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * + * @generated from field: int32 nanos = 2; + */ + nanos: number; + + constructor(data?: PartialMessage); + + toDate(): Date; + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Timestamp"; + static readonly fields: FieldList; + + static now(): Timestamp; + + static fromDate(date: Date): Timestamp; + + static fromBinary(bytes: Uint8Array, options?: Partial): Timestamp; + + static fromJson(jsonValue: JsonValue, options?: Partial): Timestamp; + + static fromJsonString(jsonString: string, options?: Partial): Timestamp; + + static equals(a: Timestamp | PlainMessage | undefined, b: Timestamp | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.js new file mode 100644 index 000000000..3b6caf002 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/timestamp_pb.js @@ -0,0 +1,202 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/timestamp.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3, protoInt64} from "@bufbuild/protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + * + * + * + * @generated from message google.protobuf.Timestamp + */ +export const Timestamp = proto3.makeMessageType( + "google.protobuf.Timestamp", + () => [ + { no: 1, name: "seconds", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "nanos", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ], +); + +Timestamp.prototype.fromJson = function fromJson(json, options) { + if (typeof json !== "string") { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: ${proto3.json.debug(json)}`); + } + const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/); + if (!matches) { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string`); + } + const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z")); + if (Number.isNaN(ms)) { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string`); + } + if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) { + throw new Error(`cannot decode message google.protobuf.Timestamp from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`); + } + this.seconds = protoInt64.parse(ms / 1000); + this.nanos = 0; + if (matches[7]) { + this.nanos = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000); + } + return this; +}; + +Timestamp.prototype.toJson = function toJson(options) { + const ms = Number(this.seconds) * 1000; + if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) { + throw new Error(`cannot encode google.protobuf.Timestamp to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`); + } + if (this.nanos < 0) { + throw new Error(`cannot encode google.protobuf.Timestamp to JSON: nanos must not be negative`); + } + let z = "Z"; + if (this.nanos > 0) { + const nanosStr = (this.nanos + 1000000000).toString().substring(1); + if (nanosStr.substring(3) === "000000") { + z = "." + nanosStr.substring(0, 3) + "Z"; + } else if (nanosStr.substring(6) === "000") { + z = "." + nanosStr.substring(0, 6) + "Z"; + } else { + z = "." + nanosStr + "Z"; + } + } + return new Date(ms).toISOString().replace(".000Z", z); +}; + +Timestamp.prototype.toDate = function toDate() { + return new Date(Number(this.seconds) * 1000 + Math.ceil(this.nanos / 1000000)); +}; + +Timestamp.now = function now() { + return Timestamp.fromDate(new Date()) +}; + +Timestamp.fromDate = function fromDate(date) { + const ms = date.getTime(); + return new Timestamp({ + seconds: protoInt64.parse(Math.floor(ms / 1000)), + nanos: (ms % 1000) * 1000000, + }); +}; + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.d.ts index 90e7bf159..c9597b081 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.d.ts +++ b/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.d.ts @@ -32,8 +32,10 @@ // @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3) /* eslint-disable */ -import type {Any, BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage, SourceContext} from "@bufbuild/protobuf"; +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; import {Message, proto3} from "@bufbuild/protobuf"; +import type {SourceContext} from "./source_context_pb.js"; +import type {Any} from "./any_pb.js"; /** * The syntax in which a protocol buffer element is defined. diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.js index 4d46a58e9..b14884773 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/type_pb.js @@ -32,7 +32,9 @@ // @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3) /* eslint-disable */ -import {Any, SourceContext, proto3} from "@bufbuild/protobuf"; +import {proto3} from "@bufbuild/protobuf"; +import {SourceContext} from "./source_context_pb.js"; +import {Any} from "./any_pb.js"; /** * The syntax in which a protocol buffer element is defined. @@ -42,10 +44,9 @@ import {Any, SourceContext, proto3} from "@bufbuild/protobuf"; export const Syntax = proto3.makeEnum( "google.protobuf.Syntax", [ - {no: 0, name: "SYNTAX_PROTO2"}, - {no: 1, name: "SYNTAX_PROTO3"}, + {no: 0, name: "SYNTAX_PROTO2", localName: "PROTO2"}, + {no: 1, name: "SYNTAX_PROTO3", localName: "PROTO3"}, ], - {sharedPrefix: "SYNTAX_"}, ); /** @@ -124,12 +125,11 @@ export const Field_Kind = proto3.makeEnum( export const Field_Cardinality = proto3.makeEnum( "google.protobuf.Field.Cardinality", [ - {no: 0, name: "CARDINALITY_UNKNOWN"}, - {no: 1, name: "CARDINALITY_OPTIONAL"}, - {no: 2, name: "CARDINALITY_REQUIRED"}, - {no: 3, name: "CARDINALITY_REPEATED"}, + {no: 0, name: "CARDINALITY_UNKNOWN", localName: "UNKNOWN"}, + {no: 1, name: "CARDINALITY_OPTIONAL", localName: "OPTIONAL"}, + {no: 2, name: "CARDINALITY_REQUIRED", localName: "REQUIRED"}, + {no: 3, name: "CARDINALITY_REPEATED", localName: "REPEATED"}, ], - {sharedPrefix: "CARDINALITY_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_custom_options_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_custom_options_pb.js index acf8f2b11..7037e8235 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_custom_options_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_custom_options_pb.js @@ -332,9 +332,8 @@ export const NestedOptionType = proto2.makeMessageType( export const NestedOptionType_NestedEnum = proto2.makeEnum( "protobuf_unittest.NestedOptionType.NestedEnum", [ - {no: 1, name: "NESTED_ENUM_VALUE"}, + {no: 1, name: "NESTED_ENUM_VALUE", localName: "VALUE"}, ], - {sharedPrefix: "NESTED_ENUM_"}, ); /** diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_lite_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_lite_pb.js index 59e3eadcd..5c7df42d0 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_lite_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_lite_pb.js @@ -146,7 +146,7 @@ export const TestAllTypesLite = proto2.makeMessageType( { no: 72, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 52000 }, { no: 73, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 74, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64, ]) }, + { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64]) }, { no: 81, name: "default_nested_enum", kind: "enum", T: proto2.getEnumType(TestAllTypesLite_NestedEnum), opt: true, default: TestAllTypesLite_NestedEnum.BAR }, { no: 82, name: "default_foreign_enum", kind: "enum", T: proto2.getEnumType(ForeignEnumLite), opt: true, default: ForeignEnumLite.FOREIGN_LITE_BAR }, { no: 83, name: "default_import_enum", kind: "enum", T: proto2.getEnumType(ImportEnumLite), opt: true, default: ImportEnumLite.IMPORT_LITE_BAR }, @@ -488,11 +488,11 @@ export const TestOneofParsingLite = proto2.makeMessageType( { no: 1, name: "oneof_int32", kind: "scalar", T: 5 /* ScalarType.INT32 */, oneof: "oneof_field" }, { no: 2, name: "oneof_submessage", kind: "message", T: TestAllTypesLite, oneof: "oneof_field" }, { no: 3, name: "oneof_string", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "oneof_field" }, - { no: 4, name: "oneof_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, ]), oneof: "oneof_field" }, + { no: 4, name: "oneof_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73]), oneof: "oneof_field" }, { no: 5, name: "oneof_string_cord", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "default Cord", oneof: "oneof_field" }, { no: 6, name: "oneof_bytes_cord", kind: "scalar", T: 12 /* ScalarType.BYTES */, oneof: "oneof_field" }, { no: 7, name: "oneof_string_string_piece", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "oneof_field" }, - { no: 8, name: "oneof_bytes_string_piece", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x50, 0x69, 0x65, 0x63, 0x65, ]), oneof: "oneof_field" }, + { no: 8, name: "oneof_bytes_string_piece", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x50, 0x69, 0x65, 0x63, 0x65]), oneof: "oneof_field" }, { no: 9, name: "oneof_enum", kind: "enum", T: proto2.getEnumType(V2EnumLite), oneof: "oneof_field" }, ], ); diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_no_field_presence_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_no_field_presence_pb.d.ts index a45711d3a..e8002f2fd 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_no_field_presence_pb.d.ts +++ b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_no_field_presence_pb.d.ts @@ -167,7 +167,7 @@ export declare class TestAllTypes extends Message { /** * N.B.: proto2-enum-type fields not allowed, because their default values * might not be zero. - *optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23; + * optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23; * * @generated from field: proto2_nofieldpresence_unittest.ForeignEnum optional_foreign_enum = 22; */ diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_pb.js index 762ffab9b..f33fcaf19 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_pb.js @@ -278,7 +278,7 @@ export const TestAllTypes = proto2.makeMessageType( { no: 72, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 52000 }, { no: 73, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 74, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64, ]) }, + { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64]) }, { no: 81, name: "default_nested_enum", kind: "enum", T: proto2.getEnumType(TestAllTypes_NestedEnum), opt: true, default: TestAllTypes_NestedEnum.BAR }, { no: 82, name: "default_foreign_enum", kind: "enum", T: proto2.getEnumType(ForeignEnum), opt: true, default: ForeignEnum.FOREIGN_BAR }, { no: 83, name: "default_import_enum", kind: "enum", T: proto2.getEnumType(ImportEnum), opt: true, default: ImportEnum.IMPORT_BAR }, @@ -1007,7 +1007,7 @@ export const TestExtensionOrderings2_TestExtensionOrderings3 = proto2.makeMessag export const TestExtremeDefaultValues = proto2.makeMessageType( "protobuf_unittest.TestExtremeDefaultValues", () => [ - { no: 1, name: "escaped_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x01, 0x07, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, 0x5C, 0xFE, ]) }, + { no: 1, name: "escaped_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x01, 0x07, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, 0x5C, 0xFE]) }, { no: 2, name: "large_uint32", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true, default: 4294967295 }, { no: 3, name: "large_uint64", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true, default: protoInt64.uParse("18446744073709551615") }, { no: 4, name: "small_int32", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true, default: -2147483647 }, @@ -1020,7 +1020,7 @@ export const TestExtremeDefaultValues = proto2.makeMessageType( { no: 9, name: "small_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 1.5 }, { no: 10, name: "negative_one_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -1 }, { no: 11, name: "negative_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -1.5 }, - { no: 12, name: "large_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 2e+08 }, + { no: 12, name: "large_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 200000000 }, { no: 13, name: "small_negative_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -8e-28 }, { no: 14, name: "inf_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: globalThis.Number.POSITIVE_INFINITY }, { no: 15, name: "neg_inf_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: globalThis.Number.NEGATIVE_INFINITY }, @@ -1030,7 +1030,7 @@ export const TestExtremeDefaultValues = proto2.makeMessageType( { no: 19, name: "nan_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: globalThis.Number.NaN }, { no: 20, name: "cpp_trigraph", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "? ? ?? ?? ??? ??/ ??-" }, { no: 23, name: "string_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 24, name: "bytes_with_zero", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x00, 0x6C, 0x64, ]) }, + { no: 24, name: "bytes_with_zero", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x00, 0x6C, 0x64]) }, { no: 25, name: "string_piece_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "abc" }, { no: 26, name: "cord_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "123" }, { no: 27, name: "replacement_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "${unknown}" }, @@ -1253,12 +1253,12 @@ export const TestOneof2 = proto2.makeMessageType( { no: 13, name: "bar_string", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "STRING", oneof: "bar" }, { no: 14, name: "bar_cord", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "CORD", oneof: "bar" }, { no: 15, name: "bar_string_piece", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "SPIECE", oneof: "bar" }, - { no: 16, name: "bar_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x42, 0x59, 0x54, 0x45, 0x53, ]), oneof: "bar" }, + { no: 16, name: "bar_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x42, 0x59, 0x54, 0x45, 0x53]), oneof: "bar" }, { no: 17, name: "bar_enum", kind: "enum", T: proto2.getEnumType(TestOneof2_NestedEnum), default: TestOneof2_NestedEnum.BAR, oneof: "bar" }, - { no: 20, name: "bar_string_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 21, name: "bar_cord_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 22, name: "bar_string_piece_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 23, name: "bar_bytes_with_empty_default", kind: "scalar", T: 12 /* ScalarType.BYTES */, oneof: "bar" }, + { no: 20, name: "bar_string_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 21, name: "bar_cord_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 22, name: "bar_string_piece_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 23, name: "bar_bytes_with_empty_default", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array(0), oneof: "bar" }, { no: 18, name: "baz_int", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 19, name: "baz_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "BAZ" }, ], diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_well_known_types_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_well_known_types_pb.js index ef84f8db1..1622dd11a 100644 --- a/packages/protobuf-test/src/gen/js/google/protobuf/unittest_well_known_types_pb.js +++ b/packages/protobuf-test/src/gen/js/google/protobuf/unittest_well_known_types_pb.js @@ -2,7 +2,7 @@ // @generated from file google/protobuf/unittest_well_known_types.proto (package protobuf_unittest, syntax proto3) /* eslint-disable */ -import {Any, Api, BoolValue, BytesValue, DoubleValue, Duration, Empty, FieldMask, FloatValue, Int32Value, Int64Value, SourceContext, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value, proto3} from "@bufbuild/protobuf"; +import {Any, Api, BoolValue, BytesValue, DoubleValue, Duration, Empty, FieldMask, FloatValue, Int32Value, Int64Value, proto3, SourceContext, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value} from "@bufbuild/protobuf"; import {Type} from "./type_pb.js"; /** diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.d.ts b/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.d.ts new file mode 100644 index 000000000..9f072e9be --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.d.ts @@ -0,0 +1,362 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. +// +// These wrappers have no meaningful use within repeated fields as they lack +// the ability to detect presence on individual elements. +// These wrappers have no meaningful use within a map or a oneof since +// individual entries of a map or fields of a oneof can already detect presence. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/wrappers.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + * + * @generated from message google.protobuf.DoubleValue + */ +export declare class DoubleValue extends Message { + /** + * The double value. + * + * @generated from field: double value = 1; + */ + value: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.DoubleValue"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: number | DoubleValue): DoubleValue, + unwrapField(value: DoubleValue): number, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): DoubleValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): DoubleValue; + + static fromJsonString(jsonString: string, options?: Partial): DoubleValue; + + static equals(a: DoubleValue | PlainMessage | undefined, b: DoubleValue | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + * + * @generated from message google.protobuf.FloatValue + */ +export declare class FloatValue extends Message { + /** + * The float value. + * + * @generated from field: float value = 1; + */ + value: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.FloatValue"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: number | FloatValue): FloatValue, + unwrapField(value: FloatValue): number, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): FloatValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): FloatValue; + + static fromJsonString(jsonString: string, options?: Partial): FloatValue; + + static equals(a: FloatValue | PlainMessage | undefined, b: FloatValue | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + * + * @generated from message google.protobuf.Int64Value + */ +export declare class Int64Value extends Message { + /** + * The int64 value. + * + * @generated from field: int64 value = 1; + */ + value: bigint; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Int64Value"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: bigint | Int64Value): Int64Value, + unwrapField(value: Int64Value): bigint, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): Int64Value; + + static fromJson(jsonValue: JsonValue, options?: Partial): Int64Value; + + static fromJsonString(jsonString: string, options?: Partial): Int64Value; + + static equals(a: Int64Value | PlainMessage | undefined, b: Int64Value | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + * + * @generated from message google.protobuf.UInt64Value + */ +export declare class UInt64Value extends Message { + /** + * The uint64 value. + * + * @generated from field: uint64 value = 1; + */ + value: bigint; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.UInt64Value"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: bigint | UInt64Value): UInt64Value, + unwrapField(value: UInt64Value): bigint, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt64Value; + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt64Value; + + static fromJsonString(jsonString: string, options?: Partial): UInt64Value; + + static equals(a: UInt64Value | PlainMessage | undefined, b: UInt64Value | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + * + * @generated from message google.protobuf.Int32Value + */ +export declare class Int32Value extends Message { + /** + * The int32 value. + * + * @generated from field: int32 value = 1; + */ + value: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.Int32Value"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: number | Int32Value): Int32Value, + unwrapField(value: Int32Value): number, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): Int32Value; + + static fromJson(jsonValue: JsonValue, options?: Partial): Int32Value; + + static fromJsonString(jsonString: string, options?: Partial): Int32Value; + + static equals(a: Int32Value | PlainMessage | undefined, b: Int32Value | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + * + * @generated from message google.protobuf.UInt32Value + */ +export declare class UInt32Value extends Message { + /** + * The uint32 value. + * + * @generated from field: uint32 value = 1; + */ + value: number; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.UInt32Value"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: number | UInt32Value): UInt32Value, + unwrapField(value: UInt32Value): number, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt32Value; + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt32Value; + + static fromJsonString(jsonString: string, options?: Partial): UInt32Value; + + static equals(a: UInt32Value | PlainMessage | undefined, b: UInt32Value | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + * + * @generated from message google.protobuf.BoolValue + */ +export declare class BoolValue extends Message { + /** + * The bool value. + * + * @generated from field: bool value = 1; + */ + value: boolean; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.BoolValue"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: boolean | BoolValue): BoolValue, + unwrapField(value: BoolValue): boolean, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): BoolValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): BoolValue; + + static fromJsonString(jsonString: string, options?: Partial): BoolValue; + + static equals(a: BoolValue | PlainMessage | undefined, b: BoolValue | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + * + * @generated from message google.protobuf.StringValue + */ +export declare class StringValue extends Message { + /** + * The string value. + * + * @generated from field: string value = 1; + */ + value: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.StringValue"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: string | StringValue): StringValue, + unwrapField(value: StringValue): string, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): StringValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): StringValue; + + static fromJsonString(jsonString: string, options?: Partial): StringValue; + + static equals(a: StringValue | PlainMessage | undefined, b: StringValue | PlainMessage | undefined): boolean; +} + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + * + * @generated from message google.protobuf.BytesValue + */ +export declare class BytesValue extends Message { + /** + * The bytes value. + * + * @generated from field: bytes value = 1; + */ + value: Uint8Array; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "google.protobuf.BytesValue"; + static readonly fields: FieldList; + + static readonly fieldWrapper: { + wrapField(value: Uint8Array | BytesValue): BytesValue, + unwrapField(value: BytesValue): Uint8Array, + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): BytesValue; + + static fromJson(jsonValue: JsonValue, options?: Partial): BytesValue; + + static fromJsonString(jsonString: string, options?: Partial): BytesValue; + + static equals(a: BytesValue | PlainMessage | undefined, b: BytesValue | PlainMessage | undefined): boolean; +} + diff --git a/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.js b/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.js new file mode 100644 index 000000000..60f195d67 --- /dev/null +++ b/packages/protobuf-test/src/gen/js/google/protobuf/wrappers_pb.js @@ -0,0 +1,406 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. +// +// These wrappers have no meaningful use within repeated fields as they lack +// the ability to detect presence on individual elements. +// These wrappers have no meaningful use within a map or a oneof since +// individual entries of a map or fields of a oneof can already detect presence. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" +// @generated from file google/protobuf/wrappers.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import {proto3, ScalarType} from "@bufbuild/protobuf"; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + * + * @generated from message google.protobuf.DoubleValue + */ +export const DoubleValue = proto3.makeMessageType( + "google.protobuf.DoubleValue", + () => [ + { no: 1, name: "value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + ], +); + +DoubleValue.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.DOUBLE, this.value, true); +} + +DoubleValue.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.DOUBLE, json); + } catch (e) { + let m = `cannot decode message google.protobuf.DoubleValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +DoubleValue.fieldWrapper = { + wrapField(value) { + return value instanceof DoubleValue ? value : new DoubleValue({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + * + * @generated from message google.protobuf.FloatValue + */ +export const FloatValue = proto3.makeMessageType( + "google.protobuf.FloatValue", + () => [ + { no: 1, name: "value", kind: "scalar", T: 2 /* ScalarType.FLOAT */ }, + ], +); + +FloatValue.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.FLOAT, this.value, true); +} + +FloatValue.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.FLOAT, json); + } catch (e) { + let m = `cannot decode message google.protobuf.FloatValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +FloatValue.fieldWrapper = { + wrapField(value) { + return value instanceof FloatValue ? value : new FloatValue({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + * + * @generated from message google.protobuf.Int64Value + */ +export const Int64Value = proto3.makeMessageType( + "google.protobuf.Int64Value", + () => [ + { no: 1, name: "value", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + ], +); + +Int64Value.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.INT64, this.value, true); +} + +Int64Value.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.INT64, json); + } catch (e) { + let m = `cannot decode message google.protobuf.Int64Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +Int64Value.fieldWrapper = { + wrapField(value) { + return value instanceof Int64Value ? value : new Int64Value({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + * + * @generated from message google.protobuf.UInt64Value + */ +export const UInt64Value = proto3.makeMessageType( + "google.protobuf.UInt64Value", + () => [ + { no: 1, name: "value", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, + ], +); + +UInt64Value.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.UINT64, this.value, true); +} + +UInt64Value.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.UINT64, json); + } catch (e) { + let m = `cannot decode message google.protobuf.UInt64Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +UInt64Value.fieldWrapper = { + wrapField(value) { + return value instanceof UInt64Value ? value : new UInt64Value({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + * + * @generated from message google.protobuf.Int32Value + */ +export const Int32Value = proto3.makeMessageType( + "google.protobuf.Int32Value", + () => [ + { no: 1, name: "value", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ], +); + +Int32Value.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.INT32, this.value, true); +} + +Int32Value.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.INT32, json); + } catch (e) { + let m = `cannot decode message google.protobuf.Int32Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +Int32Value.fieldWrapper = { + wrapField(value) { + return value instanceof Int32Value ? value : new Int32Value({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + * + * @generated from message google.protobuf.UInt32Value + */ +export const UInt32Value = proto3.makeMessageType( + "google.protobuf.UInt32Value", + () => [ + { no: 1, name: "value", kind: "scalar", T: 13 /* ScalarType.UINT32 */ }, + ], +); + +UInt32Value.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.UINT32, this.value, true); +} + +UInt32Value.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.UINT32, json); + } catch (e) { + let m = `cannot decode message google.protobuf.UInt32Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +UInt32Value.fieldWrapper = { + wrapField(value) { + return value instanceof UInt32Value ? value : new UInt32Value({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + * + * @generated from message google.protobuf.BoolValue + */ +export const BoolValue = proto3.makeMessageType( + "google.protobuf.BoolValue", + () => [ + { no: 1, name: "value", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ], +); + +BoolValue.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.BOOL, this.value, true); +} + +BoolValue.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.BOOL, json); + } catch (e) { + let m = `cannot decode message google.protobuf.BoolValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +BoolValue.fieldWrapper = { + wrapField(value) { + return value instanceof BoolValue ? value : new BoolValue({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + * + * @generated from message google.protobuf.StringValue + */ +export const StringValue = proto3.makeMessageType( + "google.protobuf.StringValue", + () => [ + { no: 1, name: "value", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ], +); + +StringValue.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.STRING, this.value, true); +} + +StringValue.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.STRING, json); + } catch (e) { + let m = `cannot decode message google.protobuf.StringValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +StringValue.fieldWrapper = { + wrapField(value) { + return value instanceof StringValue ? value : new StringValue({value}); + }, + unwrapField(value) { + return value.value; + } +}; + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + * + * @generated from message google.protobuf.BytesValue + */ +export const BytesValue = proto3.makeMessageType( + "google.protobuf.BytesValue", + () => [ + { no: 1, name: "value", kind: "scalar", T: 12 /* ScalarType.BYTES */ }, + ], +); + +BytesValue.prototype.toJson = function toJson(options) { + return proto3.json.writeScalar(ScalarType.BYTES, this.value, true); +} + +BytesValue.prototype.fromJson = function fromJson(json, options) { + try { + this.value = proto3.json.readScalar(ScalarType.BYTES, json); + } catch (e) { + let m = `cannot decode message google.protobuf.BytesValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; +}; + +BytesValue.fieldWrapper = { + wrapField(value) { + return value instanceof BytesValue ? value : new BytesValue({value}); + }, + unwrapField(value) { + return value.value; + } +}; + diff --git a/packages/protobuf-test/src/gen/ts/extra/comments_pb.ts b/packages/protobuf-test/src/gen/ts/extra/comments_pb.ts index 0a5b18df6..0bf722cb0 100644 --- a/packages/protobuf-test/src/gen/ts/extra/comments_pb.ts +++ b/packages/protobuf-test/src/gen/ts/extra/comments_pb.ts @@ -138,8 +138,6 @@ export class MessageWithComments extends Message { } | { case: undefined; value?: undefined } = { case: undefined }; /** - * - * * @generated from field: string this_field_has_an_empty_comment = 4; */ thisFieldHasAnEmptyComment = ""; diff --git a/packages/protobuf-test/src/gen/ts/extra/enum-annotated_pb.ts b/packages/protobuf-test/src/gen/ts/extra/enum-annotated_pb.ts deleted file mode 100644 index 4c745c2a6..000000000 --- a/packages/protobuf-test/src/gen/ts/extra/enum-annotated_pb.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" -// @generated from file extra/enum-annotated.proto (package spec, syntax proto3) -/* eslint-disable */ - -import {proto3} from "@bufbuild/protobuf"; - -/** - * @generated from enum spec.AnnotatedEnum - */ -export enum AnnotatedEnum { - /** - * @generated from enum value: UNSPECIFIED = 0; - */ - UNSPECIFIED = 0, - - /** - * @generated from enum value: FOO = 1; - */ - FOO = 1, -} -// Retrieve enum metadata with: proto3.getEnumType(AnnotatedEnum) -proto3.util.setEnumType(AnnotatedEnum, "spec.AnnotatedEnum", [ - { no: 0, name: "UNSPECIFIED" }, - { no: 1, name: "FOO" }, -]); - diff --git a/packages/protobuf-test/src/gen/ts/extra/enum_pb.ts b/packages/protobuf-test/src/gen/ts/extra/enum_pb.ts new file mode 100644 index 000000000..e5bac832e --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/extra/enum_pb.ts @@ -0,0 +1,162 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file extra/enum.proto (package spec, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * @generated from enum spec.AnnotatedEnum + */ +export enum AnnotatedEnum { + /** + * @generated from enum value: UNSPECIFIED = 0; + */ + UNSPECIFIED = 0, + + /** + * @generated from enum value: FOO = 1; + */ + FOO = 1, +} +// Retrieve enum metadata with: proto3.getEnumType(AnnotatedEnum) +proto3.util.setEnumType(AnnotatedEnum, "spec.AnnotatedEnum", [ + { no: 0, name: "UNSPECIFIED" }, + { no: 1, name: "FOO" }, +]); + +/** + * @generated from enum spec.SimpleEnum + */ +export enum SimpleEnum { + /** + * @generated from enum value: SIMPLE_ZERO = 0; + */ + SIMPLE_ZERO = 0, + + /** + * @generated from enum value: SIMPLE_ONE = 1; + */ + SIMPLE_ONE = 1, +} +// Retrieve enum metadata with: proto3.getEnumType(SimpleEnum) +proto3.util.setEnumType(SimpleEnum, "spec.SimpleEnum", [ + { no: 0, name: "SIMPLE_ZERO" }, + { no: 1, name: "SIMPLE_ONE" }, +]); + +/** + * @generated from enum spec.AliasEnum + */ +export enum AliasEnum { + /** + * @generated from enum value: ALIAS_ZERO = 0; + */ + ALIAS_ZERO = 0, + + /** + * @generated from enum value: ALIAS_ONE = 1; + */ + ALIAS_ONE = 1, + + /** + * @generated from enum value: ALIAS_ONE_ALIASED = 1; + */ + ALIAS_ONE_ALIASED = 1, +} +// Retrieve enum metadata with: proto3.getEnumType(AliasEnum) +proto3.util.setEnumType(AliasEnum, "spec.AliasEnum", [ + { no: 0, name: "ALIAS_ZERO" }, + { no: 1, name: "ALIAS_ONE" }, + { no: 1, name: "ALIAS_ONE_ALIASED" }, +]); + +/** + * The generated enum values should drop the "PREFIX_" + * part at the top if the target language allows + * (basically every language except C++). + * + * @generated from enum spec.PrefixEnum + */ +export enum PrefixEnum { + /** + * @generated from enum value: PREFIX_ENUM_ZERO = 0; + */ + ZERO = 0, + + /** + * @generated from enum value: PREFIX_ENUM_ONE = 1; + */ + ONE = 1, +} +// Retrieve enum metadata with: proto3.getEnumType(PrefixEnum) +proto3.util.setEnumType(PrefixEnum, "spec.PrefixEnum", [ + { no: 0, name: "PREFIX_ENUM_ZERO" }, + { no: 1, name: "PREFIX_ENUM_ONE" }, +]); + +/** + * @generated from message spec.EnumMessage + */ +export class EnumMessage extends Message { + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "spec.EnumMessage"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumMessage { + return new EnumMessage().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumMessage { + return new EnumMessage().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumMessage { + return new EnumMessage().fromJsonString(jsonString, options); + } + + static equals(a: EnumMessage | PlainMessage | undefined, b: EnumMessage | PlainMessage | undefined): boolean { + return proto3.util.equals(EnumMessage, a, b); + } +} + +/** + * @generated from enum spec.EnumMessage.NestedEnum + */ +export enum EnumMessage_NestedEnum { + /** + * @generated from enum value: NESTED_ZERO = 0; + */ + NESTED_ZERO = 0, + + /** + * @generated from enum value: NESTED_ONE = 1; + */ + NESTED_ONE = 1, +} +// Retrieve enum metadata with: proto3.getEnumType(EnumMessage_NestedEnum) +proto3.util.setEnumType(EnumMessage_NestedEnum, "spec.EnumMessage.NestedEnum", [ + { no: 0, name: "NESTED_ZERO" }, + { no: 1, name: "NESTED_ONE" }, +]); + diff --git a/packages/protobuf-test/src/gen/ts/extra/msg-json-names_pb.ts b/packages/protobuf-test/src/gen/ts/extra/msg-json-names_pb.ts index 215bdf4ad..15cd368ab 100644 --- a/packages/protobuf-test/src/gen/ts/extra/msg-json-names_pb.ts +++ b/packages/protobuf-test/src/gen/ts/extra/msg-json-names_pb.ts @@ -54,7 +54,7 @@ export class JsonNamesMessage extends Message { d = ""; /** - * @generated from field: string e = 7; + * @generated from field: string e = 7 [json_name = ""]; */ e = ""; @@ -72,7 +72,7 @@ export class JsonNamesMessage extends Message { { no: 4, name: "b", jsonName: "sameJsonName", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 5, name: "c", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 6, name: "d", jsonName: "c", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 7, name: "e", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "e", jsonName: "", kind: "scalar", T: 9 /* ScalarType.STRING */ }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): JsonNamesMessage { diff --git a/packages/protobuf-test/src/gen/ts/extra/proto2_pb.ts b/packages/protobuf-test/src/gen/ts/extra/proto2_pb.ts index 8f57f0b3e..1bafc8ed8 100644 --- a/packages/protobuf-test/src/gen/ts/extra/proto2_pb.ts +++ b/packages/protobuf-test/src/gen/ts/extra/proto2_pb.ts @@ -329,7 +329,7 @@ export class Proto2RequiredDefaultsMessage extends Message [ { no: 1, name: "string_field", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "hello \" */ " }, - { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, ]) }, + { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B]) }, { no: 3, name: "enum_field", kind: "enum", T: proto2.getEnumType(Proto2Enum), default: Proto2Enum.YES }, { no: 4, name: "message_field", kind: "message", T: Proto2ChildMessage }, ]); @@ -404,7 +404,7 @@ export class Proto2DefaultsMessage extends Message { static readonly typeName = "spec.Proto2DefaultsMessage"; static readonly fields: FieldList = proto2.util.newFieldList(() => [ { no: 1, name: "string_field", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello \" */ " }, - { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, ]) }, + { no: 2, name: "bytes_field", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x78, 0x5C, 0x78, 0x78, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B]) }, { no: 3, name: "int32_field", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true, default: 128 }, { no: 4, name: "int46_field", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true, default: protoInt64.parse("-256") }, { no: 5, name: "float_field", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -512.13 }, diff --git a/packages/protobuf-test/src/gen/ts/extra/wkt-wrappers_pb.ts b/packages/protobuf-test/src/gen/ts/extra/wkt-wrappers_pb.ts index e6a0350ac..09dba068d 100644 --- a/packages/protobuf-test/src/gen/ts/extra/wkt-wrappers_pb.ts +++ b/packages/protobuf-test/src/gen/ts/extra/wkt-wrappers_pb.ts @@ -17,7 +17,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {BoolValue, BytesValue, DoubleValue, FloatValue, Int32Value, Int64Value, Message, StringValue, UInt32Value, UInt64Value, proto3} from "@bufbuild/protobuf"; +import {BoolValue, BytesValue, DoubleValue, FloatValue, Int32Value, Int64Value, Message, proto3, StringValue, UInt32Value, UInt64Value} from "@bufbuild/protobuf"; /** * @generated from message spec.WrappersMessage diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/any_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/any_pb.ts new file mode 100644 index 000000000..5d03dc9a5 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/any_pb.ts @@ -0,0 +1,276 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/any.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, JsonWriteOptions, MessageType, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := anypb.New(foo) + * if err != nil { + * ... + * } + * ... + * foo := &pb.Foo{} + * if err := any.UnmarshalTo(foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + * + * + * @generated from message google.protobuf.Any + */ +export class Any extends Message { + /** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * + * + * @generated from field: string type_url = 1; + */ + typeUrl = ""; + + /** + * Must be a valid serialized protocol buffer of the above specified type. + * + * @generated from field: bytes value = 2; + */ + value = new Uint8Array(0); + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + if (this.typeUrl === "") { + return {}; + } + const typeName = this.typeUrlToName(this.typeUrl); + const messageType = options?.typeRegistry?.findMessage(typeName); + if (!messageType) { + throw new Error(`cannot encode message google.protobuf.Any to JSON: "${this.typeUrl}" is not in the type registry`); + } + const message = messageType.fromBinary(this.value); + let json = message.toJson(options); + if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) { + json = {value: json}; + } + json["@type"] = this.typeUrl; + return json; + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (json === null || Array.isArray(json) || typeof json != "object") { + throw new Error(`cannot decode message google.protobuf.Any from JSON: expected object but got ${json === null ? "null" : Array.isArray(json) ? "array" : typeof json}`); + } + const typeUrl = json["@type"]; + if (typeof typeUrl != "string" || typeUrl == "") { + throw new Error(`cannot decode message google.protobuf.Any from JSON: "@type" is empty`); + } + const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName); + if (!messageType) { + throw new Error(`cannot decode message google.protobuf.Any from JSON: ${typeUrl} is not in the type registry`); + } + let message; + if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) { + message = messageType.fromJson(json["value"], options); + } else { + const copy = Object.assign({}, json); + delete copy["@type"]; + message = messageType.fromJson(copy, options); + } + this.packFrom(message); + return this; + } + + packFrom(message: Message): void { + this.value = message.toBinary(); + this.typeUrl = this.typeNameToUrl(message.getType().typeName); + } + + unpackTo(target: Message): boolean { + if (!this.is(target.getType())) { + return false; + } + target.fromBinary(this.value); + return true; + } + + is(type: MessageType): boolean { + return this.typeUrl === this.typeNameToUrl(type.typeName); + } + + private typeNameToUrl(name: string): string { + return `type.googleapis.com/${name}`; + } + + private typeUrlToName(url: string): string { + if (!url.length) { + throw new Error(`invalid type url: ${url}`); + } + const slash = url.lastIndexOf("/"); + const name = slash > 0 ? url.substring(slash + 1) : url; + if (!name.length) { + throw new Error(`invalid type url: ${url}`); + } + return name; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Any"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "value", kind: "scalar", T: 12 /* ScalarType.BYTES */ }, + ]); + + static pack(message: Message): Any { + const any = new Any(); + any.packFrom(message); + return any; + } + + static fromBinary(bytes: Uint8Array, options?: Partial): Any { + return new Any().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Any { + return new Any().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Any { + return new Any().fromJsonString(jsonString, options); + } + + static equals(a: Any | PlainMessage | undefined, b: Any | PlainMessage | undefined): boolean { + return proto3.util.equals(Any, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/api_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/api_pb.ts new file mode 100644 index 000000000..84804d974 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/api_pb.ts @@ -0,0 +1,374 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/api.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; +import {Option, Syntax} from "./type_pb.js"; +import {SourceContext} from "./source_context_pb.js"; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + * + * @generated from message google.protobuf.Api + */ +export class Api extends Message { + /** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * + * @generated from field: string name = 1; + */ + name = ""; + + /** + * The methods of this interface, in unspecified order. + * + * @generated from field: repeated google.protobuf.Method methods = 2; + */ + methods: Method[] = []; + + /** + * Any metadata attached to the interface. + * + * @generated from field: repeated google.protobuf.Option options = 3; + */ + options: Option[] = []; + + /** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * + * + * + * @generated from field: string version = 4; + */ + version = ""; + + /** + * Source context for the protocol buffer service represented by this + * message. + * + * @generated from field: google.protobuf.SourceContext source_context = 5; + */ + sourceContext?: SourceContext; + + /** + * Included interfaces. See [Mixin][]. + * + * @generated from field: repeated google.protobuf.Mixin mixins = 6; + */ + mixins: Mixin[] = []; + + /** + * The source syntax of the service. + * + * @generated from field: google.protobuf.Syntax syntax = 7; + */ + syntax = Syntax.PROTO2; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Api"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "methods", kind: "message", T: Method, repeated: true }, + { no: 3, name: "options", kind: "message", T: Option, repeated: true }, + { no: 4, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "source_context", kind: "message", T: SourceContext }, + { no: 6, name: "mixins", kind: "message", T: Mixin, repeated: true }, + { no: 7, name: "syntax", kind: "enum", T: proto3.getEnumType(Syntax) }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Api { + return new Api().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Api { + return new Api().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Api { + return new Api().fromJsonString(jsonString, options); + } + + static equals(a: Api | PlainMessage | undefined, b: Api | PlainMessage | undefined): boolean { + return proto3.util.equals(Api, a, b); + } +} + +/** + * Method represents a method of an API interface. + * + * @generated from message google.protobuf.Method + */ +export class Method extends Message { + /** + * The simple name of this method. + * + * @generated from field: string name = 1; + */ + name = ""; + + /** + * A URL of the input message type. + * + * @generated from field: string request_type_url = 2; + */ + requestTypeUrl = ""; + + /** + * If true, the request is streamed. + * + * @generated from field: bool request_streaming = 3; + */ + requestStreaming = false; + + /** + * The URL of the output message type. + * + * @generated from field: string response_type_url = 4; + */ + responseTypeUrl = ""; + + /** + * If true, the response is streamed. + * + * @generated from field: bool response_streaming = 5; + */ + responseStreaming = false; + + /** + * Any metadata attached to the method. + * + * @generated from field: repeated google.protobuf.Option options = 6; + */ + options: Option[] = []; + + /** + * The source syntax of this method. + * + * @generated from field: google.protobuf.Syntax syntax = 7; + */ + syntax = Syntax.PROTO2; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Method"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "request_type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "request_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 4, name: "response_type_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "response_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 6, name: "options", kind: "message", T: Option, repeated: true }, + { no: 7, name: "syntax", kind: "enum", T: proto3.getEnumType(Syntax) }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Method { + return new Method().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Method { + return new Method().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Method { + return new Method().fromJsonString(jsonString, options); + } + + static equals(a: Method | PlainMessage | undefined, b: Method | PlainMessage | undefined): boolean { + return proto3.util.equals(Method, a, b); + } +} + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inheriting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + * + * @generated from message google.protobuf.Mixin + */ +export class Mixin extends Message { + /** + * The fully qualified name of the interface which is included. + * + * @generated from field: string name = 1; + */ + name = ""; + + /** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * + * @generated from field: string root = 2; + */ + root = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Mixin"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "root", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Mixin { + return new Mixin().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Mixin { + return new Mixin().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Mixin { + return new Mixin().fromJsonString(jsonString, options); + } + + static equals(a: Mixin | PlainMessage | undefined, b: Mixin | PlainMessage | undefined): boolean { + return proto3.util.equals(Mixin, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/compiler/plugin_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/compiler/plugin_pb.ts new file mode 100644 index 000000000..135947e3b --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/compiler/plugin_pb.ts @@ -0,0 +1,392 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/compiler/plugin.proto (package google.protobuf.compiler, syntax proto2) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto2} from "@bufbuild/protobuf"; +import {FileDescriptorProto, GeneratedCodeInfo} from "../descriptor_pb.js"; + +/** + * The version number of protocol compiler. + * + * @generated from message google.protobuf.compiler.Version + */ +export class Version extends Message { + /** + * @generated from field: optional int32 major = 1; + */ + major?: number; + + /** + * @generated from field: optional int32 minor = 2; + */ + minor?: number; + + /** + * @generated from field: optional int32 patch = 3; + */ + patch?: number; + + /** + * A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + * be empty for mainline stable releases. + * + * @generated from field: optional string suffix = 4; + */ + suffix?: string; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.compiler.Version"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "major", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "minor", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "patch", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "suffix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Version { + return new Version().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Version { + return new Version().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Version { + return new Version().fromJsonString(jsonString, options); + } + + static equals(a: Version | PlainMessage | undefined, b: Version | PlainMessage | undefined): boolean { + return proto2.util.equals(Version, a, b); + } +} + +/** + * An encoded CodeGeneratorRequest is written to the plugin's stdin. + * + * @generated from message google.protobuf.compiler.CodeGeneratorRequest + */ +export class CodeGeneratorRequest extends Message { + /** + * The .proto files that were explicitly listed on the command-line. The + * code generator should generate code only for these files. Each file's + * descriptor will be included in proto_file, below. + * + * @generated from field: repeated string file_to_generate = 1; + */ + fileToGenerate: string[] = []; + + /** + * The generator parameter passed on the command-line. + * + * @generated from field: optional string parameter = 2; + */ + parameter?: string; + + /** + * FileDescriptorProtos for all files in files_to_generate and everything + * they import. The files will appear in topological order, so each file + * appears before any file that imports it. + * + * protoc guarantees that all proto_files will be written after + * the fields above, even though this is not technically guaranteed by the + * protobuf wire format. This theoretically could allow a plugin to stream + * in the FileDescriptorProtos and handle them one by one rather than read + * the entire set into memory at once. However, as of this writing, this + * is not similarly optimized on protoc's end -- it will store all fields in + * memory at once before sending them to the plugin. + * + * Type names of fields and extensions in the FileDescriptorProto are always + * fully qualified. + * + * @generated from field: repeated google.protobuf.FileDescriptorProto proto_file = 15; + */ + protoFile: FileDescriptorProto[] = []; + + /** + * The version number of protocol compiler. + * + * @generated from field: optional google.protobuf.compiler.Version compiler_version = 3; + */ + compilerVersion?: Version; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorRequest"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "file_to_generate", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 2, name: "parameter", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 15, name: "proto_file", kind: "message", T: FileDescriptorProto, repeated: true }, + { no: 3, name: "compiler_version", kind: "message", T: Version, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorRequest { + return new CodeGeneratorRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorRequest { + return new CodeGeneratorRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorRequest { + return new CodeGeneratorRequest().fromJsonString(jsonString, options); + } + + static equals(a: CodeGeneratorRequest | PlainMessage | undefined, b: CodeGeneratorRequest | PlainMessage | undefined): boolean { + return proto2.util.equals(CodeGeneratorRequest, a, b); + } +} + +/** + * The plugin writes an encoded CodeGeneratorResponse to stdout. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse + */ +export class CodeGeneratorResponse extends Message { + /** + * Error message. If non-empty, code generation failed. The plugin process + * should exit with status code zero even if it reports an error in this way. + * + * This should be used to indicate errors in .proto files which prevent the + * code generator from generating correct code. Errors which indicate a + * problem in protoc itself -- such as the input CodeGeneratorRequest being + * unparseable -- should be reported by writing a message to stderr and + * exiting with a non-zero status code. + * + * @generated from field: optional string error = 1; + */ + error?: string; + + /** + * A bitmask of supported features that the code generator supports. + * This is a bitwise "or" of values from the Feature enum. + * + * @generated from field: optional uint64 supported_features = 2; + */ + supportedFeatures?: bigint; + + /** + * @generated from field: repeated google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + */ + file: CodeGeneratorResponse_File[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorResponse"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "error", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "supported_features", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 15, name: "file", kind: "message", T: CodeGeneratorResponse_File, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorResponse { + return new CodeGeneratorResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorResponse { + return new CodeGeneratorResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorResponse { + return new CodeGeneratorResponse().fromJsonString(jsonString, options); + } + + static equals(a: CodeGeneratorResponse | PlainMessage | undefined, b: CodeGeneratorResponse | PlainMessage | undefined): boolean { + return proto2.util.equals(CodeGeneratorResponse, a, b); + } +} + +/** + * Sync with code_generator.h. + * + * @generated from enum google.protobuf.compiler.CodeGeneratorResponse.Feature + */ +export enum CodeGeneratorResponse_Feature { + /** + * @generated from enum value: FEATURE_NONE = 0; + */ + NONE = 0, + + /** + * @generated from enum value: FEATURE_PROTO3_OPTIONAL = 1; + */ + PROTO3_OPTIONAL = 1, +} +// Retrieve enum metadata with: proto2.getEnumType(CodeGeneratorResponse_Feature) +proto2.util.setEnumType(CodeGeneratorResponse_Feature, "google.protobuf.compiler.CodeGeneratorResponse.Feature", [ + { no: 0, name: "FEATURE_NONE" }, + { no: 1, name: "FEATURE_PROTO3_OPTIONAL" }, +]); + +/** + * Represents a single generated file. + * + * @generated from message google.protobuf.compiler.CodeGeneratorResponse.File + */ +export class CodeGeneratorResponse_File extends Message { + /** + * The file name, relative to the output directory. The name must not + * contain "." or ".." components and must be relative, not be absolute (so, + * the file cannot lie outside the output directory). "/" must be used as + * the path separator, not "\". + * + * If the name is omitted, the content will be appended to the previous + * file. This allows the generator to break large files into small chunks, + * and allows the generated text to be streamed back to protoc so that large + * files need not reside completely in memory at one time. Note that as of + * this writing protoc does not optimize for this -- it will read the entire + * CodeGeneratorResponse before writing files to disk. + * + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * If non-empty, indicates that the named file should already exist, and the + * content here is to be inserted into that file at a defined insertion + * point. This feature allows a code generator to extend the output + * produced by another code generator. The original generator may provide + * insertion points by placing special annotations in the file that look + * like: + * @@protoc_insertion_point(NAME) + * The annotation can have arbitrary text before and after it on the line, + * which allows it to be placed in a comment. NAME should be replaced with + * an identifier naming the point -- this is what other generators will use + * as the insertion_point. Code inserted at this point will be placed + * immediately above the line containing the insertion point (thus multiple + * insertions to the same point will come out in the order they were added). + * The double-@ is intended to make it unlikely that the generated code + * could contain things that look like insertion points by accident. + * + * For example, the C++ code generator places the following line in the + * .pb.h files that it generates: + * // @@protoc_insertion_point(namespace_scope) + * This line appears within the scope of the file's package namespace, but + * outside of any particular class. Another plugin can then specify the + * insertion_point "namespace_scope" to generate additional classes or + * other declarations that should be placed in this scope. + * + * Note that if the line containing the insertion point begins with + * whitespace, the same whitespace will be added to every line of the + * inserted text. This is useful for languages like Python, where + * indentation matters. In these languages, the insertion point comment + * should be indented the same amount as any inserted code will need to be + * in order to work correctly in that context. + * + * The code generator that generates the initial file and the one which + * inserts into it must both run as part of a single invocation of protoc. + * Code generators are executed in the order in which they appear on the + * command line. + * + * If |insertion_point| is present, |name| must also be present. + * + * @generated from field: optional string insertion_point = 2; + */ + insertionPoint?: string; + + /** + * The file contents. + * + * @generated from field: optional string content = 15; + */ + content?: string; + + /** + * Information describing the file content being inserted. If an insertion + * point is used, this information will be appropriately offset and inserted + * into the code generation metadata for the generated files. + * + * @generated from field: optional google.protobuf.GeneratedCodeInfo generated_code_info = 16; + */ + generatedCodeInfo?: GeneratedCodeInfo; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.compiler.CodeGeneratorResponse.File"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "insertion_point", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 15, name: "content", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 16, name: "generated_code_info", kind: "message", T: GeneratedCodeInfo, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CodeGeneratorResponse_File { + return new CodeGeneratorResponse_File().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CodeGeneratorResponse_File { + return new CodeGeneratorResponse_File().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CodeGeneratorResponse_File { + return new CodeGeneratorResponse_File().fromJsonString(jsonString, options); + } + + static equals(a: CodeGeneratorResponse_File | PlainMessage | undefined, b: CodeGeneratorResponse_File | PlainMessage | undefined): boolean { + return proto2.util.equals(CodeGeneratorResponse_File, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/descriptor_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/descriptor_pb.ts new file mode 100644 index 000000000..1d5022742 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/descriptor_pb.ts @@ -0,0 +1,2460 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/descriptor.proto (package google.protobuf, syntax proto2) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto2} from "@bufbuild/protobuf"; + +/** + * The protocol compiler can output a FileDescriptorSet containing the .proto + * files it parses. + * + * @generated from message google.protobuf.FileDescriptorSet + */ +export class FileDescriptorSet extends Message { + /** + * @generated from field: repeated google.protobuf.FileDescriptorProto file = 1; + */ + file: FileDescriptorProto[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.FileDescriptorSet"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "file", kind: "message", T: FileDescriptorProto, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FileDescriptorSet { + return new FileDescriptorSet().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FileDescriptorSet { + return new FileDescriptorSet().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FileDescriptorSet { + return new FileDescriptorSet().fromJsonString(jsonString, options); + } + + static equals(a: FileDescriptorSet | PlainMessage | undefined, b: FileDescriptorSet | PlainMessage | undefined): boolean { + return proto2.util.equals(FileDescriptorSet, a, b); + } +} + +/** + * Describes a complete .proto file. + * + * @generated from message google.protobuf.FileDescriptorProto + */ +export class FileDescriptorProto extends Message { + /** + * file name, relative to root of source tree + * + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * e.g. "foo", "foo.bar", etc. + * + * @generated from field: optional string package = 2; + */ + package?: string; + + /** + * Names of files imported by this file. + * + * @generated from field: repeated string dependency = 3; + */ + dependency: string[] = []; + + /** + * Indexes of the public imported files in the dependency list above. + * + * @generated from field: repeated int32 public_dependency = 10; + */ + publicDependency: number[] = []; + + /** + * Indexes of the weak imported files in the dependency list. + * For Google-internal migration only. Do not use. + * + * @generated from field: repeated int32 weak_dependency = 11; + */ + weakDependency: number[] = []; + + /** + * All top-level definitions in this file. + * + * @generated from field: repeated google.protobuf.DescriptorProto message_type = 4; + */ + messageType: DescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.EnumDescriptorProto enum_type = 5; + */ + enumType: EnumDescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.ServiceDescriptorProto service = 6; + */ + service: ServiceDescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto extension = 7; + */ + extension: FieldDescriptorProto[] = []; + + /** + * @generated from field: optional google.protobuf.FileOptions options = 8; + */ + options?: FileOptions; + + /** + * This field contains optional information about the original source code. + * You may safely remove this entire field without harming runtime + * functionality of the descriptors -- the information is needed only by + * development tools. + * + * @generated from field: optional google.protobuf.SourceCodeInfo source_code_info = 9; + */ + sourceCodeInfo?: SourceCodeInfo; + + /** + * The syntax of the proto file. + * The supported values are "proto2" and "proto3". + * + * @generated from field: optional string syntax = 12; + */ + syntax?: string; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.FileDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "dependency", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + { no: 10, name: "public_dependency", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 11, name: "weak_dependency", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true }, + { no: 4, name: "message_type", kind: "message", T: DescriptorProto, repeated: true }, + { no: 5, name: "enum_type", kind: "message", T: EnumDescriptorProto, repeated: true }, + { no: 6, name: "service", kind: "message", T: ServiceDescriptorProto, repeated: true }, + { no: 7, name: "extension", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 8, name: "options", kind: "message", T: FileOptions, opt: true }, + { no: 9, name: "source_code_info", kind: "message", T: SourceCodeInfo, opt: true }, + { no: 12, name: "syntax", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FileDescriptorProto { + return new FileDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FileDescriptorProto { + return new FileDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FileDescriptorProto { + return new FileDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: FileDescriptorProto | PlainMessage | undefined, b: FileDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(FileDescriptorProto, a, b); + } +} + +/** + * Describes a message type. + * + * @generated from message google.protobuf.DescriptorProto + */ +export class DescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto field = 2; + */ + field: FieldDescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.FieldDescriptorProto extension = 6; + */ + extension: FieldDescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto nested_type = 3; + */ + nestedType: DescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.EnumDescriptorProto enum_type = 4; + */ + enumType: EnumDescriptorProto[] = []; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + */ + extensionRange: DescriptorProto_ExtensionRange[] = []; + + /** + * @generated from field: repeated google.protobuf.OneofDescriptorProto oneof_decl = 8; + */ + oneofDecl: OneofDescriptorProto[] = []; + + /** + * @generated from field: optional google.protobuf.MessageOptions options = 7; + */ + options?: MessageOptions; + + /** + * @generated from field: repeated google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + */ + reservedRange: DescriptorProto_ReservedRange[] = []; + + /** + * Reserved field names, which may not be used by fields in the same message. + * A given name may only be reserved once. + * + * @generated from field: repeated string reserved_name = 10; + */ + reservedName: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.DescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "field", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 6, name: "extension", kind: "message", T: FieldDescriptorProto, repeated: true }, + { no: 3, name: "nested_type", kind: "message", T: DescriptorProto, repeated: true }, + { no: 4, name: "enum_type", kind: "message", T: EnumDescriptorProto, repeated: true }, + { no: 5, name: "extension_range", kind: "message", T: DescriptorProto_ExtensionRange, repeated: true }, + { no: 8, name: "oneof_decl", kind: "message", T: OneofDescriptorProto, repeated: true }, + { no: 7, name: "options", kind: "message", T: MessageOptions, opt: true }, + { no: 9, name: "reserved_range", kind: "message", T: DescriptorProto_ReservedRange, repeated: true }, + { no: 10, name: "reserved_name", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto { + return new DescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto { + return new DescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto { + return new DescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: DescriptorProto | PlainMessage | undefined, b: DescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(DescriptorProto, a, b); + } +} + +/** + * @generated from message google.protobuf.DescriptorProto.ExtensionRange + */ +export class DescriptorProto_ExtensionRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Exclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + /** + * @generated from field: optional google.protobuf.ExtensionRangeOptions options = 3; + */ + options?: ExtensionRangeOptions; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.DescriptorProto.ExtensionRange"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "options", kind: "message", T: ExtensionRangeOptions, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto_ExtensionRange { + return new DescriptorProto_ExtensionRange().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto_ExtensionRange { + return new DescriptorProto_ExtensionRange().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto_ExtensionRange { + return new DescriptorProto_ExtensionRange().fromJsonString(jsonString, options); + } + + static equals(a: DescriptorProto_ExtensionRange | PlainMessage | undefined, b: DescriptorProto_ExtensionRange | PlainMessage | undefined): boolean { + return proto2.util.equals(DescriptorProto_ExtensionRange, a, b); + } +} + +/** + * Range of reserved tag numbers. Reserved tag numbers may not be used by + * fields or extension ranges in the same message. Reserved ranges may + * not overlap. + * + * @generated from message google.protobuf.DescriptorProto.ReservedRange + */ +export class DescriptorProto_ReservedRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Exclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.DescriptorProto.ReservedRange"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DescriptorProto_ReservedRange { + return new DescriptorProto_ReservedRange().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DescriptorProto_ReservedRange { + return new DescriptorProto_ReservedRange().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DescriptorProto_ReservedRange { + return new DescriptorProto_ReservedRange().fromJsonString(jsonString, options); + } + + static equals(a: DescriptorProto_ReservedRange | PlainMessage | undefined, b: DescriptorProto_ReservedRange | PlainMessage | undefined): boolean { + return proto2.util.equals(DescriptorProto_ReservedRange, a, b); + } +} + +/** + * @generated from message google.protobuf.ExtensionRangeOptions + */ +export class ExtensionRangeOptions extends Message { + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.ExtensionRangeOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ExtensionRangeOptions { + return new ExtensionRangeOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ExtensionRangeOptions { + return new ExtensionRangeOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ExtensionRangeOptions { + return new ExtensionRangeOptions().fromJsonString(jsonString, options); + } + + static equals(a: ExtensionRangeOptions | PlainMessage | undefined, b: ExtensionRangeOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(ExtensionRangeOptions, a, b); + } +} + +/** + * Describes a field within a message. + * + * @generated from message google.protobuf.FieldDescriptorProto + */ +export class FieldDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional int32 number = 3; + */ + number?: number; + + /** + * @generated from field: optional google.protobuf.FieldDescriptorProto.Label label = 4; + */ + label?: FieldDescriptorProto_Label; + + /** + * If type_name is set, this need not be set. If both this and type_name + * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + * + * @generated from field: optional google.protobuf.FieldDescriptorProto.Type type = 5; + */ + type?: FieldDescriptorProto_Type; + + /** + * For message and enum types, this is the name of the type. If the name + * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + * rules are used to find the type (i.e. first the nested types within this + * message are searched, then within the parent, on up to the root + * namespace). + * + * @generated from field: optional string type_name = 6; + */ + typeName?: string; + + /** + * For extensions, this is the name of the type being extended. It is + * resolved in the same manner as type_name. + * + * @generated from field: optional string extendee = 2; + */ + extendee?: string; + + /** + * For numeric types, contains the original text representation of the value. + * For booleans, "true" or "false". + * For strings, contains the default text contents (not escaped in any way). + * For bytes, contains the C escaped value. All bytes >= 128 are escaped. + * + * @generated from field: optional string default_value = 7; + */ + defaultValue?: string; + + /** + * If set, gives the index of a oneof in the containing type's oneof_decl + * list. This field is a member of that oneof. + * + * @generated from field: optional int32 oneof_index = 9; + */ + oneofIndex?: number; + + /** + * JSON name of this field. The value is set by protocol compiler. If the + * user has set a "json_name" option on this field, that option's value + * will be used. Otherwise, it's deduced from the field's name by converting + * it to camelCase. + * + * @generated from field: optional string json_name = 10; + */ + jsonName?: string; + + /** + * @generated from field: optional google.protobuf.FieldOptions options = 8; + */ + options?: FieldOptions; + + /** + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * + * @generated from field: optional bool proto3_optional = 17; + */ + proto3Optional?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.FieldDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "number", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "label", kind: "enum", T: proto2.getEnumType(FieldDescriptorProto_Label), opt: true }, + { no: 5, name: "type", kind: "enum", T: proto2.getEnumType(FieldDescriptorProto_Type), opt: true }, + { no: 6, name: "type_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "extendee", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 7, name: "default_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 9, name: "oneof_index", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 10, name: "json_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 8, name: "options", kind: "message", T: FieldOptions, opt: true }, + { no: 17, name: "proto3_optional", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldDescriptorProto { + return new FieldDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldDescriptorProto { + return new FieldDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FieldDescriptorProto { + return new FieldDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: FieldDescriptorProto | PlainMessage | undefined, b: FieldDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(FieldDescriptorProto, a, b); + } +} + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Type + */ +export enum FieldDescriptorProto_Type { + /** + * 0 is reserved for errors. + * Order is weird for historical reasons. + * + * @generated from enum value: TYPE_DOUBLE = 1; + */ + DOUBLE = 1, + + /** + * @generated from enum value: TYPE_FLOAT = 2; + */ + FLOAT = 2, + + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + * negative values are likely. + * + * @generated from enum value: TYPE_INT64 = 3; + */ + INT64 = 3, + + /** + * @generated from enum value: TYPE_UINT64 = 4; + */ + UINT64 = 4, + + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + * negative values are likely. + * + * @generated from enum value: TYPE_INT32 = 5; + */ + INT32 = 5, + + /** + * @generated from enum value: TYPE_FIXED64 = 6; + */ + FIXED64 = 6, + + /** + * @generated from enum value: TYPE_FIXED32 = 7; + */ + FIXED32 = 7, + + /** + * @generated from enum value: TYPE_BOOL = 8; + */ + BOOL = 8, + + /** + * @generated from enum value: TYPE_STRING = 9; + */ + STRING = 9, + + /** + * Tag-delimited aggregate. + * Group type is deprecated and not supported in proto3. However, Proto3 + * implementations should still be able to parse the group wire format and + * treat group fields as unknown fields. + * + * @generated from enum value: TYPE_GROUP = 10; + */ + GROUP = 10, + + /** + * Length-delimited aggregate. + * + * @generated from enum value: TYPE_MESSAGE = 11; + */ + MESSAGE = 11, + + /** + * New in version 2. + * + * @generated from enum value: TYPE_BYTES = 12; + */ + BYTES = 12, + + /** + * @generated from enum value: TYPE_UINT32 = 13; + */ + UINT32 = 13, + + /** + * @generated from enum value: TYPE_ENUM = 14; + */ + ENUM = 14, + + /** + * @generated from enum value: TYPE_SFIXED32 = 15; + */ + SFIXED32 = 15, + + /** + * @generated from enum value: TYPE_SFIXED64 = 16; + */ + SFIXED64 = 16, + + /** + * Uses ZigZag encoding. + * + * @generated from enum value: TYPE_SINT32 = 17; + */ + SINT32 = 17, + + /** + * Uses ZigZag encoding. + * + * @generated from enum value: TYPE_SINT64 = 18; + */ + SINT64 = 18, +} +// Retrieve enum metadata with: proto2.getEnumType(FieldDescriptorProto_Type) +proto2.util.setEnumType(FieldDescriptorProto_Type, "google.protobuf.FieldDescriptorProto.Type", [ + { no: 1, name: "TYPE_DOUBLE" }, + { no: 2, name: "TYPE_FLOAT" }, + { no: 3, name: "TYPE_INT64" }, + { no: 4, name: "TYPE_UINT64" }, + { no: 5, name: "TYPE_INT32" }, + { no: 6, name: "TYPE_FIXED64" }, + { no: 7, name: "TYPE_FIXED32" }, + { no: 8, name: "TYPE_BOOL" }, + { no: 9, name: "TYPE_STRING" }, + { no: 10, name: "TYPE_GROUP" }, + { no: 11, name: "TYPE_MESSAGE" }, + { no: 12, name: "TYPE_BYTES" }, + { no: 13, name: "TYPE_UINT32" }, + { no: 14, name: "TYPE_ENUM" }, + { no: 15, name: "TYPE_SFIXED32" }, + { no: 16, name: "TYPE_SFIXED64" }, + { no: 17, name: "TYPE_SINT32" }, + { no: 18, name: "TYPE_SINT64" }, +]); + +/** + * @generated from enum google.protobuf.FieldDescriptorProto.Label + */ +export enum FieldDescriptorProto_Label { + /** + * 0 is reserved for errors + * + * @generated from enum value: LABEL_OPTIONAL = 1; + */ + OPTIONAL = 1, + + /** + * @generated from enum value: LABEL_REQUIRED = 2; + */ + REQUIRED = 2, + + /** + * @generated from enum value: LABEL_REPEATED = 3; + */ + REPEATED = 3, +} +// Retrieve enum metadata with: proto2.getEnumType(FieldDescriptorProto_Label) +proto2.util.setEnumType(FieldDescriptorProto_Label, "google.protobuf.FieldDescriptorProto.Label", [ + { no: 1, name: "LABEL_OPTIONAL" }, + { no: 2, name: "LABEL_REQUIRED" }, + { no: 3, name: "LABEL_REPEATED" }, +]); + +/** + * Describes a oneof. + * + * @generated from message google.protobuf.OneofDescriptorProto + */ +export class OneofDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional google.protobuf.OneofOptions options = 2; + */ + options?: OneofOptions; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.OneofDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "options", kind: "message", T: OneofOptions, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OneofDescriptorProto { + return new OneofDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OneofDescriptorProto { + return new OneofDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OneofDescriptorProto { + return new OneofDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: OneofDescriptorProto | PlainMessage | undefined, b: OneofDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(OneofDescriptorProto, a, b); + } +} + +/** + * Describes an enum type. + * + * @generated from message google.protobuf.EnumDescriptorProto + */ +export class EnumDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.EnumValueDescriptorProto value = 2; + */ + value: EnumValueDescriptorProto[] = []; + + /** + * @generated from field: optional google.protobuf.EnumOptions options = 3; + */ + options?: EnumOptions; + + /** + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * + * @generated from field: repeated google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + */ + reservedRange: EnumDescriptorProto_EnumReservedRange[] = []; + + /** + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * + * @generated from field: repeated string reserved_name = 5; + */ + reservedName: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.EnumDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "value", kind: "message", T: EnumValueDescriptorProto, repeated: true }, + { no: 3, name: "options", kind: "message", T: EnumOptions, opt: true }, + { no: 4, name: "reserved_range", kind: "message", T: EnumDescriptorProto_EnumReservedRange, repeated: true }, + { no: 5, name: "reserved_name", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumDescriptorProto { + return new EnumDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumDescriptorProto { + return new EnumDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumDescriptorProto { + return new EnumDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: EnumDescriptorProto | PlainMessage | undefined, b: EnumDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumDescriptorProto, a, b); + } +} + +/** + * Range of reserved numeric values. Reserved values may not be used by + * entries in the same enum. Reserved ranges may not overlap. + * + * Note that this is distinct from DescriptorProto.ReservedRange in that it + * is inclusive such that it can appropriately represent the entire int32 + * domain. + * + * @generated from message google.protobuf.EnumDescriptorProto.EnumReservedRange + */ +export class EnumDescriptorProto_EnumReservedRange extends Message { + /** + * Inclusive. + * + * @generated from field: optional int32 start = 1; + */ + start?: number; + + /** + * Inclusive. + * + * @generated from field: optional int32 end = 2; + */ + end?: number; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.EnumDescriptorProto.EnumReservedRange"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "start", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 2, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumDescriptorProto_EnumReservedRange { + return new EnumDescriptorProto_EnumReservedRange().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumDescriptorProto_EnumReservedRange { + return new EnumDescriptorProto_EnumReservedRange().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumDescriptorProto_EnumReservedRange { + return new EnumDescriptorProto_EnumReservedRange().fromJsonString(jsonString, options); + } + + static equals(a: EnumDescriptorProto_EnumReservedRange | PlainMessage | undefined, b: EnumDescriptorProto_EnumReservedRange | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumDescriptorProto_EnumReservedRange, a, b); + } +} + +/** + * Describes a value within an enum. + * + * @generated from message google.protobuf.EnumValueDescriptorProto + */ +export class EnumValueDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: optional int32 number = 2; + */ + number?: number; + + /** + * @generated from field: optional google.protobuf.EnumValueOptions options = 3; + */ + options?: EnumValueOptions; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.EnumValueDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "number", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 3, name: "options", kind: "message", T: EnumValueOptions, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumValueDescriptorProto { + return new EnumValueDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumValueDescriptorProto { + return new EnumValueDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumValueDescriptorProto { + return new EnumValueDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: EnumValueDescriptorProto | PlainMessage | undefined, b: EnumValueDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumValueDescriptorProto, a, b); + } +} + +/** + * Describes a service. + * + * @generated from message google.protobuf.ServiceDescriptorProto + */ +export class ServiceDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * @generated from field: repeated google.protobuf.MethodDescriptorProto method = 2; + */ + method: MethodDescriptorProto[] = []; + + /** + * @generated from field: optional google.protobuf.ServiceOptions options = 3; + */ + options?: ServiceOptions; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.ServiceDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "method", kind: "message", T: MethodDescriptorProto, repeated: true }, + { no: 3, name: "options", kind: "message", T: ServiceOptions, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ServiceDescriptorProto { + return new ServiceDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ServiceDescriptorProto { + return new ServiceDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ServiceDescriptorProto { + return new ServiceDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: ServiceDescriptorProto | PlainMessage | undefined, b: ServiceDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(ServiceDescriptorProto, a, b); + } +} + +/** + * Describes a method of a service. + * + * @generated from message google.protobuf.MethodDescriptorProto + */ +export class MethodDescriptorProto extends Message { + /** + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * Input and output type names. These are resolved in the same way as + * FieldDescriptorProto.type_name, but must refer to a message type. + * + * @generated from field: optional string input_type = 2; + */ + inputType?: string; + + /** + * @generated from field: optional string output_type = 3; + */ + outputType?: string; + + /** + * @generated from field: optional google.protobuf.MethodOptions options = 4; + */ + options?: MethodOptions; + + /** + * Identifies if client streams multiple client messages + * + * @generated from field: optional bool client_streaming = 5 [default = false]; + */ + clientStreaming?: boolean; + + /** + * Identifies if server streams multiple server messages + * + * @generated from field: optional bool server_streaming = 6 [default = false]; + */ + serverStreaming?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.MethodDescriptorProto"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "input_type", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "output_type", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "options", kind: "message", T: MethodOptions, opt: true }, + { no: 5, name: "client_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 6, name: "server_streaming", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MethodDescriptorProto { + return new MethodDescriptorProto().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MethodDescriptorProto { + return new MethodDescriptorProto().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MethodDescriptorProto { + return new MethodDescriptorProto().fromJsonString(jsonString, options); + } + + static equals(a: MethodDescriptorProto | PlainMessage | undefined, b: MethodDescriptorProto | PlainMessage | undefined): boolean { + return proto2.util.equals(MethodDescriptorProto, a, b); + } +} + +/** + * @generated from message google.protobuf.FileOptions + */ +export class FileOptions extends Message { + /** + * Sets the Java package where classes generated from this .proto will be + * placed. By default, the proto package is used, but this is often + * inappropriate because proto packages do not normally start with backwards + * domain names. + * + * @generated from field: optional string java_package = 1; + */ + javaPackage?: string; + + /** + * Controls the name of the wrapper Java class generated for the .proto file. + * That class will always contain the .proto file's getDescriptor() method as + * well as any top-level extensions defined in the .proto file. + * If java_multiple_files is disabled, then all the other classes from the + * .proto file will be nested inside the single wrapper outer class. + * + * @generated from field: optional string java_outer_classname = 8; + */ + javaOuterClassname?: string; + + /** + * If enabled, then the Java code generator will generate a separate .java + * file for each top-level message, enum, and service defined in the .proto + * file. Thus, these types will *not* be nested inside the wrapper class + * named by java_outer_classname. However, the wrapper class will still be + * generated to contain the file's getDescriptor() method as well as any + * top-level extensions defined in the file. + * + * @generated from field: optional bool java_multiple_files = 10 [default = false]; + */ + javaMultipleFiles?: boolean; + + /** + * This option does nothing. + * + * @generated from field: optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + * @deprecated + */ + javaGenerateEqualsAndHash?: boolean; + + /** + * If set true, then the Java2 code generator will generate code that + * throws an exception whenever an attempt is made to assign a non-UTF-8 + * byte sequence to a string field. + * Message reflection will do the same. + * However, an extension field still accepts non-UTF-8 byte sequences. + * This option has no effect on when used with the lite runtime. + * + * @generated from field: optional bool java_string_check_utf8 = 27 [default = false]; + */ + javaStringCheckUtf8?: boolean; + + /** + * @generated from field: optional google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + */ + optimizeFor?: FileOptions_OptimizeMode; + + /** + * Sets the Go package where structs generated from this .proto will be + * placed. If omitted, the Go package will be derived from the following: + * - The basename of the package import path, if provided. + * - Otherwise, the package statement in the .proto file, if present. + * - Otherwise, the basename of the .proto file, without extension. + * + * @generated from field: optional string go_package = 11; + */ + goPackage?: string; + + /** + * Should generic services be generated in each language? "Generic" services + * are not specific to any particular RPC system. They are generated by the + * main code generators in each language (without additional plugins). + * Generic services were the only kind of service generation supported by + * early versions of google.protobuf. + * + * Generic services are now considered deprecated in favor of using plugins + * that generate code specific to your particular RPC system. Therefore, + * these default to false. Old code which depends on generic services should + * explicitly set them to true. + * + * @generated from field: optional bool cc_generic_services = 16 [default = false]; + */ + ccGenericServices?: boolean; + + /** + * @generated from field: optional bool java_generic_services = 17 [default = false]; + */ + javaGenericServices?: boolean; + + /** + * @generated from field: optional bool py_generic_services = 18 [default = false]; + */ + pyGenericServices?: boolean; + + /** + * @generated from field: optional bool php_generic_services = 42 [default = false]; + */ + phpGenericServices?: boolean; + + /** + * Is this file deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for everything in the file, or it will be completely ignored; in the very + * least, this is a formalization for deprecating files. + * + * @generated from field: optional bool deprecated = 23 [default = false]; + */ + deprecated?: boolean; + + /** + * Enables the use of arenas for the proto messages in this file. This applies + * only to generated classes for C++. + * + * @generated from field: optional bool cc_enable_arenas = 31 [default = true]; + */ + ccEnableArenas?: boolean; + + /** + * Sets the objective c class prefix which is prepended to all objective c + * generated classes from this .proto. There is no default. + * + * @generated from field: optional string objc_class_prefix = 36; + */ + objcClassPrefix?: string; + + /** + * Namespace for generated classes; defaults to the package. + * + * @generated from field: optional string csharp_namespace = 37; + */ + csharpNamespace?: string; + + /** + * By default Swift generators will take the proto package and CamelCase it + * replacing '.' with underscore and use that to prefix the types/symbols + * defined. When this options is provided, they will use this value instead + * to prefix the types/symbols defined. + * + * @generated from field: optional string swift_prefix = 39; + */ + swiftPrefix?: string; + + /** + * Sets the php class prefix which is prepended to all php generated classes + * from this .proto. Default is empty. + * + * @generated from field: optional string php_class_prefix = 40; + */ + phpClassPrefix?: string; + + /** + * Use this option to change the namespace of php generated classes. Default + * is empty. When this option is empty, the package name will be used for + * determining the namespace. + * + * @generated from field: optional string php_namespace = 41; + */ + phpNamespace?: string; + + /** + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * + * @generated from field: optional string php_metadata_namespace = 44; + */ + phpMetadataNamespace?: string; + + /** + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * + * @generated from field: optional string ruby_package = 45; + */ + rubyPackage?: string; + + /** + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.FileOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "java_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 8, name: "java_outer_classname", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 10, name: "java_multiple_files", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 20, name: "java_generate_equals_and_hash", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 27, name: "java_string_check_utf8", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 9, name: "optimize_for", kind: "enum", T: proto2.getEnumType(FileOptions_OptimizeMode), opt: true, default: FileOptions_OptimizeMode.SPEED }, + { no: 11, name: "go_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 16, name: "cc_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 17, name: "java_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 18, name: "py_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 42, name: "php_generic_services", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 23, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 31, name: "cc_enable_arenas", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, + { no: 36, name: "objc_class_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 37, name: "csharp_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 39, name: "swift_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 40, name: "php_class_prefix", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 41, name: "php_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 44, name: "php_metadata_namespace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 45, name: "ruby_package", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FileOptions { + return new FileOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FileOptions { + return new FileOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FileOptions { + return new FileOptions().fromJsonString(jsonString, options); + } + + static equals(a: FileOptions | PlainMessage | undefined, b: FileOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(FileOptions, a, b); + } +} + +/** + * Generated classes can be optimized for speed or code size. + * + * @generated from enum google.protobuf.FileOptions.OptimizeMode + */ +export enum FileOptions_OptimizeMode { + /** + * Generate complete code for parsing, serialization, + * + * @generated from enum value: SPEED = 1; + */ + SPEED = 1, + + /** + * etc. + * + * Use ReflectionOps to implement these methods. + * + * @generated from enum value: CODE_SIZE = 2; + */ + CODE_SIZE = 2, + + /** + * Generate code using MessageLite and the lite runtime. + * + * @generated from enum value: LITE_RUNTIME = 3; + */ + LITE_RUNTIME = 3, +} +// Retrieve enum metadata with: proto2.getEnumType(FileOptions_OptimizeMode) +proto2.util.setEnumType(FileOptions_OptimizeMode, "google.protobuf.FileOptions.OptimizeMode", [ + { no: 1, name: "SPEED" }, + { no: 2, name: "CODE_SIZE" }, + { no: 3, name: "LITE_RUNTIME" }, +]); + +/** + * @generated from message google.protobuf.MessageOptions + */ +export class MessageOptions extends Message { + /** + * Set true to use the old proto1 MessageSet wire format for extensions. + * This is provided for backwards-compatibility with the MessageSet wire + * format. You should not use this for any other reason: It's less + * efficient, has fewer features, and is more complicated. + * + * The message must be defined exactly as follows: + * message Foo { + * option message_set_wire_format = true; + * extensions 4 to max; + * } + * Note that the message cannot have any defined fields; MessageSets only + * have extensions. + * + * All extensions of your type must be singular messages; e.g. they cannot + * be int32s, enums, or repeated messages. + * + * Because this is an option, the above two restrictions are not enforced by + * the protocol compiler. + * + * @generated from field: optional bool message_set_wire_format = 1 [default = false]; + */ + messageSetWireFormat?: boolean; + + /** + * Disables the generation of the standard "descriptor()" accessor, which can + * conflict with a field of the same name. This is meant to make migration + * from proto1 easier; new code should avoid fields named "descriptor". + * + * @generated from field: optional bool no_standard_descriptor_accessor = 2 [default = false]; + */ + noStandardDescriptorAccessor?: boolean; + + /** + * Is this message deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the message, or it will be completely ignored; in the very least, + * this is a formalization for deprecating messages. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * Whether the message is an automatically generated map entry type for the + * maps field. + * + * For maps fields: + * map map_field = 1; + * The parsed descriptor looks like: + * message MapFieldEntry { + * option map_entry = true; + * optional KeyType key = 1; + * optional ValueType value = 2; + * } + * repeated MapFieldEntry map_field = 1; + * + * Implementations may choose not to generate the map_entry=true message, but + * use a native map in the target language to hold the keys and values. + * The reflection APIs in such implementations still need to work as + * if the field is a repeated message field. + * + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. + * + * @generated from field: optional bool map_entry = 7; + */ + mapEntry?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.MessageOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "message_set_wire_format", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 2, name: "no_standard_descriptor_accessor", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 7, name: "map_entry", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MessageOptions { + return new MessageOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MessageOptions { + return new MessageOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MessageOptions { + return new MessageOptions().fromJsonString(jsonString, options); + } + + static equals(a: MessageOptions | PlainMessage | undefined, b: MessageOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(MessageOptions, a, b); + } +} + +/** + * @generated from message google.protobuf.FieldOptions + */ +export class FieldOptions extends Message { + /** + * The ctype option instructs the C++ code generator to use a different + * representation of the field than it normally would. See the specific + * options below. This option is not yet implemented in the open source + * release -- sorry, we'll try to include it in a future version! + * + * @generated from field: optional google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + */ + ctype?: FieldOptions_CType; + + /** + * The packed option can be enabled for repeated primitive fields to enable + * a more efficient representation on the wire. Rather than repeatedly + * writing the tag and type for each element, the entire array is encoded as + * a single length-delimited blob. In proto3, only explicit setting it to + * false will avoid using packed encoding. + * + * @generated from field: optional bool packed = 2; + */ + packed?: boolean; + + /** + * The jstype option determines the JavaScript type used for values of the + * field. The option is permitted only for 64 bit integral and fixed types + * (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + * is represented as JavaScript string, which avoids loss of precision that + * can happen when a large value is converted to a floating point JavaScript. + * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + * use the JavaScript "number" type. The behavior of the default option + * JS_NORMAL is implementation dependent. + * + * This option is an enum to permit additional types to be added, e.g. + * goog.math.Integer. + * + * @generated from field: optional google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + */ + jstype?: FieldOptions_JSType; + + /** + * Should this field be parsed lazily? Lazy applies only to message-type + * fields. It means that when the outer message is initially parsed, the + * inner message's contents will not be parsed but instead stored in encoded + * form. The inner message will actually be parsed when it is first accessed. + * + * This is only a hint. Implementations are free to choose whether to use + * eager or lazy parsing regardless of the value of this option. However, + * setting this option true suggests that the protocol author believes that + * using lazy parsing on this field is worth the additional bookkeeping + * overhead typically needed to implement it. + * + * This option does not affect the public interface of any generated code; + * all method signatures remain the same. Furthermore, thread-safety of the + * interface is not affected by this option; const methods remain safe to + * call from multiple threads concurrently, while non-const methods continue + * to require exclusive access. + * + * + * Note that implementations may choose not to check required fields within + * a lazy sub-message. That is, calling IsInitialized() on the outer message + * may return true even if the inner message has missing required fields. + * This is necessary because otherwise the inner message would have to be + * parsed in order to perform the check, defeating the purpose of lazy + * parsing. An implementation which chooses not to check required fields + * must be consistent about it. That is, for any particular sub-message, the + * implementation must either *always* check its required fields, or *never* + * check its required fields, regardless of whether or not the message has + * been parsed. + * + * As of 2021, lazy does no correctness checks on the byte stream during + * parsing. This may lead to crashes if and when an invalid byte stream is + * finally parsed upon access. + * + * TODO(b/211906113): Enable validation on lazy fields. + * + * @generated from field: optional bool lazy = 5 [default = false]; + */ + lazy?: boolean; + + /** + * unverified_lazy does no correctness checks on the byte stream. This should + * only be used where lazy with verification is prohibitive for performance + * reasons. + * + * @generated from field: optional bool unverified_lazy = 15 [default = false]; + */ + unverifiedLazy?: boolean; + + /** + * Is this field deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for accessors, or it will be completely ignored; in the very least, this + * is a formalization for deprecating fields. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * For Google-internal migration only. Do not use. + * + * @generated from field: optional bool weak = 10 [default = false]; + */ + weak?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.FieldOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "ctype", kind: "enum", T: proto2.getEnumType(FieldOptions_CType), opt: true, default: FieldOptions_CType.STRING }, + { no: 2, name: "packed", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 6, name: "jstype", kind: "enum", T: proto2.getEnumType(FieldOptions_JSType), opt: true, default: FieldOptions_JSType.JS_NORMAL }, + { no: 5, name: "lazy", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 15, name: "unverified_lazy", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 10, name: "weak", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldOptions { + return new FieldOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldOptions { + return new FieldOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FieldOptions { + return new FieldOptions().fromJsonString(jsonString, options); + } + + static equals(a: FieldOptions | PlainMessage | undefined, b: FieldOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(FieldOptions, a, b); + } +} + +/** + * @generated from enum google.protobuf.FieldOptions.CType + */ +export enum FieldOptions_CType { + /** + * Default mode. + * + * @generated from enum value: STRING = 0; + */ + STRING = 0, + + /** + * @generated from enum value: CORD = 1; + */ + CORD = 1, + + /** + * @generated from enum value: STRING_PIECE = 2; + */ + STRING_PIECE = 2, +} +// Retrieve enum metadata with: proto2.getEnumType(FieldOptions_CType) +proto2.util.setEnumType(FieldOptions_CType, "google.protobuf.FieldOptions.CType", [ + { no: 0, name: "STRING" }, + { no: 1, name: "CORD" }, + { no: 2, name: "STRING_PIECE" }, +]); + +/** + * @generated from enum google.protobuf.FieldOptions.JSType + */ +export enum FieldOptions_JSType { + /** + * Use the default type. + * + * @generated from enum value: JS_NORMAL = 0; + */ + JS_NORMAL = 0, + + /** + * Use JavaScript strings. + * + * @generated from enum value: JS_STRING = 1; + */ + JS_STRING = 1, + + /** + * Use JavaScript numbers. + * + * @generated from enum value: JS_NUMBER = 2; + */ + JS_NUMBER = 2, +} +// Retrieve enum metadata with: proto2.getEnumType(FieldOptions_JSType) +proto2.util.setEnumType(FieldOptions_JSType, "google.protobuf.FieldOptions.JSType", [ + { no: 0, name: "JS_NORMAL" }, + { no: 1, name: "JS_STRING" }, + { no: 2, name: "JS_NUMBER" }, +]); + +/** + * @generated from message google.protobuf.OneofOptions + */ +export class OneofOptions extends Message { + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.OneofOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OneofOptions { + return new OneofOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OneofOptions { + return new OneofOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OneofOptions { + return new OneofOptions().fromJsonString(jsonString, options); + } + + static equals(a: OneofOptions | PlainMessage | undefined, b: OneofOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(OneofOptions, a, b); + } +} + +/** + * @generated from message google.protobuf.EnumOptions + */ +export class EnumOptions extends Message { + /** + * Set this option to true to allow mapping different tag names to the same + * value. + * + * @generated from field: optional bool allow_alias = 2; + */ + allowAlias?: boolean; + + /** + * Is this enum deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum, or it will be completely ignored; in the very least, this + * is a formalization for deprecating enums. + * + * @generated from field: optional bool deprecated = 3 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.EnumOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 2, name: "allow_alias", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true }, + { no: 3, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumOptions { + return new EnumOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumOptions { + return new EnumOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumOptions { + return new EnumOptions().fromJsonString(jsonString, options); + } + + static equals(a: EnumOptions | PlainMessage | undefined, b: EnumOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumOptions, a, b); + } +} + +/** + * @generated from message google.protobuf.EnumValueOptions + */ +export class EnumValueOptions extends Message { + /** + * Is this enum value deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum value, or it will be completely ignored; in the very least, + * this is a formalization for deprecating enum values. + * + * @generated from field: optional bool deprecated = 1 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.EnumValueOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): EnumValueOptions { + return new EnumValueOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): EnumValueOptions { + return new EnumValueOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): EnumValueOptions { + return new EnumValueOptions().fromJsonString(jsonString, options); + } + + static equals(a: EnumValueOptions | PlainMessage | undefined, b: EnumValueOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(EnumValueOptions, a, b); + } +} + +/** + * @generated from message google.protobuf.ServiceOptions + */ +export class ServiceOptions extends Message { + /** + * Is this service deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the service, or it will be completely ignored; in the very least, + * this is a formalization for deprecating services. + * + * @generated from field: optional bool deprecated = 33 [default = false]; + */ + deprecated?: boolean; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.ServiceOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 33, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ServiceOptions { + return new ServiceOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ServiceOptions { + return new ServiceOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ServiceOptions { + return new ServiceOptions().fromJsonString(jsonString, options); + } + + static equals(a: ServiceOptions | PlainMessage | undefined, b: ServiceOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(ServiceOptions, a, b); + } +} + +/** + * @generated from message google.protobuf.MethodOptions + */ +export class MethodOptions extends Message { + /** + * Is this method deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the method, or it will be completely ignored; in the very least, + * this is a formalization for deprecating methods. + * + * @generated from field: optional bool deprecated = 33 [default = false]; + */ + deprecated?: boolean; + + /** + * @generated from field: optional google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + */ + idempotencyLevel?: MethodOptions_IdempotencyLevel; + + /** + * The parser stores options it doesn't recognize here. See above. + * + * @generated from field: repeated google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + uninterpretedOption: UninterpretedOption[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.MethodOptions"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 33, name: "deprecated", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: false }, + { no: 34, name: "idempotency_level", kind: "enum", T: proto2.getEnumType(MethodOptions_IdempotencyLevel), opt: true, default: MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN }, + { no: 999, name: "uninterpreted_option", kind: "message", T: UninterpretedOption, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MethodOptions { + return new MethodOptions().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MethodOptions { + return new MethodOptions().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MethodOptions { + return new MethodOptions().fromJsonString(jsonString, options); + } + + static equals(a: MethodOptions | PlainMessage | undefined, b: MethodOptions | PlainMessage | undefined): boolean { + return proto2.util.equals(MethodOptions, a, b); + } +} + +/** + * Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + * or neither? HTTP based RPC implementation may choose GET verb for safe + * methods, and PUT verb for idempotent methods instead of the default POST. + * + * @generated from enum google.protobuf.MethodOptions.IdempotencyLevel + */ +export enum MethodOptions_IdempotencyLevel { + /** + * @generated from enum value: IDEMPOTENCY_UNKNOWN = 0; + */ + IDEMPOTENCY_UNKNOWN = 0, + + /** + * implies idempotent + * + * @generated from enum value: NO_SIDE_EFFECTS = 1; + */ + NO_SIDE_EFFECTS = 1, + + /** + * idempotent, but may have side effects + * + * @generated from enum value: IDEMPOTENT = 2; + */ + IDEMPOTENT = 2, +} +// Retrieve enum metadata with: proto2.getEnumType(MethodOptions_IdempotencyLevel) +proto2.util.setEnumType(MethodOptions_IdempotencyLevel, "google.protobuf.MethodOptions.IdempotencyLevel", [ + { no: 0, name: "IDEMPOTENCY_UNKNOWN" }, + { no: 1, name: "NO_SIDE_EFFECTS" }, + { no: 2, name: "IDEMPOTENT" }, +]); + +/** + * A message representing a option the parser does not recognize. This only + * appears in options protos created by the compiler::Parser class. + * DescriptorPool resolves these when building Descriptor objects. Therefore, + * options protos in descriptor objects (e.g. returned by Descriptor::options(), + * or produced by Descriptor::CopyTo()) will never have UninterpretedOptions + * in them. + * + * @generated from message google.protobuf.UninterpretedOption + */ +export class UninterpretedOption extends Message { + /** + * @generated from field: repeated google.protobuf.UninterpretedOption.NamePart name = 2; + */ + name: UninterpretedOption_NamePart[] = []; + + /** + * The value of the uninterpreted option, in whatever type the tokenizer + * identified it as during parsing. Exactly one of these should be set. + * + * @generated from field: optional string identifier_value = 3; + */ + identifierValue?: string; + + /** + * @generated from field: optional uint64 positive_int_value = 4; + */ + positiveIntValue?: bigint; + + /** + * @generated from field: optional int64 negative_int_value = 5; + */ + negativeIntValue?: bigint; + + /** + * @generated from field: optional double double_value = 6; + */ + doubleValue?: number; + + /** + * @generated from field: optional bytes string_value = 7; + */ + stringValue?: Uint8Array; + + /** + * @generated from field: optional string aggregate_value = 8; + */ + aggregateValue?: string; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.UninterpretedOption"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 2, name: "name", kind: "message", T: UninterpretedOption_NamePart, repeated: true }, + { no: 3, name: "identifier_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "positive_int_value", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true }, + { no: 5, name: "negative_int_value", kind: "scalar", T: 3 /* ScalarType.INT64 */, opt: true }, + { no: 6, name: "double_value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true }, + { no: 7, name: "string_value", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true }, + { no: 8, name: "aggregate_value", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): UninterpretedOption { + return new UninterpretedOption().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UninterpretedOption { + return new UninterpretedOption().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UninterpretedOption { + return new UninterpretedOption().fromJsonString(jsonString, options); + } + + static equals(a: UninterpretedOption | PlainMessage | undefined, b: UninterpretedOption | PlainMessage | undefined): boolean { + return proto2.util.equals(UninterpretedOption, a, b); + } +} + +/** + * The name of the uninterpreted option. Each string represents a segment in + * a dot-separated name. is_extension is true iff a segment represents an + * extension (denoted with parentheses in options specs in .proto files). + * E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + * "foo.(bar.baz).qux". + * + * @generated from message google.protobuf.UninterpretedOption.NamePart + */ +export class UninterpretedOption_NamePart extends Message { + /** + * @generated from field: required string name_part = 1; + */ + namePart?: string; + + /** + * @generated from field: required bool is_extension = 2; + */ + isExtension?: boolean; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.UninterpretedOption.NamePart"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name_part", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "is_extension", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): UninterpretedOption_NamePart { + return new UninterpretedOption_NamePart().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UninterpretedOption_NamePart { + return new UninterpretedOption_NamePart().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UninterpretedOption_NamePart { + return new UninterpretedOption_NamePart().fromJsonString(jsonString, options); + } + + static equals(a: UninterpretedOption_NamePart | PlainMessage | undefined, b: UninterpretedOption_NamePart | PlainMessage | undefined): boolean { + return proto2.util.equals(UninterpretedOption_NamePart, a, b); + } +} + +/** + * Encapsulates information about the original source file from which a + * FileDescriptorProto was generated. + * + * @generated from message google.protobuf.SourceCodeInfo + */ +export class SourceCodeInfo extends Message { + /** + * A Location identifies a piece of source code in a .proto file which + * corresponds to a particular definition. This information is intended + * to be useful to IDEs, code indexers, documentation generators, and similar + * tools. + * + * For example, say we have a file like: + * message Foo { + * optional string foo = 1; + * } + * Let's look at just the field definition: + * optional string foo = 1; + * ^ ^^ ^^ ^ ^^^ + * a bc de f ghi + * We have the following locations: + * span path represents + * [a,i) [ 4, 0, 2, 0 ] The whole field definition. + * [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + * [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + * [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + * [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + * + * Notes: + * - A location may refer to a repeated field itself (i.e. not to any + * particular index within it). This is used whenever a set of elements are + * logically enclosed in a single code segment. For example, an entire + * extend block (possibly containing multiple extension definitions) will + * have an outer location whose path refers to the "extensions" repeated + * field without an index. + * - Multiple locations may have the same path. This happens when a single + * logical declaration is spread out across multiple places. The most + * obvious example is the "extend" block again -- there may be multiple + * extend blocks in the same scope, each of which will have the same path. + * - A location's span is not always a subset of its parent's span. For + * example, the "extendee" of an extension declaration appears at the + * beginning of the "extend" block and is shared by all extensions within + * the block. + * - Just because a location's span is a subset of some other location's span + * does not mean that it is a descendant. For example, a "group" defines + * both a type and a field in a single declaration. Thus, the locations + * corresponding to the type and field and their components will overlap. + * - Code which tries to interpret locations should probably be designed to + * ignore those that it doesn't understand, as more types of locations could + * be recorded in the future. + * + * @generated from field: repeated google.protobuf.SourceCodeInfo.Location location = 1; + */ + location: SourceCodeInfo_Location[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.SourceCodeInfo"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "location", kind: "message", T: SourceCodeInfo_Location, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceCodeInfo { + return new SourceCodeInfo().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceCodeInfo { + return new SourceCodeInfo().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SourceCodeInfo { + return new SourceCodeInfo().fromJsonString(jsonString, options); + } + + static equals(a: SourceCodeInfo | PlainMessage | undefined, b: SourceCodeInfo | PlainMessage | undefined): boolean { + return proto2.util.equals(SourceCodeInfo, a, b); + } +} + +/** + * @generated from message google.protobuf.SourceCodeInfo.Location + */ +export class SourceCodeInfo_Location extends Message { + /** + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition occurs. + * For example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * + * @generated from field: repeated int32 path = 1 [packed = true]; + */ + path: number[] = []; + + /** + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * + * @generated from field: repeated int32 span = 2 [packed = true]; + */ + span: number[] = []; + + /** + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * + * Examples: + * + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * + * // Detached comment for corge paragraph 2. + * + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. *\/ + * /* Block comment attached to + * * grault. *\/ + * optional int32 grault = 6; + * + * // ignored detached comments. + * + * @generated from field: optional string leading_comments = 3; + */ + leadingComments?: string; + + /** + * @generated from field: optional string trailing_comments = 4; + */ + trailingComments?: string; + + /** + * @generated from field: repeated string leading_detached_comments = 6; + */ + leadingDetachedComments: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.SourceCodeInfo.Location"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "path", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 2, name: "span", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 3, name: "leading_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "trailing_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 6, name: "leading_detached_comments", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceCodeInfo_Location { + return new SourceCodeInfo_Location().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceCodeInfo_Location { + return new SourceCodeInfo_Location().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SourceCodeInfo_Location { + return new SourceCodeInfo_Location().fromJsonString(jsonString, options); + } + + static equals(a: SourceCodeInfo_Location | PlainMessage | undefined, b: SourceCodeInfo_Location | PlainMessage | undefined): boolean { + return proto2.util.equals(SourceCodeInfo_Location, a, b); + } +} + +/** + * Describes the relationship between generated code and its original source + * file. A GeneratedCodeInfo message is associated with only one generated + * source file, but may contain references to different source .proto files. + * + * @generated from message google.protobuf.GeneratedCodeInfo + */ +export class GeneratedCodeInfo extends Message { + /** + * An Annotation connects some span of text in generated code to an element + * of its generating .proto file. + * + * @generated from field: repeated google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + */ + annotation: GeneratedCodeInfo_Annotation[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.GeneratedCodeInfo"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "annotation", kind: "message", T: GeneratedCodeInfo_Annotation, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GeneratedCodeInfo { + return new GeneratedCodeInfo().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GeneratedCodeInfo { + return new GeneratedCodeInfo().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GeneratedCodeInfo { + return new GeneratedCodeInfo().fromJsonString(jsonString, options); + } + + static equals(a: GeneratedCodeInfo | PlainMessage | undefined, b: GeneratedCodeInfo | PlainMessage | undefined): boolean { + return proto2.util.equals(GeneratedCodeInfo, a, b); + } +} + +/** + * @generated from message google.protobuf.GeneratedCodeInfo.Annotation + */ +export class GeneratedCodeInfo_Annotation extends Message { + /** + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * + * @generated from field: repeated int32 path = 1 [packed = true]; + */ + path: number[] = []; + + /** + * Identifies the filesystem path to the original source .proto. + * + * @generated from field: optional string source_file = 2; + */ + sourceFile?: string; + + /** + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * + * @generated from field: optional int32 begin = 3; + */ + begin?: number; + + /** + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * + * @generated from field: optional int32 end = 4; + */ + end?: number; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime = proto2; + static readonly typeName = "google.protobuf.GeneratedCodeInfo.Annotation"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "path", kind: "scalar", T: 5 /* ScalarType.INT32 */, repeated: true, packed: true }, + { no: 2, name: "source_file", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "begin", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + { no: 4, name: "end", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GeneratedCodeInfo_Annotation { + return new GeneratedCodeInfo_Annotation().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GeneratedCodeInfo_Annotation { + return new GeneratedCodeInfo_Annotation().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GeneratedCodeInfo_Annotation { + return new GeneratedCodeInfo_Annotation().fromJsonString(jsonString, options); + } + + static equals(a: GeneratedCodeInfo_Annotation | PlainMessage | undefined, b: GeneratedCodeInfo_Annotation | PlainMessage | undefined): boolean { + return proto2.util.equals(GeneratedCodeInfo_Annotation, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/duration_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/duration_pb.ts new file mode 100644 index 000000000..247a18365 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/duration_pb.ts @@ -0,0 +1,193 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/duration.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, JsonWriteOptions, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64} from "@bufbuild/protobuf"; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (duration.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + * + * + * + * @generated from message google.protobuf.Duration + */ +export class Duration extends Message { + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * @generated from field: int64 seconds = 1; + */ + seconds = protoInt64.zero; + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * @generated from field: int32 nanos = 2; + */ + nanos = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (typeof json !== "string") { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + const match = json.match(/^(-?[0-9]+)(?:\.([0-9]+))?s/); + if (match === null) { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + const longSeconds = Number(match[1]); + if (longSeconds > 315576000000 || longSeconds < -315576000000) { + throw new Error(`cannot decode google.protobuf.Duration from JSON: ${proto3.json.debug(json)}`); + } + this.seconds = protoInt64.parse(longSeconds); + if (typeof match[2] == "string") { + const nanosStr = match[2] + "0".repeat(9 - match[2].length); + this.nanos = parseInt(nanosStr); + if (longSeconds < protoInt64.zero) { + this.nanos = -this.nanos; + } + } + return this; + } + + override toJson(options?: Partial): JsonValue { + if (Number(this.seconds) > 315576000000 || Number(this.seconds) < -315576000000) { + throw new Error(`cannot encode google.protobuf.Duration to JSON: value out of range`); + } + let text = this.seconds.toString(); + if (this.nanos !== 0) { + let nanosStr = Math.abs(this.nanos).toString(); + nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr; + if (nanosStr.substring(3) === "000000") { + nanosStr = nanosStr.substring(0, 3); + } else if (nanosStr.substring(6) === "000") { + nanosStr = nanosStr.substring(0, 6); + } + text += "." + nanosStr; + } + return text + "s"; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Duration"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "seconds", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "nanos", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Duration { + return new Duration().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Duration { + return new Duration().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Duration { + return new Duration().fromJsonString(jsonString, options); + } + + static equals(a: Duration | PlainMessage | undefined, b: Duration | PlainMessage | undefined): boolean { + return proto3.util.equals(Duration, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/empty_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/empty_pb.ts new file mode 100644 index 000000000..30f524f45 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/empty_pb.ts @@ -0,0 +1,78 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/empty.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + * + * @generated from message google.protobuf.Empty + */ +export class Empty extends Message { + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Empty"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Empty { + return new Empty().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Empty { + return new Empty().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Empty { + return new Empty().fromJsonString(jsonString, options); + } + + static equals(a: Empty | PlainMessage | undefined, b: Empty | PlainMessage | undefined): boolean { + return proto3.util.equals(Empty, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/field_mask_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/field_mask_pb.ts new file mode 100644 index 000000000..9bf89b8ec --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/field_mask_pb.ts @@ -0,0 +1,338 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/field_mask.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, JsonWriteOptions, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is unmappable. + * + * @generated from message google.protobuf.FieldMask + */ +export class FieldMask extends Message { + /** + * The set of field mask paths. + * + * @generated from field: repeated string paths = 1; + */ + paths: string[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + // Converts snake_case to protoCamelCase according to the convention + // used by protoc to convert a field name to a JSON name. + function protoCamelCase(snakeCase: string): string { + let capNext = false; + const b = []; + for (let i = 0; i < snakeCase.length; i++) { + let c = snakeCase.charAt(i); + switch (c) { + case '_': + capNext = true; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + b.push(c); + capNext = false; + break; + default: + if (capNext) { + capNext = false; + c = c.toUpperCase(); + } + b.push(c); + break; + } + } + return b.join(''); + } + return this.paths.map(p => { + if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: lowerCamelCase of path name \"" + p + "\" is irreversible"); + } + return protoCamelCase(p); + }).join(","); + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (typeof json !== "string") { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: " + proto3.json.debug(json)); + } + if (json === "") { + return this; + } + function camelToSnake (str: string) { + if (str.includes("_")) { + throw new Error("cannot decode google.protobuf.FieldMask from JSON: path names must be lowerCamelCase"); + } + const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase()); + return (sc[0] === "_") ? sc.substring(1) : sc; + } + this.paths = json.split(",").map(camelToSnake); + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.FieldMask"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "paths", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): FieldMask { + return new FieldMask().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FieldMask { + return new FieldMask().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FieldMask { + return new FieldMask().fromJsonString(jsonString, options); + } + + static equals(a: FieldMask | PlainMessage | undefined, b: FieldMask | PlainMessage | undefined): boolean { + return proto3.util.equals(FieldMask, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/source_context_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/source_context_pb.ts new file mode 100644 index 000000000..44cbe2574 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/source_context_pb.ts @@ -0,0 +1,80 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/source_context.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + * + * @generated from message google.protobuf.SourceContext + */ +export class SourceContext extends Message { + /** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * + * @generated from field: string file_name = 1; + */ + fileName = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.SourceContext"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "file_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): SourceContext { + return new SourceContext().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): SourceContext { + return new SourceContext().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): SourceContext { + return new SourceContext().fromJsonString(jsonString, options); + } + + static equals(a: SourceContext | PlainMessage | undefined, b: SourceContext | PlainMessage | undefined): boolean { + return proto3.util.equals(SourceContext, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/struct_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/struct_pb.ts new file mode 100644 index 000000000..ef8a15c2f --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/struct_pb.ts @@ -0,0 +1,321 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonObject, JsonReadOptions, JsonValue, JsonWriteOptions, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + * + * @generated from enum google.protobuf.NullValue + */ +export enum NullValue { + /** + * Null value. + * + * @generated from enum value: NULL_VALUE = 0; + */ + NULL_VALUE = 0, +} +// Retrieve enum metadata with: proto3.getEnumType(NullValue) +proto3.util.setEnumType(NullValue, "google.protobuf.NullValue", [ + { no: 0, name: "NULL_VALUE" }, +]); + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + * + * @generated from message google.protobuf.Struct + */ +export class Struct extends Message { + /** + * Unordered map of dynamically typed values. + * + * @generated from field: map fields = 1; + */ + fields: { [key: string]: Value } = {}; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + const json: JsonObject = {} + for (const [k, v] of Object.entries(this.fields)) { + json[k] = v.toJson(options); + } + return json; + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (typeof json != "object" || json == null || Array.isArray(json)) { + throw new Error("cannot decode google.protobuf.Struct from JSON " + proto3.json.debug(json)); + } + for (const [k, v] of Object.entries(json)) { + this.fields[k] = Value.fromJson(v); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Struct"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "fields", kind: "map", K: 9 /* ScalarType.STRING */, V: {kind: "message", T: Value} }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Struct { + return new Struct().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Struct { + return new Struct().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Struct { + return new Struct().fromJsonString(jsonString, options); + } + + static equals(a: Struct | PlainMessage | undefined, b: Struct | PlainMessage | undefined): boolean { + return proto3.util.equals(Struct, a, b); + } +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + * + * @generated from message google.protobuf.Value + */ +export class Value extends Message { + /** + * The kind of value. + * + * @generated from oneof google.protobuf.Value.kind + */ + kind: { + /** + * Represents a null value. + * + * @generated from field: google.protobuf.NullValue null_value = 1; + */ + value: NullValue; + case: "nullValue"; + } | { + /** + * Represents a double value. + * + * @generated from field: double number_value = 2; + */ + value: number; + case: "numberValue"; + } | { + /** + * Represents a string value. + * + * @generated from field: string string_value = 3; + */ + value: string; + case: "stringValue"; + } | { + /** + * Represents a boolean value. + * + * @generated from field: bool bool_value = 4; + */ + value: boolean; + case: "boolValue"; + } | { + /** + * Represents a structured value. + * + * @generated from field: google.protobuf.Struct struct_value = 5; + */ + value: Struct; + case: "structValue"; + } | { + /** + * Represents a repeated `Value`. + * + * @generated from field: google.protobuf.ListValue list_value = 6; + */ + value: ListValue; + case: "listValue"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + switch (this.kind.case) { + case "nullValue": + return null; + case "boolValue": + case "numberValue": + case "stringValue": + return this.kind.value; + case "structValue": + case "listValue": + return this.kind.value.toJson({...options, emitDefaultValues: true}); + } + throw new Error("google.protobuf.Value must have a value"); + } + + override fromJson(json: JsonValue, options?: Partial): this { + switch (typeof json) { + case "number": + this.kind = { case: "numberValue", value: json }; + break; + case "string": + this.kind = { case: "stringValue", value: json }; + break; + case "boolean": + this.kind = { case: "boolValue", value: json }; + break; + case "object": + if (json === null) { + this.kind = { case: "nullValue", value: NullValue.NULL_VALUE }; + } else if (Array.isArray(json)) { + this.kind = { case: "listValue", value: ListValue.fromJson(json) }; + } else { + this.kind = { case: "structValue", value: Struct.fromJson(json) }; + } + break; + default: + throw new Error("cannot decode google.protobuf.Value from JSON " + proto3.json.debug(json)); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "null_value", kind: "enum", T: proto3.getEnumType(NullValue), oneof: "kind" }, + { no: 2, name: "number_value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, oneof: "kind" }, + { no: 3, name: "string_value", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "kind" }, + { no: 4, name: "bool_value", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "kind" }, + { no: 5, name: "struct_value", kind: "message", T: Struct, oneof: "kind" }, + { no: 6, name: "list_value", kind: "message", T: ListValue, oneof: "kind" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): Value { + return new Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Value { + return new Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Value { + return new Value().fromJsonString(jsonString, options); + } + + static equals(a: Value | PlainMessage | undefined, b: Value | PlainMessage | undefined): boolean { + return proto3.util.equals(Value, a, b); + } +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + * + * @generated from message google.protobuf.ListValue + */ +export class ListValue extends Message { + /** + * Repeated field of dynamically typed values. + * + * @generated from field: repeated google.protobuf.Value values = 1; + */ + values: Value[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return this.values.map(v => v.toJson()); + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (!Array.isArray(json)) { + throw new Error("cannot decode google.protobuf.ListValue from JSON " + proto3.json.debug(json)); + } + for (let e of json) { + this.values.push(Value.fromJson(e)); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.ListValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "values", kind: "message", T: Value, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ListValue { + return new ListValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ListValue { + return new ListValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ListValue { + return new ListValue().fromJsonString(jsonString, options); + } + + static equals(a: ListValue | PlainMessage | undefined, b: ListValue | PlainMessage | undefined): boolean { + return proto3.util.equals(ListValue, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto2_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto2_pb.ts index 9d4afaf26..f79d9bf10 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto2_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto2_pb.ts @@ -892,11 +892,11 @@ export class TestAllTypesProto2 extends Message { { no: 248, name: "default_fixed64", kind: "scalar", T: 6 /* ScalarType.FIXED64 */, opt: true, default: protoInt64.uParse("10123456789123456789") }, { no: 249, name: "default_sfixed32", kind: "scalar", T: 15 /* ScalarType.SFIXED32 */, opt: true, default: -123456789 }, { no: 250, name: "default_sfixed64", kind: "scalar", T: 16 /* ScalarType.SFIXED64 */, opt: true, default: protoInt64.parse("-9123456789123456789") }, - { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9e+09 }, + { no: 251, name: "default_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 9000000000 }, { no: 252, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 7e+22 }, { no: 253, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 254, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "Rosebud" }, - { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61, ]) }, + { no: 255, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x6A, 0x6F, 0x73, 0x68, 0x75, 0x61]) }, { no: 401, name: "fieldname1", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 402, name: "field_name2", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 403, name: "_field_name3", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto3_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto3_pb.ts index afc4166d6..6c4c262de 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto3_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/test_messages_proto3_pb.ts @@ -40,7 +40,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, Message, NullValue, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value, proto3, protoInt64} from "@bufbuild/protobuf"; +import {Any, BoolValue, BytesValue, DoubleValue, Duration, FieldMask, FloatValue, Int32Value, Int64Value, ListValue, Message, NullValue, proto3, protoInt64, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value} from "@bufbuild/protobuf"; /** * @generated from enum protobuf_test_messages.proto3.ForeignEnum diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/timestamp_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/timestamp_pb.ts new file mode 100644 index 000000000..692a4e2ae --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/timestamp_pb.ts @@ -0,0 +1,244 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/timestamp.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, JsonWriteOptions, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64} from "@bufbuild/protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + * + * + * + * @generated from message google.protobuf.Timestamp + */ +export class Timestamp extends Message { + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * + * @generated from field: int64 seconds = 1; + */ + seconds = protoInt64.zero; + + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * + * @generated from field: int32 nanos = 2; + */ + nanos = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override fromJson(json: JsonValue, options?: Partial): this { + if (typeof json !== "string") { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: ${proto3.json.debug(json)}`); + } + const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/); + if (!matches) { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string`); + } + const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z")); + if (Number.isNaN(ms)) { + throw new Error(`cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string`); + } + if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) { + throw new Error(`cannot decode message google.protobuf.Timestamp from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`); + } + this.seconds = protoInt64.parse(ms / 1000); + this.nanos = 0; + if (matches[7]) { + this.nanos = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000); + } + return this; + } + + override toJson(options?: Partial): JsonValue { + const ms = Number(this.seconds) * 1000; + if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) { + throw new Error(`cannot encode google.protobuf.Timestamp to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`); + } + if (this.nanos < 0) { + throw new Error(`cannot encode google.protobuf.Timestamp to JSON: nanos must not be negative`); + } + let z = "Z"; + if (this.nanos > 0) { + const nanosStr = (this.nanos + 1000000000).toString().substring(1); + if (nanosStr.substring(3) === "000000") { + z = "." + nanosStr.substring(0, 3) + "Z"; + } else if (nanosStr.substring(6) === "000") { + z = "." + nanosStr.substring(0, 6) + "Z"; + } else { + z = "." + nanosStr + "Z"; + } + } + return new Date(ms).toISOString().replace(".000Z", z); + } + + toDate(): Date { + return new Date(Number(this.seconds) * 1000 + Math.ceil(this.nanos / 1000000)); + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Timestamp"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "seconds", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 2, name: "nanos", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ]); + + static now(): Timestamp { + return Timestamp.fromDate(new Date()) + } + + static fromDate(date: Date): Timestamp { + const ms = date.getTime(); + return new Timestamp({ + seconds: protoInt64.parse(Math.floor(ms / 1000)), + nanos: (ms % 1000) * 1000000, + }); + } + + static fromBinary(bytes: Uint8Array, options?: Partial): Timestamp { + return new Timestamp().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Timestamp { + return new Timestamp().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Timestamp { + return new Timestamp().fromJsonString(jsonString, options); + } + + static equals(a: Timestamp | PlainMessage | undefined, b: Timestamp | PlainMessage | undefined): boolean { + return proto3.util.equals(Timestamp, a, b); + } +} + diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/type_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/type_pb.ts index 50779c581..969d5faf6 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/type_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/type_pb.ts @@ -33,7 +33,9 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Any, Message, SourceContext, proto3} from "@bufbuild/protobuf"; +import {Message, proto3} from "@bufbuild/protobuf"; +import {SourceContext} from "./source_context_pb.js"; +import {Any} from "./any_pb.js"; /** * The syntax in which a protocol buffer element is defined. diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_lite_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_lite_pb.ts index 62e62a44e..9eef4ac07 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_lite_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_lite_pb.ts @@ -593,7 +593,7 @@ export class TestAllTypesLite extends Message { { no: 72, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 52000 }, { no: 73, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 74, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64, ]) }, + { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64]) }, { no: 81, name: "default_nested_enum", kind: "enum", T: proto2.getEnumType(TestAllTypesLite_NestedEnum), opt: true, default: TestAllTypesLite_NestedEnum.BAR }, { no: 82, name: "default_foreign_enum", kind: "enum", T: proto2.getEnumType(ForeignEnumLite), opt: true, default: ForeignEnumLite.FOREIGN_LITE_BAR }, { no: 83, name: "default_import_enum", kind: "enum", T: proto2.getEnumType(ImportEnumLite), opt: true, default: ImportEnumLite.IMPORT_LITE_BAR }, @@ -1898,11 +1898,11 @@ export class TestOneofParsingLite extends Message { { no: 1, name: "oneof_int32", kind: "scalar", T: 5 /* ScalarType.INT32 */, oneof: "oneof_field" }, { no: 2, name: "oneof_submessage", kind: "message", T: TestAllTypesLite, oneof: "oneof_field" }, { no: 3, name: "oneof_string", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "oneof_field" }, - { no: 4, name: "oneof_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, ]), oneof: "oneof_field" }, + { no: 4, name: "oneof_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73]), oneof: "oneof_field" }, { no: 5, name: "oneof_string_cord", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "default Cord", oneof: "oneof_field" }, { no: 6, name: "oneof_bytes_cord", kind: "scalar", T: 12 /* ScalarType.BYTES */, oneof: "oneof_field" }, { no: 7, name: "oneof_string_string_piece", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "oneof_field" }, - { no: 8, name: "oneof_bytes_string_piece", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x50, 0x69, 0x65, 0x63, 0x65, ]), oneof: "oneof_field" }, + { no: 8, name: "oneof_bytes_string_piece", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x50, 0x69, 0x65, 0x63, 0x65]), oneof: "oneof_field" }, { no: 9, name: "oneof_enum", kind: "enum", T: proto2.getEnumType(V2EnumLite), oneof: "oneof_field" }, ]); diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_no_field_presence_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_no_field_presence_pb.ts index 56616927f..fe93dae69 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_no_field_presence_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_no_field_presence_pb.ts @@ -173,7 +173,7 @@ export class TestAllTypes extends Message { /** * N.B.: proto2-enum-type fields not allowed, because their default values * might not be zero. - *optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23; + * optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23; * * @generated from field: proto2_nofieldpresence_unittest.ForeignEnum optional_foreign_enum = 22; */ diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_pb.ts index 3a35353f9..9f60d1a72 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_pb.ts @@ -1255,7 +1255,7 @@ export class TestAllTypes extends Message { { no: 72, name: "default_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: 52000 }, { no: 73, name: "default_bool", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true, default: true }, { no: 74, name: "default_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64, ]) }, + { no: 75, name: "default_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x6C, 0x64]) }, { no: 81, name: "default_nested_enum", kind: "enum", T: proto2.getEnumType(TestAllTypes_NestedEnum), opt: true, default: TestAllTypes_NestedEnum.BAR }, { no: 82, name: "default_foreign_enum", kind: "enum", T: proto2.getEnumType(ForeignEnum), opt: true, default: ForeignEnum.FOREIGN_BAR }, { no: 83, name: "default_import_enum", kind: "enum", T: proto2.getEnumType(ImportEnum), opt: true, default: ImportEnum.IMPORT_BAR }, @@ -4082,7 +4082,7 @@ export class TestExtremeDefaultValues extends Message static readonly runtime = proto2; static readonly typeName = "protobuf_unittest.TestExtremeDefaultValues"; static readonly fields: FieldList = proto2.util.newFieldList(() => [ - { no: 1, name: "escaped_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x01, 0x07, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, 0x5C, 0xFE, ]) }, + { no: 1, name: "escaped_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x00, 0x01, 0x07, 0x08, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, 0x5C, 0xFE]) }, { no: 2, name: "large_uint32", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true, default: 4294967295 }, { no: 3, name: "large_uint64", kind: "scalar", T: 4 /* ScalarType.UINT64 */, opt: true, default: protoInt64.uParse("18446744073709551615") }, { no: 4, name: "small_int32", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true, default: -2147483647 }, @@ -4095,7 +4095,7 @@ export class TestExtremeDefaultValues extends Message { no: 9, name: "small_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 1.5 }, { no: 10, name: "negative_one_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -1 }, { no: 11, name: "negative_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -1.5 }, - { no: 12, name: "large_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 2e+08 }, + { no: 12, name: "large_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: 200000000 }, { no: 13, name: "small_negative_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: -8e-28 }, { no: 14, name: "inf_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: globalThis.Number.POSITIVE_INFINITY }, { no: 15, name: "neg_inf_double", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, opt: true, default: globalThis.Number.NEGATIVE_INFINITY }, @@ -4105,7 +4105,7 @@ export class TestExtremeDefaultValues extends Message { no: 19, name: "nan_float", kind: "scalar", T: 2 /* ScalarType.FLOAT */, opt: true, default: globalThis.Number.NaN }, { no: 20, name: "cpp_trigraph", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "? ? ?? ?? ??? ??/ ??-" }, { no: 23, name: "string_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "hello" }, - { no: 24, name: "bytes_with_zero", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x00, 0x6C, 0x64, ]) }, + { no: 24, name: "bytes_with_zero", kind: "scalar", T: 12 /* ScalarType.BYTES */, opt: true, default: new Uint8Array([0x77, 0x6F, 0x72, 0x00, 0x6C, 0x64]) }, { no: 25, name: "string_piece_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "abc" }, { no: 26, name: "cord_with_zero", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "123" }, { no: 27, name: "replacement_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "${unknown}" }, @@ -5091,12 +5091,12 @@ export class TestOneof2 extends Message { { no: 13, name: "bar_string", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "STRING", oneof: "bar" }, { no: 14, name: "bar_cord", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "CORD", oneof: "bar" }, { no: 15, name: "bar_string_piece", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "SPIECE", oneof: "bar" }, - { no: 16, name: "bar_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x42, 0x59, 0x54, 0x45, 0x53, ]), oneof: "bar" }, + { no: 16, name: "bar_bytes", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array([0x42, 0x59, 0x54, 0x45, 0x53]), oneof: "bar" }, { no: 17, name: "bar_enum", kind: "enum", T: proto2.getEnumType(TestOneof2_NestedEnum), default: TestOneof2_NestedEnum.BAR, oneof: "bar" }, - { no: 20, name: "bar_string_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 21, name: "bar_cord_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 22, name: "bar_string_piece_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "bar" }, - { no: 23, name: "bar_bytes_with_empty_default", kind: "scalar", T: 12 /* ScalarType.BYTES */, oneof: "bar" }, + { no: 20, name: "bar_string_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 21, name: "bar_cord_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 22, name: "bar_string_piece_with_empty_default", kind: "scalar", T: 9 /* ScalarType.STRING */, default: "", oneof: "bar" }, + { no: 23, name: "bar_bytes_with_empty_default", kind: "scalar", T: 12 /* ScalarType.BYTES */, default: new Uint8Array(0), oneof: "bar" }, { no: 18, name: "baz_int", kind: "scalar", T: 5 /* ScalarType.INT32 */, opt: true }, { no: 19, name: "baz_string", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true, default: "BAZ" }, ]); diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_well_known_types_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_well_known_types_pb.ts index c0ecd9f33..d1953a4f3 100644 --- a/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_well_known_types_pb.ts +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/unittest_well_known_types_pb.ts @@ -3,7 +3,7 @@ /* eslint-disable */ import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; -import {Any, Api, BoolValue, BytesValue, DoubleValue, Duration, Empty, FieldMask, FloatValue, Int32Value, Int64Value, Message, SourceContext, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value, proto3} from "@bufbuild/protobuf"; +import {Any, Api, BoolValue, BytesValue, DoubleValue, Duration, Empty, FieldMask, FloatValue, Int32Value, Int64Value, Message, proto3, SourceContext, StringValue, Struct, Timestamp, UInt32Value, UInt64Value, Value} from "@bufbuild/protobuf"; import {Type} from "./type_pb.js"; /** diff --git a/packages/protobuf-test/src/gen/ts/google/protobuf/wrappers_pb.ts b/packages/protobuf-test/src/gen/ts/google/protobuf/wrappers_pb.ts new file mode 100644 index 000000000..9e81e6230 --- /dev/null +++ b/packages/protobuf-test/src/gen/ts/google/protobuf/wrappers_pb.ts @@ -0,0 +1,668 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. +// +// These wrappers have no meaningful use within repeated fields as they lack +// the ability to detect presence on individual elements. +// These wrappers have no meaningful use within a map or a oneof since +// individual entries of a map or fields of a oneof can already detect presence. + +// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=ts" +// @generated from file google/protobuf/wrappers.proto (package google.protobuf, syntax proto3) +/* eslint-disable */ + +import type {BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, JsonWriteOptions, PartialMessage, PlainMessage} from "@bufbuild/protobuf"; +import {Message, proto3, protoInt64, ScalarType} from "@bufbuild/protobuf"; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + * + * @generated from message google.protobuf.DoubleValue + */ +export class DoubleValue extends Message { + /** + * The double value. + * + * @generated from field: double value = 1; + */ + value = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.DOUBLE, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.DOUBLE, json); + } catch (e) { + let m = `cannot decode message google.protobuf.DoubleValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.DoubleValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: number | DoubleValue): DoubleValue { + return value instanceof DoubleValue ? value : new DoubleValue({value}); + }, + unwrapField(value: DoubleValue): number { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): DoubleValue { + return new DoubleValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DoubleValue { + return new DoubleValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DoubleValue { + return new DoubleValue().fromJsonString(jsonString, options); + } + + static equals(a: DoubleValue | PlainMessage | undefined, b: DoubleValue | PlainMessage | undefined): boolean { + return proto3.util.equals(DoubleValue, a, b); + } +} + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + * + * @generated from message google.protobuf.FloatValue + */ +export class FloatValue extends Message { + /** + * The float value. + * + * @generated from field: float value = 1; + */ + value = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.FLOAT, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.FLOAT, json); + } catch (e) { + let m = `cannot decode message google.protobuf.FloatValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.FloatValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 2 /* ScalarType.FLOAT */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: number | FloatValue): FloatValue { + return value instanceof FloatValue ? value : new FloatValue({value}); + }, + unwrapField(value: FloatValue): number { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): FloatValue { + return new FloatValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): FloatValue { + return new FloatValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): FloatValue { + return new FloatValue().fromJsonString(jsonString, options); + } + + static equals(a: FloatValue | PlainMessage | undefined, b: FloatValue | PlainMessage | undefined): boolean { + return proto3.util.equals(FloatValue, a, b); + } +} + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + * + * @generated from message google.protobuf.Int64Value + */ +export class Int64Value extends Message { + /** + * The int64 value. + * + * @generated from field: int64 value = 1; + */ + value = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.INT64, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.INT64, json); + } catch (e) { + let m = `cannot decode message google.protobuf.Int64Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Int64Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: bigint | Int64Value): Int64Value { + return value instanceof Int64Value ? value : new Int64Value({value}); + }, + unwrapField(value: Int64Value): bigint { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): Int64Value { + return new Int64Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Int64Value { + return new Int64Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Int64Value { + return new Int64Value().fromJsonString(jsonString, options); + } + + static equals(a: Int64Value | PlainMessage | undefined, b: Int64Value | PlainMessage | undefined): boolean { + return proto3.util.equals(Int64Value, a, b); + } +} + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + * + * @generated from message google.protobuf.UInt64Value + */ +export class UInt64Value extends Message { + /** + * The uint64 value. + * + * @generated from field: uint64 value = 1; + */ + value = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.UINT64, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.UINT64, json); + } catch (e) { + let m = `cannot decode message google.protobuf.UInt64Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.UInt64Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: bigint | UInt64Value): UInt64Value { + return value instanceof UInt64Value ? value : new UInt64Value({value}); + }, + unwrapField(value: UInt64Value): bigint { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt64Value { + return new UInt64Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt64Value { + return new UInt64Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UInt64Value { + return new UInt64Value().fromJsonString(jsonString, options); + } + + static equals(a: UInt64Value | PlainMessage | undefined, b: UInt64Value | PlainMessage | undefined): boolean { + return proto3.util.equals(UInt64Value, a, b); + } +} + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + * + * @generated from message google.protobuf.Int32Value + */ +export class Int32Value extends Message { + /** + * The int32 value. + * + * @generated from field: int32 value = 1; + */ + value = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.INT32, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.INT32, json); + } catch (e) { + let m = `cannot decode message google.protobuf.Int32Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.Int32Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: number | Int32Value): Int32Value { + return value instanceof Int32Value ? value : new Int32Value({value}); + }, + unwrapField(value: Int32Value): number { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): Int32Value { + return new Int32Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): Int32Value { + return new Int32Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): Int32Value { + return new Int32Value().fromJsonString(jsonString, options); + } + + static equals(a: Int32Value | PlainMessage | undefined, b: Int32Value | PlainMessage | undefined): boolean { + return proto3.util.equals(Int32Value, a, b); + } +} + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + * + * @generated from message google.protobuf.UInt32Value + */ +export class UInt32Value extends Message { + /** + * The uint32 value. + * + * @generated from field: uint32 value = 1; + */ + value = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.UINT32, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.UINT32, json); + } catch (e) { + let m = `cannot decode message google.protobuf.UInt32Value from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.UInt32Value"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 13 /* ScalarType.UINT32 */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: number | UInt32Value): UInt32Value { + return value instanceof UInt32Value ? value : new UInt32Value({value}); + }, + unwrapField(value: UInt32Value): number { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): UInt32Value { + return new UInt32Value().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): UInt32Value { + return new UInt32Value().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): UInt32Value { + return new UInt32Value().fromJsonString(jsonString, options); + } + + static equals(a: UInt32Value | PlainMessage | undefined, b: UInt32Value | PlainMessage | undefined): boolean { + return proto3.util.equals(UInt32Value, a, b); + } +} + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + * + * @generated from message google.protobuf.BoolValue + */ +export class BoolValue extends Message { + /** + * The bool value. + * + * @generated from field: bool value = 1; + */ + value = false; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.BOOL, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.BOOL, json); + } catch (e) { + let m = `cannot decode message google.protobuf.BoolValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.BoolValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: boolean | BoolValue): BoolValue { + return value instanceof BoolValue ? value : new BoolValue({value}); + }, + unwrapField(value: BoolValue): boolean { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): BoolValue { + return new BoolValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BoolValue { + return new BoolValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BoolValue { + return new BoolValue().fromJsonString(jsonString, options); + } + + static equals(a: BoolValue | PlainMessage | undefined, b: BoolValue | PlainMessage | undefined): boolean { + return proto3.util.equals(BoolValue, a, b); + } +} + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + * + * @generated from message google.protobuf.StringValue + */ +export class StringValue extends Message { + /** + * The string value. + * + * @generated from field: string value = 1; + */ + value = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.STRING, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.STRING, json); + } catch (e) { + let m = `cannot decode message google.protobuf.StringValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.StringValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: string | StringValue): StringValue { + return value instanceof StringValue ? value : new StringValue({value}); + }, + unwrapField(value: StringValue): string { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): StringValue { + return new StringValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StringValue { + return new StringValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StringValue { + return new StringValue().fromJsonString(jsonString, options); + } + + static equals(a: StringValue | PlainMessage | undefined, b: StringValue | PlainMessage | undefined): boolean { + return proto3.util.equals(StringValue, a, b); + } +} + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + * + * @generated from message google.protobuf.BytesValue + */ +export class BytesValue extends Message { + /** + * The bytes value. + * + * @generated from field: bytes value = 1; + */ + value = new Uint8Array(0); + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + override toJson(options?: Partial): JsonValue { + return proto3.json.writeScalar(ScalarType.BYTES, this.value, true)!; + } + + override fromJson(json: JsonValue, options?: Partial): this { + try { + this.value = proto3.json.readScalar(ScalarType.BYTES, json); + } catch (e) { + let m = `cannot decode message google.protobuf.BytesValue from JSON"`; + if (e instanceof Error && e.message.length > 0) { + m += `: ${e.message}` + } + throw new Error(m); + } + return this; + } + + static readonly runtime = proto3; + static readonly typeName = "google.protobuf.BytesValue"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "value", kind: "scalar", T: 12 /* ScalarType.BYTES */ }, + ]); + + static readonly fieldWrapper = { + wrapField(value: Uint8Array | BytesValue): BytesValue { + return value instanceof BytesValue ? value : new BytesValue({value}); + }, + unwrapField(value: BytesValue): Uint8Array { + return value.value; + } + }; + + static fromBinary(bytes: Uint8Array, options?: Partial): BytesValue { + return new BytesValue().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): BytesValue { + return new BytesValue().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): BytesValue { + return new BytesValue().fromJsonString(jsonString, options); + } + + static equals(a: BytesValue | PlainMessage | undefined, b: BytesValue | PlainMessage | undefined): boolean { + return proto3.util.equals(BytesValue, a, b); + } +} + diff --git a/packages/protobuf-test/src/google/protobuf/any.test.ts b/packages/protobuf-test/src/google/protobuf/any.test.ts index 4103eb7d4..f71a94865 100644 --- a/packages/protobuf-test/src/google/protobuf/any.test.ts +++ b/packages/protobuf-test/src/google/protobuf/any.test.ts @@ -12,74 +12,81 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Any, Struct, TypeRegistry, Value } from "@bufbuild/protobuf"; +import { createRegistry, Struct, Value } from "@bufbuild/protobuf"; +import { Any as TS_Any } from "../../gen/ts/google/protobuf/any_pb"; +import { Any as JS_Any } from "../../gen/js/google/protobuf/any_pb"; -describe(Any.typeName, () => { - const typeRegistry = TypeRegistry.from(Struct, Value); +describe("google.protobuf.Any", () => { + describe.each([ + { Any: TS_Any, name: `(generated ts)` }, + { Any: JS_Any, name: `(generated js)` }, + ])("$name", ({ Any }) => { + const typeRegistry = createRegistry(Struct, Value); - test(`encodes ${Struct.typeName} to JSON`, () => { - const str = new Struct({ - fields: { - foo: { kind: { case: "numberValue", value: 1 } }, - }, - }); - const got = Any.pack(str).toJson({ - typeRegistry, - }); - expect(got).toStrictEqual({ - "@type": "type.googleapis.com/google.protobuf.Struct", - value: { foo: 1 }, + test(`encodes ${Struct.typeName} to JSON`, () => { + const str = new Struct({ + fields: { + foo: { kind: { case: "numberValue", value: 1 } }, + }, + }); + const got = Any.pack(str).toJson({ + typeRegistry, + }); + expect(got).toStrictEqual({ + "@type": "type.googleapis.com/google.protobuf.Struct", + value: { foo: 1 }, + }); }); - }); - test(`encodes ${Value.typeName} to JSON`, () => { - const val = new Value({ - kind: { case: "numberValue", value: 1 }, - }); - const got = Any.pack(val).toJson({ - typeRegistry, - }); - expect(got).toStrictEqual({ - "@type": "type.googleapis.com/google.protobuf.Value", - value: 1, + test(`encodes ${Value.typeName} to JSON`, () => { + const val = new Value({ + kind: { case: "numberValue", value: 1 }, + }); + const got = Any.pack(val).toJson({ + typeRegistry, + }); + expect(got).toStrictEqual({ + "@type": "type.googleapis.com/google.protobuf.Value", + value: 1, + }); }); - }); - test(`encodes ${Value.typeName} with ${Struct.typeName} to JSON`, () => { - const want = { - "@type": "type.googleapis.com/google.protobuf.Value", - value: { - foo: 1, - }, - }; - const got = Any.pack( - new Value({ - kind: { - case: "structValue", - value: new Struct({ - fields: { - foo: { kind: { case: "numberValue", value: 1 } }, - }, - }), + test(`encodes ${Value.typeName} with ${Struct.typeName} to JSON`, () => { + const want = { + "@type": "type.googleapis.com/google.protobuf.Value", + value: { + foo: 1, }, - }) - ).toJson({ typeRegistry }); - expect(got).toStrictEqual(want); - }); + }; + const got = Any.pack( + new Value({ + kind: { + case: "structValue", + value: new Struct({ + fields: { + foo: { kind: { case: "numberValue", value: 1 } }, + }, + }), + }, + }) + ).toJson({ typeRegistry }); + expect(got).toStrictEqual(want); + }); - test(`decodes ${Value.typeName} from JSON`, () => { - const want = new Value({ - kind: { case: "numberValue", value: 1 }, + test(`decodes ${Value.typeName} from JSON`, () => { + const want = new Value({ + kind: { case: "numberValue", value: 1 }, + }); + const any = Any.fromJson( + { + "@type": "type.googleapis.com/google.protobuf.Value", + value: 1, + }, + { typeRegistry } + ); + const got = new Value(); + expect(any.unpackTo(got)).toBe(true); + expect(got).toStrictEqual(want); }); - const any = Any.fromJson( - { - "@type": "type.googleapis.com/google.protobuf.Value", - value: 1, - }, - { typeRegistry } - ); - const got = new Value(); - expect(any.unpackTo(got)).toBe(true); - expect(got).toStrictEqual(want); }); }); diff --git a/packages/protobuf-test/src/google/protobuf/duration.test.ts b/packages/protobuf-test/src/google/protobuf/duration.test.ts index ec6a7b1c6..b56c61a18 100644 --- a/packages/protobuf-test/src/google/protobuf/duration.test.ts +++ b/packages/protobuf-test/src/google/protobuf/duration.test.ts @@ -12,38 +12,44 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Duration } from "@bufbuild/protobuf"; +import { Duration as TS_Duration } from "../../gen/ts/google/protobuf/duration_pb.js"; +import { Duration as JS_Duration } from "../../gen/js/google/protobuf/duration_pb.js"; /* eslint-disable @typescript-eslint/ban-ts-comment */ -describe(Duration.typeName, () => { - const json3s = "3s"; - const json3s1ms = "3.000001s"; - const json3s1ns = "3.000000001s"; - // @ts-expect-error TS2737 - const dura3s = new Duration({ seconds: 3n, nanos: 0 }); - // @ts-expect-error TS2737 - const dura3s1ms = new Duration({ seconds: 3n, nanos: 1000 }); - // @ts-expect-error TS2737 - const dura3s1ns = new Duration({ seconds: 3n, nanos: 1 }); +describe("google.protobuf.Duration", () => { + describe.each([ + { Duration: TS_Duration, name: `(generated ts)` }, + { Duration: JS_Duration, name: `(generated js)` }, + ])("$name", ({ Duration }) => { + const json3s = "3s"; + const json3s1ms = "3.000001s"; + const json3s1ns = "3.000000001s"; + // @ts-expect-error TS2737 + const dura3s = new Duration({ seconds: 3n, nanos: 0 }); + // @ts-expect-error TS2737 + const dura3s1ms = new Duration({ seconds: 3n, nanos: 1000 }); + // @ts-expect-error TS2737 + const dura3s1ns = new Duration({ seconds: 3n, nanos: 1 }); - test("encodes 3s to JSON", () => { - expect(dura3s.toJson()).toBe(json3s); - }); - test("encodes 3s 1ms to JSON", () => { - expect(dura3s1ms.toJson()).toBe(json3s1ms); - }); - test("encodes 3s 1ns to JSON", () => { - expect(dura3s1ns.toJson()).toBe(json3s1ns); - }); + test("encodes 3s to JSON", () => { + expect(dura3s.toJson()).toBe(json3s); + }); + test("encodes 3s 1ms to JSON", () => { + expect(dura3s1ms.toJson()).toBe(json3s1ms); + }); + test("encodes 3s 1ns to JSON", () => { + expect(dura3s1ns.toJson()).toBe(json3s1ns); + }); - test("decodes 3s from JSON", () => { - expect(Duration.fromJson(json3s)).toStrictEqual(dura3s); - }); - test("decodes 3s 1ms from JSON", () => { - expect(Duration.fromJson(json3s1ms)).toStrictEqual(dura3s1ms); - }); - test("decodes 3s 1ns from JSON", () => { - expect(Duration.fromJson(json3s1ns)).toStrictEqual(dura3s1ns); + test("decodes 3s from JSON", () => { + expect(Duration.fromJson(json3s)).toStrictEqual(dura3s); + }); + test("decodes 3s 1ms from JSON", () => { + expect(Duration.fromJson(json3s1ms)).toStrictEqual(dura3s1ms); + }); + test("decodes 3s 1ns from JSON", () => { + expect(Duration.fromJson(json3s1ns)).toStrictEqual(dura3s1ns); + }); }); }); diff --git a/packages/protobuf-test/src/google/protobuf/field_mask.test.ts b/packages/protobuf-test/src/google/protobuf/field_mask.test.ts index a475913e7..2a09c1a09 100644 --- a/packages/protobuf-test/src/google/protobuf/field_mask.test.ts +++ b/packages/protobuf-test/src/google/protobuf/field_mask.test.ts @@ -12,20 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { FieldMask } from "@bufbuild/protobuf"; +import { FieldMask as TS_FieldMask } from "../../gen/ts/google/protobuf/field_mask_pb"; +import { FieldMask as JS_FieldMask } from "../../gen/js/google/protobuf/field_mask_pb"; -describe(FieldMask.typeName, () => { - const fieldMask = new FieldMask({ - paths: ["user.display_name", "photo"], - }); - const json = "user.displayName,photo"; - test("encodes to JSON", () => { - expect(fieldMask.toJson()).toBe(json); - }); - test("decodes from JSON", () => { - const want = new FieldMask({ +describe("google.protobuf.FieldMask", () => { + describe.each([ + { FieldMask: TS_FieldMask, name: `(generated ts)` }, + { FieldMask: JS_FieldMask, name: `(generated js)` }, + ])("$name", ({ FieldMask }) => { + const fieldMask = new FieldMask({ paths: ["user.display_name", "photo"], }); - expect(FieldMask.fromJson(json)).toStrictEqual(want); + const json = "user.displayName,photo"; + test("encodes to JSON", () => { + expect(fieldMask.toJson()).toBe(json); + }); + test("decodes from JSON", () => { + const want = new FieldMask({ + paths: ["user.display_name", "photo"], + }); + expect(FieldMask.fromJson(json)).toStrictEqual(want); + }); }); }); diff --git a/packages/protobuf-test/src/google/protobuf/struct.test.ts b/packages/protobuf-test/src/google/protobuf/struct.test.ts index 5831065f6..4570e690c 100644 --- a/packages/protobuf-test/src/google/protobuf/struct.test.ts +++ b/packages/protobuf-test/src/google/protobuf/struct.test.ts @@ -13,94 +13,110 @@ // limitations under the License. import type { JsonObject } from "@bufbuild/protobuf"; -import { Struct, Value } from "@bufbuild/protobuf"; +import * as TS from "../../gen/ts/google/protobuf/struct_pb"; +import * as JS from "../../gen/js/google/protobuf/struct_pb"; -describe(Value.typeName, () => { - test("encodes to JSON", () => { - const value = new Value({ - kind: { case: "boolValue", value: true }, +describe("google.protobuf.Struct", () => { + describe.each([ + { Struct: TS.Struct, name: `(generated ts)` }, + { Struct: JS.Struct, name: `(generated js)` }, + ])("$name", ({ Struct }) => { + let json: JsonObject; + let struct: TS.Struct; + beforeEach(() => { + json = { + a: 123, + b: "abc", + }; + struct = new Struct({ + fields: { + a: { + kind: { case: "numberValue", value: 123 }, + }, + b: { + kind: { case: "stringValue", value: "abc" }, + }, + }, + }); }); - expect(value.toJsonString()).toBe("true"); - }); - test("decodes from JSON", () => { - const value = Value.fromJsonString("true"); - expect(value.kind.case).toBe("boolValue"); - expect(value.kind.value).toBe(true); - }); - test("survives binary round trip", () => { - const want = new Value({ - kind: { case: "boolValue", value: true }, + test("encodes to JSON", () => { + const got = struct.toJson(); + expect(got).toStrictEqual(json); + }); + test("decodes from JSON", () => { + const got = Struct.fromJson(json); + expect(Object.keys(got.fields).length).toBe( + Object.keys(struct.fields).length + ); + expect(got.fields["a"].kind.case).toBe(struct.fields["a"].kind.case); + expect(got.fields["a"].kind.value).toBe(struct.fields["a"].kind.value); + expect(got.fields["b"].kind.case).toBe(struct.fields["b"].kind.case); + expect(got.fields["b"].kind.value).toBe(struct.fields["b"].kind.value); + }); + test("survives binary round trip", () => { + const got = Struct.fromBinary(struct.toBinary()); + expect(got).toStrictEqual(struct); }); - const got = Value.fromBinary(want.toBinary()); - expect(got).toStrictEqual(want); }); }); -describe(`${Value.typeName} with ${Struct.typeName} field`, () => { - let json: JsonObject; - let value: Value; - beforeEach(() => { - json = { - foo: 1, - }; - value = new Value({ - kind: { - case: "structValue", - value: new Struct({ - fields: { - foo: { kind: { case: "numberValue", value: 1 } }, - }, - }), - }, +describe("google.protobuf.Value", () => { + describe.each([ + { Value: TS.Value, name: `(generated ts)` }, + { Value: JS.Value, name: `(generated js)` }, + ])("$name", ({ Value }) => { + test("encodes to JSON", () => { + const value = new Value({ + kind: { case: "boolValue", value: true }, + }); + expect(value.toJsonString()).toBe("true"); + }); + test("decodes from JSON", () => { + const value = Value.fromJsonString("true"); + expect(value.kind.case).toBe("boolValue"); + expect(value.kind.value).toBe(true); + }); + test("survives binary round trip", () => { + const want = new Value({ + kind: { case: "boolValue", value: true }, + }); + const got = Value.fromBinary(want.toBinary()); + expect(got).toStrictEqual(want); }); - }); - test("encodes to JSON", () => { - expect(value.toJson()).toStrictEqual(json); - }); - test("decodes from JSON", () => { - expect(Value.fromJson(json)).toStrictEqual(value); - }); - test("survives binary round trip", () => { - const got = Value.fromBinary(value.toBinary()); - expect(got).toStrictEqual(value); }); }); -describe(Struct.typeName, () => { - let json: JsonObject; - let struct: Struct; - beforeEach(() => { - json = { - a: 123, - b: "abc", - }; - struct = new Struct({ - fields: { - a: { - kind: { case: "numberValue", value: 123 }, +describe("google.protobuf.Value with Struct field", () => { + describe.each([ + { Value: TS.Value, Struct: TS.Struct, name: `(generated ts)` }, + { Value: JS.Value, Struct: JS.Struct, name: `(generated js)` }, + ])("$name", ({ Value, Struct }) => { + let json: JsonObject; + let value: TS.Value; + beforeEach(() => { + json = { + foo: 1, + }; + value = new Value({ + kind: { + case: "structValue", + value: new Struct({ + fields: { + foo: { kind: { case: "numberValue", value: 1 } }, + }, + }), }, - b: { - kind: { case: "stringValue", value: "abc" }, - }, - }, + }); + }); + test("encodes to JSON", () => { + expect(value.toJson()).toStrictEqual(json); + }); + test("decodes from JSON", () => { + expect(Value.fromJson(json)).toStrictEqual(value); + }); + test("survives binary round trip", () => { + const got = Value.fromBinary(value.toBinary()); + expect(got).toStrictEqual(value); }); - }); - test("encodes to JSON", () => { - const got = struct.toJson(); - expect(got).toStrictEqual(json); - }); - test("decodes from JSON", () => { - const got = Struct.fromJson(json); - expect(Object.keys(got.fields).length).toBe( - Object.keys(struct.fields).length - ); - expect(got.fields["a"].kind.case).toBe(struct.fields["a"].kind.case); - expect(got.fields["a"].kind.value).toBe(struct.fields["a"].kind.value); - expect(got.fields["b"].kind.case).toBe(struct.fields["b"].kind.case); - expect(got.fields["b"].kind.value).toBe(struct.fields["b"].kind.value); - }); - test("survives binary round trip", () => { - const got = Struct.fromBinary(struct.toBinary()); - expect(got).toStrictEqual(struct); }); }); diff --git a/packages/protobuf-test/src/google/protobuf/timestamp.test.ts b/packages/protobuf-test/src/google/protobuf/timestamp.test.ts index c160e3db5..46ce4d6e2 100644 --- a/packages/protobuf-test/src/google/protobuf/timestamp.test.ts +++ b/packages/protobuf-test/src/google/protobuf/timestamp.test.ts @@ -12,18 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Timestamp } from "@bufbuild/protobuf"; +import { Timestamp as TS_Timestamp } from "../../gen/ts/google/protobuf/timestamp_pb"; +import { Timestamp as JS_Timestamp } from "../../gen/js/google/protobuf/timestamp_pb"; -describe(Timestamp.typeName, () => { - test("now()", () => { - const ts = Timestamp.now(); - expect(ts.seconds).toBeDefined(); - }); - - test("fromDate()", () => { - const a = new Date(); - const ts = Timestamp.fromDate(a); - const b = ts.toDate(); - expect(b.getTime()).toBe(a.getTime()); +describe("google.protobuf.Timestamp", () => { + describe.each([ + { Timestamp: TS_Timestamp, name: `(generated ts)` }, + { Timestamp: JS_Timestamp, name: `(generated js)` }, + ])("$name", ({ Timestamp }) => { + test("now()", () => { + const ts = Timestamp.now(); + expect(ts.seconds).toBeDefined(); + }); + test("fromDate()", () => { + const a = new Date(); + const ts = Timestamp.fromDate(a); + const b = ts.toDate(); + expect(b.getTime()).toBe(a.getTime()); + }); }); }); diff --git a/packages/protobuf-test/src/google/protobuf/wrappers.test.ts b/packages/protobuf-test/src/google/protobuf/wrappers.test.ts new file mode 100644 index 000000000..bf4b71d59 --- /dev/null +++ b/packages/protobuf-test/src/google/protobuf/wrappers.test.ts @@ -0,0 +1,198 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import * as JS from "../../gen/js/google/protobuf/wrappers_pb"; +import * as TS from "../../gen/js/google/protobuf/wrappers_pb"; +import { protoInt64 } from "@bufbuild/protobuf"; + +describe("google.protobuf.DoubleValue", () => { + describe.each([ + { DoubleValue: TS.DoubleValue, name: `(generated ts)` }, + { DoubleValue: JS.DoubleValue, name: `(generated js)` }, + ])("$name", ({ DoubleValue }) => { + const primitive = 12.3; + test("wraps", () => { + const got = DoubleValue.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(DoubleValue); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = DoubleValue.fieldWrapper.unwrapField( + new DoubleValue({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.FloatValue", () => { + describe.each([ + { FloatValue: TS.FloatValue, name: `(generated ts)` }, + { FloatValue: JS.FloatValue, name: `(generated js)` }, + ])("$name", ({ FloatValue }) => { + const primitive = 12.3; + test("wraps", () => { + const got = FloatValue.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(FloatValue); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = FloatValue.fieldWrapper.unwrapField( + new FloatValue({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.Int64Value", () => { + describe.each([ + { Int64Value: TS.Int64Value, name: `(generated ts)` }, + { Int64Value: JS.Int64Value, name: `(generated js)` }, + ])("$name", ({ Int64Value }) => { + const primitive = protoInt64.parse("-5100100100"); + test("wraps", () => { + const got = Int64Value.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(Int64Value); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = Int64Value.fieldWrapper.unwrapField( + new Int64Value({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.UInt64Value", () => { + describe.each([ + { UInt64Value: TS.UInt64Value, name: `(generated ts)` }, + { UInt64Value: JS.UInt64Value, name: `(generated js)` }, + ])("$name", ({ UInt64Value }) => { + const primitive = protoInt64.uParse("5100100100"); + test("wraps", () => { + const got = UInt64Value.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(UInt64Value); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = UInt64Value.fieldWrapper.unwrapField( + new UInt64Value({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.Int32Value", () => { + describe.each([ + { Int32Value: TS.Int32Value, name: `(generated ts)` }, + { Int32Value: JS.Int32Value, name: `(generated js)` }, + ])("$name", ({ Int32Value }) => { + const primitive = -123; + test("wraps", () => { + const got = Int32Value.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(Int32Value); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = Int32Value.fieldWrapper.unwrapField( + new Int32Value({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.UInt32Value", () => { + describe.each([ + { UInt32Value: TS.UInt32Value, name: `(generated ts)` }, + { UInt32Value: JS.UInt32Value, name: `(generated js)` }, + ])("$name", ({ UInt32Value }) => { + const primitive = 123; + test("wraps", () => { + const got = UInt32Value.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(UInt32Value); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = UInt32Value.fieldWrapper.unwrapField( + new UInt32Value({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.BoolValue", () => { + describe.each([ + { BoolValue: TS.BoolValue, name: `(generated ts)`, primitive: true }, + { BoolValue: TS.BoolValue, name: `(generated ts)`, primitive: false }, + { BoolValue: JS.BoolValue, name: `(generated js)`, primitive: true }, + { BoolValue: JS.BoolValue, name: `(generated js)`, primitive: false }, + ])("$name", ({ BoolValue, primitive }) => { + test("wraps", () => { + const got = BoolValue.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(BoolValue); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = BoolValue.fieldWrapper.unwrapField( + new BoolValue({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.StringValue", () => { + describe.each([ + { StringValue: TS.StringValue, name: `(generated ts)` }, + { StringValue: JS.StringValue, name: `(generated js)` }, + ])("$name", ({ StringValue }) => { + const primitive = "hello world"; + test("wraps", () => { + const got = StringValue.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(StringValue); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = StringValue.fieldWrapper.unwrapField( + new StringValue({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); + +describe("google.protobuf.BytesValue", () => { + describe.each([ + { BytesValue: TS.BytesValue, name: `(generated ts)` }, + { BytesValue: JS.BytesValue, name: `(generated js)` }, + ])("$name", ({ BytesValue }) => { + const primitive = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); + test("wraps", () => { + const got = BytesValue.fieldWrapper.wrapField(primitive); + expect(got).toBeInstanceOf(BytesValue); + expect(got.value).toBe(primitive); + }); + test("unwraps", () => { + const got = BytesValue.fieldWrapper.unwrapField( + new BytesValue({ value: primitive }) + ); + expect(got).toBe(primitive); + }); + }); +}); diff --git a/packages/protobuf-test/src/helpers.ts b/packages/protobuf-test/src/helpers.ts index a084d25db..2a9351e8e 100644 --- a/packages/protobuf-test/src/helpers.ts +++ b/packages/protobuf-test/src/helpers.ts @@ -12,11 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import type { Message, MessageType } from "@bufbuild/protobuf"; -import type { EnumType, FieldInfo } from "@bufbuild/protobuf"; +import type { + EnumType, + FieldInfo, + Message, + MessageType, +} from "@bufbuild/protobuf"; +import { createRegistryFromDescriptors } from "@bufbuild/protobuf"; import { readFileSync } from "fs"; -import { FileDescriptorSet } from "@bufbuild/protobuf"; -import { DescriptorRegistry } from "@bufbuild/protobuf"; /** * Runs a describe.each() with three test cases: @@ -66,11 +69,9 @@ export function testMT>( }); } -const fds = FileDescriptorSet.fromBinary(readFileSync("./descriptorset.bin")); -const dr = new DescriptorRegistry(); -dr.add(...fds.file); +const dr = createRegistryFromDescriptors(readFileSync("./descriptorset.bin")); -function makeMessageTypeDynamic>( +export function makeMessageTypeDynamic>( type: MessageType ): MessageType { const dyn = dr.findMessage(type.typeName); diff --git a/packages/protobuf-test/src/descriptor-registry.test.ts b/packages/protobuf-test/src/legacy-descriptor-registry.test.ts similarity index 75% rename from packages/protobuf-test/src/descriptor-registry.test.ts rename to packages/protobuf-test/src/legacy-descriptor-registry.test.ts index 482a351ab..115def597 100644 --- a/packages/protobuf-test/src/descriptor-registry.test.ts +++ b/packages/protobuf-test/src/legacy-descriptor-registry.test.ts @@ -14,8 +14,7 @@ import { readFileSync } from "fs"; import { - DescriptorRegistry, - DescriptorSet, + LegacyDescriptorRegistry, FileDescriptorSet, } from "@bufbuild/protobuf"; import { TestAllTypes } from "./gen/ts/google/protobuf/unittest_proto3_pb.js"; @@ -24,24 +23,14 @@ import { assertMessageTypeEquals } from "./helpers.js"; const fdsBytes = readFileSync("./descriptorset.bin"); const fds = FileDescriptorSet.fromBinary(fdsBytes); -describe("DescriptorSet", () => { - test("add() does not crash", () => { - const ds = new DescriptorSet(); - expect(ds.enums).toStrictEqual({}); - expect(ds.messages).toStrictEqual({}); - expect(ds.services).toStrictEqual({}); - ds.add(...fds.file); - }); -}); - -describe("DescriptorRegistry", () => { +describe("LegacyDescriptorRegistry", () => { test("finds nothing if empty", () => { - const dr = new DescriptorRegistry(); + const dr = new LegacyDescriptorRegistry(); expect(dr.findMessage("foo.Foo")).toBeUndefined(); expect(dr.findEnum("foo.Foo")).toBeUndefined(); }); test("fromDescriptorSet with instance", () => { - const dr = DescriptorRegistry.fromFileDescriptorSet(fds); + const dr = LegacyDescriptorRegistry.fromFileDescriptorSet(fds); expect(dr.findEnum("foo.Foo")).toBeUndefined(); const mt = dr.findMessage(TestAllTypes.typeName); expect(mt).toBeDefined(); @@ -50,7 +39,7 @@ describe("DescriptorRegistry", () => { } }); test("fromDescriptorSet with bytes", () => { - const dr = DescriptorRegistry.fromFileDescriptorSet(fdsBytes); + const dr = LegacyDescriptorRegistry.fromFileDescriptorSet(fdsBytes); expect(dr.findEnum("foo.Foo")).toBeUndefined(); const mt = dr.findMessage(TestAllTypes.typeName); expect(mt).toBeDefined(); diff --git a/packages/protobuf-test/src/legacy-descriptor-set.test.ts b/packages/protobuf-test/src/legacy-descriptor-set.test.ts new file mode 100644 index 000000000..5e1f56868 --- /dev/null +++ b/packages/protobuf-test/src/legacy-descriptor-set.test.ts @@ -0,0 +1,28 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { readFileSync } from "fs"; +import { FileDescriptorSet, LegacyDescriptorSet } from "@bufbuild/protobuf"; + +const fds = FileDescriptorSet.fromBinary(readFileSync("./descriptorset.bin")); + +describe("LegacyDescriptorSet", () => { + test("add() does not crash", () => { + const ds = new LegacyDescriptorSet(); + expect(ds.enums).toStrictEqual({}); + expect(ds.messages).toStrictEqual({}); + expect(ds.services).toStrictEqual({}); + ds.add(...fds.file); + }); +}); diff --git a/packages/protobuf/README.md b/packages/protobuf/README.md index 0b09165aa..a7a5632bd 100644 --- a/packages/protobuf/README.md +++ b/packages/protobuf/README.md @@ -1,9 +1,39 @@ # @bufbuild/protobuf -[![npm](https://img.shields.io/npm/v/@bufbuild/protobuf?style=flat-square)](https://www.npmjs.com/package/@bufbuild/protobuf) +This package provides the runtime library for the code generator plugin +[`protoc-gen-es`](https://github.com/bufbuild/packages/protoc-gen-es). -A complete implementation of protocol buffers in TypeScript, -suitable for web browsers and Node.js. +## Protocol Buffers for ECMAScript + +A complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) +in TypeScript, suitable for web browsers and Node.js. Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). -This is the runtime library for the code generator plugin [`protoc-gen-es`](../protoc-gen-es). + +It is a complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) +in TypeScript, suitable for web browsers and Node.js. + +For example, the following definition: + +```protobuf +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; +} +``` + +Is compiled to an ECMAScript class that can be used like this: + +```typescript +let pete = new Person({ + name: "pete", + id: 123 +}); + +let bytes = pete.toBinary(); +pete = Person.fromBinary(bytes); +pete = Person.fromJsonString('{"name": "pete", "id": 123}'); +``` + +Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). diff --git a/packages/protobuf/package.json b/packages/protobuf/package.json index 592390f58..6715b06a1 100644 --- a/packages/protobuf/package.json +++ b/packages/protobuf/package.json @@ -2,7 +2,7 @@ "name": "@bufbuild/protobuf", "version": "0.0.8", "license": "(Apache-2.0 AND BSD-3-Clause)", - "description": "A complete implementation of protocol buffers in TypeScript, suitable for web browsers and Node.js.", + "description": "A complete implementation of Protocol Buffers in TypeScript, suitable for web browsers and Node.js.", "repository": { "type": "git", "url": "https://github.com/bufbuild/protobuf-es.git", diff --git a/packages/protobuf/src/codegen-info.ts b/packages/protobuf/src/codegen-info.ts new file mode 100644 index 000000000..d62f5e7f3 --- /dev/null +++ b/packages/protobuf/src/codegen-info.ts @@ -0,0 +1,94 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { localName } from "./private/names.js"; +import { getUnwrappedFieldType } from "./private/field-wrapper.js"; +import { scalarDefaultValue } from "./private/scalars.js"; + +interface CodegenInfo { + readonly packageName: string; + readonly localName: typeof localName; + readonly symbols: Record; + readonly getUnwrappedFieldType: typeof getUnwrappedFieldType; + readonly wktSourceFiles: readonly string[]; + readonly scalarDefaultValue: typeof scalarDefaultValue; +} + +type RuntimeSymbolName = + | "proto2" + | "proto3" + | "Message" + | "PartialMessage" + | "PlainMessage" + | "FieldList" + | "MessageType" + | "BinaryReadOptions" + | "BinaryWriteOptions" + | "JsonReadOptions" + | "JsonWriteOptions" + | "JsonValue" + | "JsonObject" + | "protoInt64" + | "ScalarType" + | "MethodKind" + | "MethodIdempotency"; + +type RuntimeSymbolInfo = { + typeOnly: boolean; + publicImportPath: string; + privateImportPath: string; +}; + +const packageName = "@bufbuild/protobuf"; + +export const codegenInfo: CodegenInfo = { + packageName, + localName, + getUnwrappedFieldType, + scalarDefaultValue, + // prettier-ignore + symbols: { + proto2: {typeOnly: false, privateImportPath: "./proto2.js", publicImportPath: packageName}, + proto3: {typeOnly: false, privateImportPath: "./proto3.js", publicImportPath: packageName}, + Message: {typeOnly: false, privateImportPath: "./message.js", publicImportPath: packageName}, + PartialMessage: {typeOnly: true, privateImportPath: "./message.js", publicImportPath: packageName}, + PlainMessage: {typeOnly: true, privateImportPath: "./message.js", publicImportPath: packageName}, + FieldList: {typeOnly: true, privateImportPath: "./field-list.js", publicImportPath: packageName}, + MessageType: {typeOnly: true, privateImportPath: "./message-type.js", publicImportPath: packageName}, + BinaryReadOptions: {typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName}, + BinaryWriteOptions: {typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName}, + JsonReadOptions: {typeOnly: true, privateImportPath: "./json-format.js", publicImportPath: packageName}, + JsonWriteOptions: {typeOnly: true, privateImportPath: "./json-format.js", publicImportPath: packageName}, + JsonValue: {typeOnly: true, privateImportPath: "./json-format.js", publicImportPath: packageName}, + JsonObject: {typeOnly: true, privateImportPath: "./json-format.js", publicImportPath: packageName}, + protoInt64: {typeOnly: false, privateImportPath: "./proto-int64.js", publicImportPath: packageName}, + ScalarType: {typeOnly: false, privateImportPath: "./field.js", publicImportPath: packageName}, + MethodKind: {typeOnly: false, privateImportPath: "./service-type.js", publicImportPath: packageName}, + MethodIdempotency: {typeOnly: false, privateImportPath: "./service-type.js", publicImportPath: packageName}, + }, + wktSourceFiles: [ + "google/protobuf/compiler/plugin.proto", + "google/protobuf/any.proto", + "google/protobuf/api.proto", + "google/protobuf/descriptor.proto", + "google/protobuf/duration.proto", + "google/protobuf/empty.proto", + "google/protobuf/field_mask.proto", + "google/protobuf/source_context.proto", + "google/protobuf/struct.proto", + "google/protobuf/timestamp.proto", + "google/protobuf/type.proto", + "google/protobuf/wrappers.proto", + ], +} as const; diff --git a/packages/protobuf/src/create-descriptor-set.ts b/packages/protobuf/src/create-descriptor-set.ts new file mode 100644 index 000000000..8640dd512 --- /dev/null +++ b/packages/protobuf/src/create-descriptor-set.ts @@ -0,0 +1,1167 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { + DescriptorProto, + EnumDescriptorProto, + FieldDescriptorProto, + OneofDescriptorProto, +} from "./google/protobuf/descriptor_pb.js"; +import { + FieldDescriptorProto_Label, + FieldDescriptorProto_Type, + FileDescriptorProto, + FileDescriptorSet, + MethodDescriptorProto, + MethodOptions_IdempotencyLevel, + ServiceDescriptorProto, + SourceCodeInfo, +} from "./google/protobuf/descriptor_pb.js"; +import { assert } from "./private/assert.js"; +import type { + DescComments, + DescEnum, + DescExtension, + DescField, + DescFile, + DescMessage, + DescMethod, + DescOneof, + DescriptorSet, + DescService, +} from "./descriptor-set.js"; +import { ScalarType } from "./field.js"; +import { MethodIdempotency, MethodKind } from "./service-type.js"; +import { findEnumSharedPrefix, fieldJsonName } from "./private/names.js"; +import { protoInt64 } from "./proto-int64.js"; + +/** + * Create a DescriptorSet, a convenient interface for working with a set of + * google.protobuf.FileDescriptorProto. + * + * Note that files must be given in topological order, so each file appears + * before any file that imports it. Protocol buffer compilers always produce + * files in topological order. + */ +export function createDescriptorSet( + input: FileDescriptorProto[] | FileDescriptorSet | Uint8Array +): DescriptorSet { + const cart = { + enums: new Map(), + messages: new Map(), + services: new Map(), + extensions: new Map(), + mapEntries: new Map(), + }; + const fileDescriptors = + input instanceof FileDescriptorSet + ? input.file + : input instanceof Uint8Array + ? FileDescriptorSet.fromBinary(input).file + : input; + const files = fileDescriptors.map((proto) => newFile(proto, cart)); + return { files, ...cart }; +} + +/** + * Cart is an implementation detail. It captures a few variables we + * use to resolve reference when creating descriptors. + */ +interface Cart { + enums: Map; + messages: Map; + services: Map; + extensions: Map; + mapEntries: Map; +} + +/** + * Create a descriptor for a file. + */ +function newFile(proto: FileDescriptorProto, cart: Cart): DescFile { + assert(proto.name, `invalid FileDescriptorProto: missing name`); + assert( + proto.syntax === undefined || proto.syntax === "proto3", + `invalid FileDescriptorProto: unsupported syntax: ${ + proto.syntax ?? "undefined" + }` + ); + const file: DescFile = { + kind: "file", + proto, + deprecated: proto.options?.deprecated ?? false, + syntax: proto.syntax === "proto3" ? "proto3" : "proto2", + name: proto.name.replace(/\.proto/, ""), + enums: [], + messages: [], + extensions: [], + services: [], + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `file ${this.proto.name}`; + }, + getSyntaxComments() { + return findComments(this.proto.sourceCodeInfo, [ + FieldNumber.FileDescriptorProto_Syntax, + ]); + }, + getPackageComments() { + return findComments(this.proto.sourceCodeInfo, [ + FieldNumber.FileDescriptorProto_Package, + ]); + }, + }; + cart.mapEntries.clear(); // map entries are local to the file, we can safely discard + for (const enumProto of proto.enumType) { + addEnum(enumProto, file, undefined, cart); + } + for (const messageProto of proto.messageType) { + addMessage(messageProto, file, undefined, cart); + } + for (const serviceProto of proto.service) { + addService(serviceProto, file, cart); + } + addExtensions(file, cart); + for (const mapEntry of cart.mapEntries.values()) { + addFields(mapEntry, cart); + } + for (const message of file.messages) { + addFields(message, cart); + addExtensions(message, cart); + } + cart.mapEntries.clear(); // map entries are local to the file, we can safely discard + return file; +} + +/** + * Create descriptors for extensions, and add them to the message / file, + * and to our cart. + * Recurses into nested types. + */ +function addExtensions(desc: DescFile | DescMessage, cart: Cart): void { + switch (desc.kind) { + case "file": + for (const proto of desc.proto.extension) { + const ext = newExtension(proto, desc, undefined, cart); + desc.extensions.push(ext); + cart.extensions.set(ext.typeName, ext); + } + break; + case "message": + for (const proto of desc.proto.extension) { + const ext = newExtension(proto, desc.file, desc, cart); + desc.nestedExtensions.push(ext); + cart.extensions.set(ext.typeName, ext); + } + for (const message of desc.nestedMessages) { + addExtensions(message, cart); + } + break; + } +} + +/** + * Create descriptors for fields and oneof groups, and add them to the message. + * Recurses into nested types. + */ +function addFields(message: DescMessage, cart: Cart): void { + const allOneofs = message.proto.oneofDecl.map((proto) => + newOneof(proto, message) + ); + const oneofsSeen = new Set(); + for (const proto of message.proto.field) { + const oneof = findOneof(proto, allOneofs); + const field = newField(proto, message.file, message, oneof, cart); + message.fields.push(field); + if (oneof === undefined) { + message.members.push(field); + } else { + oneof.fields.push(field); + if (!oneofsSeen.has(oneof)) { + oneofsSeen.add(oneof); + message.members.push(oneof); + } + } + } + for (const oneof of allOneofs.filter((o) => oneofsSeen.has(o))) { + message.oneofs.push(oneof); + } + for (const child of message.nestedMessages) { + addFields(child, cart); + } +} + +/** + * Create a descriptor for an enumeration, and add it our cart and to the + * parent type, if any. + */ +function addEnum( + proto: EnumDescriptorProto, + file: DescFile, + parent: DescMessage | undefined, + cart: Cart +): void { + assert(proto.name, `invalid EnumDescriptorProto: missing name`); + const desc: DescEnum = { + kind: "enum", + proto, + deprecated: proto.options?.deprecated ?? false, + file, + parent, + name: proto.name, + typeName: makeTypeName(proto, parent, file), + values: [], + sharedPrefix: findEnumSharedPrefix( + proto.name, + proto.value.map((v) => v.name ?? "") + ), + toString(): string { + return `enum ${this.typeName}`; + }, + getComments() { + const path = this.parent + ? [ + ...this.parent.getComments().sourcePath, + FieldNumber.DescriptorProto_EnumType, + this.parent.proto.enumType.indexOf(this.proto), + ] + : [ + FieldNumber.FileDescriptorProto_EnumType, + this.file.proto.enumType.indexOf(this.proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }; + cart.enums.set(desc.typeName, desc); + proto.value.forEach((proto) => { + assert(proto.name, `invalid EnumValueDescriptorProto: missing name`); + assert( + proto.number !== undefined, + `invalid EnumValueDescriptorProto: missing number` + ); + desc.values.push({ + kind: "enum_value", + proto, + deprecated: proto.options?.deprecated ?? false, + parent: desc, + name: proto.name, + number: proto.number, + toString() { + return `enum value ${desc.typeName}.${this.name}`; + }, + declarationString() { + let str = `${this.name} = ${this.number}`; + if (this.proto.options?.deprecated === true) { + str += " [deprecated = true]"; + } + return str; + }, + getComments() { + const path = [ + ...this.parent.getComments().sourcePath, + FieldNumber.EnumDescriptorProto_Value, + this.parent.proto.value.indexOf(this.proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }); + }); + (parent?.nestedEnums ?? file.enums).push(desc); +} + +/** + * Create a descriptor for a message, including nested types, and add it to our + * cart. Note that this does not create descriptors fields. + */ +function addMessage( + proto: DescriptorProto, + file: DescFile, + parent: DescMessage | undefined, + cart: Cart +): void { + assert(proto.name, `invalid DescriptorProto: missing name`); + const desc: DescMessage = { + kind: "message", + proto, + deprecated: proto.options?.deprecated ?? false, + file, + parent, + name: proto.name, + typeName: makeTypeName(proto, parent, file), + fields: [], + oneofs: [], + members: [], + nestedEnums: [], + nestedMessages: [], + nestedExtensions: [], + toString(): string { + return `message ${this.typeName}`; + }, + getComments() { + const path = this.parent + ? [ + ...this.parent.getComments().sourcePath, + FieldNumber.DescriptorProto_NestedType, + this.parent.proto.nestedType.indexOf(this.proto), + ] + : [ + FieldNumber.FileDescriptorProto_MessageType, + this.file.proto.messageType.indexOf(this.proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }; + if (proto.options?.mapEntry === true) { + cart.mapEntries.set(desc.typeName, desc); + } else { + (parent?.nestedMessages ?? file.messages).push(desc); + cart.messages.set(desc.typeName, desc); + } + for (const enumProto of proto.enumType) { + addEnum(enumProto, file, desc, cart); + } + for (const messageProto of proto.nestedType) { + addMessage(messageProto, file, desc, cart); + } +} + +/** + * Create a descriptor for a service, including methods, and add it to our + * cart. + */ +function addService( + proto: ServiceDescriptorProto, + file: DescFile, + cart: Cart +): void { + assert(proto.name, `invalid ServiceDescriptorProto: missing name`); + const desc: DescService = { + kind: "service", + proto, + deprecated: proto.options?.deprecated ?? false, + file, + name: proto.name, + typeName: makeTypeName(proto, undefined, file), + methods: [], + toString(): string { + return `service ${this.typeName}`; + }, + getComments() { + const path = [ + FieldNumber.FileDescriptorProto_Service, + this.file.proto.service.indexOf(this.proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }; + file.services.push(desc); + cart.services.set(desc.typeName, desc); + for (const methodProto of proto.method) { + desc.methods.push(newMethod(methodProto, desc, cart)); + } +} + +/** + * Create a descriptor for a method. + */ +function newMethod( + proto: MethodDescriptorProto, + parent: DescService, + cart: Cart +): DescMethod { + assert(proto.name, `invalid MethodDescriptorProto: missing name`); + assert(proto.inputType, `invalid MethodDescriptorProto: missing input_type`); + assert( + proto.outputType, + `invalid MethodDescriptorProto: missing output_type` + ); + let methodKind: MethodKind; + if (proto.clientStreaming === true && proto.serverStreaming === true) { + methodKind = MethodKind.BiDiStreaming; + } else if (proto.clientStreaming === true) { + methodKind = MethodKind.ClientStreaming; + } else if (proto.serverStreaming === true) { + methodKind = MethodKind.ServerStreaming; + } else { + methodKind = MethodKind.Unary; + } + let idempotency: MethodIdempotency | undefined; + switch (proto.options?.idempotencyLevel) { + case MethodOptions_IdempotencyLevel.IDEMPOTENT: + idempotency = MethodIdempotency.Idempotent; + break; + case MethodOptions_IdempotencyLevel.NO_SIDE_EFFECTS: + idempotency = MethodIdempotency.NoSideEffects; + break; + case MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN: + case undefined: + idempotency = undefined; + break; + } + const input = cart.messages.get(trimLeadingDot(proto.inputType)); + const output = cart.messages.get(trimLeadingDot(proto.outputType)); + assert( + input, + `invalid MethodDescriptorProto: input_type ${proto.inputType} not found` + ); + assert( + output, + `invalid MethodDescriptorProto: output_type ${proto.inputType} not found` + ); + const name = proto.name; + return { + kind: "rpc", + proto, + deprecated: proto.options?.deprecated ?? false, + parent, + name, + methodKind, + input, + output, + idempotency, + toString() { + return `rpc ${parent.typeName}.${name}`; + }, + getComments() { + const path = [ + ...this.parent.getComments().sourcePath, + FieldNumber.ServiceDescriptorProto_Method, + this.parent.proto.method.indexOf(this.proto), + ]; + return findComments(parent.file.proto.sourceCodeInfo, path); + }, + }; +} + +/** + * Create a descriptor for a oneof group. + */ +function newOneof(proto: OneofDescriptorProto, parent: DescMessage): DescOneof { + assert(proto.name, `invalid OneofDescriptorProto: missing name`); + return { + kind: "oneof", + proto, + deprecated: false, + parent, + fields: [], + name: proto.name, + toString(): string { + return `oneof ${parent.typeName}.${this.name}`; + }, + getComments() { + const path = [ + ...this.parent.getComments().sourcePath, + FieldNumber.DescriptorProto_OneofDecl, + this.parent.proto.oneofDecl.indexOf(this.proto), + ]; + return findComments(parent.file.proto.sourceCodeInfo, path); + }, + }; +} + +/** + * Create a descriptor for a field. + */ +function newField( + proto: FieldDescriptorProto, + file: DescFile, + parent: DescMessage, + oneof: DescOneof | undefined, + cart: Cart +): DescField { + assert(proto.name, `invalid FieldDescriptorProto: missing name`); + assert(proto.number, `invalid FieldDescriptorProto: missing number`); + assert(proto.type, `invalid FieldDescriptorProto: missing type`); + const packedByDefault = isPackedFieldByDefault(proto, file.syntax); + const common = { + proto, + deprecated: proto.options?.deprecated ?? false, + name: proto.name, + number: proto.number, + parent, + oneof, + optional: isOptionalField(proto, file.syntax), + packed: proto.options?.packed ?? packedByDefault, + packedByDefault, + jsonName: + proto.jsonName === fieldJsonName(proto.name) ? undefined : proto.jsonName, + scalar: undefined, + message: undefined, + enum: undefined, + mapKey: undefined, + mapValue: undefined, + toString(): string { + // note that newExtension() calls us with parent = null + return `field ${this.parent.typeName}.${this.name}`; + }, + declarationString, + getComments() { + const path = [ + ...this.parent.getComments().sourcePath, + FieldNumber.DescriptorProto_Field, + this.parent.proto.field.indexOf(this.proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }; + const repeated = proto.label === FieldDescriptorProto_Label.REPEATED; + switch (proto.type) { + case FieldDescriptorProto_Type.MESSAGE: + case FieldDescriptorProto_Type.GROUP: { + assert(proto.typeName, `invalid FieldDescriptorProto: missing type_name`); + const mapEntry = cart.mapEntries.get(trimLeadingDot(proto.typeName)); + if (mapEntry !== undefined) { + assert( + repeated, + `invalid FieldDescriptorProto: expected map entry to be repeated` + ); + return { + ...common, + kind: "map_field", + repeated: false, + ...getMapFieldTypes(mapEntry), + }; + } + const message = cart.messages.get(trimLeadingDot(proto.typeName)); + assert( + message !== undefined, + `invalid FieldDescriptorProto: type_name ${proto.typeName} not found` + ); + return { + ...common, + kind: "message_field", + repeated, + message, + }; + } + case FieldDescriptorProto_Type.ENUM: { + assert(proto.typeName, `invalid FieldDescriptorProto: missing type_name`); + const e = cart.enums.get(trimLeadingDot(proto.typeName)); + assert( + e !== undefined, + `invalid FieldDescriptorProto: type_name ${proto.typeName} not found` + ); + return { + ...common, + kind: "enum_field", + getDefaultValue, + repeated, + enum: e, + }; + } + default: { + const scalar = fieldTypeToScalarType[proto.type]; + assert( + scalar, + `invalid FieldDescriptorProto: unknown type ${proto.type}` + ); + return { + ...common, + kind: "scalar_field", + getDefaultValue, + repeated, + scalar, + }; + } + } +} + +/** + * Create a descriptor for an extension field. + */ +function newExtension( + proto: FieldDescriptorProto, + file: DescFile, + parent: DescMessage | undefined, + cart: Cart +): DescExtension { + assert(proto.extendee, `invalid FieldDescriptorProto: missing extendee`); + const field = newField( + proto, + file, + null as unknown as DescMessage, // to safe us many lines of duplicated code, we trick the type system + undefined, + cart + ); + const extendee = cart.messages.get(trimLeadingDot(proto.extendee)); + assert( + extendee, + `invalid FieldDescriptorProto: extendee ${proto.extendee} not found` + ); + return { + ...field, + typeName: makeTypeName(proto, parent, file), + parent, + file, + extendee, + toString(): string { + return `extension ${this.typeName}`; + }, + getComments() { + const path = this.parent + ? [ + ...this.parent.getComments().sourcePath, + FieldNumber.DescriptorProto_Extension, + this.parent.proto.extension.indexOf(proto), + ] + : [ + FieldNumber.FileDescriptorProto_Extension, + this.file.proto.extension.indexOf(proto), + ]; + return findComments(file.proto.sourceCodeInfo, path); + }, + }; +} + +/** + * Create a fully qualified name for a protobuf type or extension field. + * + * The fully qualified name for messages, enumerations, and services is + * constructed by concatenating the package name (if present), parent + * message names (for nested types), and the type name. We omit the leading + * dot added by protobuf compilers. Examples: + * - mypackage.MyMessage + * - mypackage.MyMessage.NestedMessage + * + * The fully qualified name for extension fields is constructed by + * concatenating the package name (if present), parent message names (for + * extensions declared within a message), and the field name. Examples: + * - mypackage.extfield + * - mypackage.MyMessage.extfield + */ +function makeTypeName( + proto: + | DescriptorProto + | ServiceDescriptorProto + | EnumDescriptorProto + | FieldDescriptorProto, + parent: DescMessage | DescService | undefined, + file: DescFile +): string { + assert(proto.name, `invalid ${proto.getType().typeName}: missing name`); + let typeName: string; + if (parent) { + typeName = `${parent.typeName}.${proto.name}`; + } else if (file.proto.package !== undefined) { + typeName = `${file.proto.package}.${proto.name}`; + } else { + typeName = `${proto.name}`; + } + return typeName; +} + +/** + * Remove the leading dot from a fully qualified type name. + */ +function trimLeadingDot(typeName: string): string { + return typeName.startsWith(".") ? typeName.substring(1) : typeName; +} + +function getMapFieldTypes( + mapEntry: DescMessage +): Pick { + assert( + mapEntry.proto.options?.mapEntry, + `invalid DescriptorProto: expected ${mapEntry.toString()} to be a map entry` + ); + assert( + mapEntry.fields.length === 2, + `invalid DescriptorProto: map entry ${mapEntry.toString()} has ${ + mapEntry.fields.length + } fields` + ); + const keyField = mapEntry.fields.find((f) => f.proto.number === 1); + assert( + keyField, + `invalid DescriptorProto: map entry ${mapEntry.toString()} is missing key field` + ); + const mapKey = keyField.scalar; + assert( + mapKey !== undefined && + mapKey !== ScalarType.BYTES && + mapKey !== ScalarType.FLOAT && + mapKey !== ScalarType.DOUBLE, + `invalid DescriptorProto: map entry ${mapEntry.toString()} has unexpected key type ${ + keyField.proto.type ?? -1 + }` + ); + const valueField = mapEntry.fields.find((f) => f.proto.number === 2); + assert( + valueField, + `invalid DescriptorProto: map entry ${mapEntry.toString()} is missing value field` + ); + switch (valueField.kind) { + case "scalar_field": + return { + mapKey, + mapValue: { + ...valueField, + kind: "scalar", + }, + }; + case "message_field": + return { + mapKey, + mapValue: { + ...valueField, + kind: "message", + }, + }; + case "enum_field": + return { + mapKey, + mapValue: { + ...valueField, + kind: "enum", + }, + }; + default: + throw new Error( + "invalid DescriptorProto: unsupported map entry value field" + ); + } +} + +/** + * Did the user put the field in a oneof group? + * This handles proto3 optionals. + */ +function findOneof( + proto: FieldDescriptorProto, + allOneofs: DescOneof[] +): DescOneof | undefined { + const oneofIndex = proto.oneofIndex; + if (oneofIndex === undefined) { + return undefined; + } + let oneof: DescOneof | undefined; + if (proto.proto3Optional !== true) { + oneof = allOneofs[oneofIndex]; + assert( + oneof, + `invalid FieldDescriptorProto: oneof #${oneofIndex} for field #${ + proto.number ?? -1 + } not found` + ); + } + return oneof; +} + +/** + * Did the user use the `optional` keyword? + * This handles proto3 optionals. + */ +function isOptionalField( + proto: FieldDescriptorProto, + syntax: "proto2" | "proto3" +): boolean { + switch (syntax) { + case "proto2": + return ( + proto.oneofIndex === undefined && + proto.label === FieldDescriptorProto_Label.OPTIONAL + ); + case "proto3": + return proto.proto3Optional === true; + } +} + +/** + * Get the default `packed` state of a repeated field. + */ +export function isPackedFieldByDefault( + proto: FieldDescriptorProto, + syntax: "proto2" | "proto3" +): boolean { + assert(proto.type, `invalid FieldDescriptorProto: missing type`); + if (syntax === "proto3") { + switch (proto.type) { + case FieldDescriptorProto_Type.DOUBLE: + case FieldDescriptorProto_Type.FLOAT: + case FieldDescriptorProto_Type.INT64: + case FieldDescriptorProto_Type.UINT64: + case FieldDescriptorProto_Type.INT32: + case FieldDescriptorProto_Type.FIXED64: + case FieldDescriptorProto_Type.FIXED32: + case FieldDescriptorProto_Type.UINT32: + case FieldDescriptorProto_Type.SFIXED32: + case FieldDescriptorProto_Type.SFIXED64: + case FieldDescriptorProto_Type.SINT32: + case FieldDescriptorProto_Type.SINT64: + case FieldDescriptorProto_Type.BOOL: + case FieldDescriptorProto_Type.ENUM: + // From the proto3 language guide: + // > In proto3, repeated fields of scalar numeric types are packed by default. + // This information is incomplete - according to the conformance tests, BOOL + // and ENUM are packed by default as well. This means only STRING and BYTES + // are not packed by default, which makes sense because they are length-delimited. + return true; + default: + return false; + } + } + return false; +} + +/** + * Map from a compiler-generated field type to our ScalarType, which is a + * subset of field types declared by protobuf enum google.protobuf.FieldDescriptorProto. + */ +const fieldTypeToScalarType: Record< + FieldDescriptorProto_Type, + ScalarType | undefined +> = { + [FieldDescriptorProto_Type.DOUBLE]: ScalarType.DOUBLE, + [FieldDescriptorProto_Type.FLOAT]: ScalarType.FLOAT, + [FieldDescriptorProto_Type.INT64]: ScalarType.INT64, + [FieldDescriptorProto_Type.UINT64]: ScalarType.UINT64, + [FieldDescriptorProto_Type.INT32]: ScalarType.INT32, + [FieldDescriptorProto_Type.FIXED64]: ScalarType.FIXED64, + [FieldDescriptorProto_Type.FIXED32]: ScalarType.FIXED32, + [FieldDescriptorProto_Type.BOOL]: ScalarType.BOOL, + [FieldDescriptorProto_Type.STRING]: ScalarType.STRING, + [FieldDescriptorProto_Type.GROUP]: undefined, + [FieldDescriptorProto_Type.MESSAGE]: undefined, + [FieldDescriptorProto_Type.BYTES]: ScalarType.BYTES, + [FieldDescriptorProto_Type.UINT32]: ScalarType.UINT32, + [FieldDescriptorProto_Type.ENUM]: undefined, + [FieldDescriptorProto_Type.SFIXED32]: ScalarType.SFIXED32, + [FieldDescriptorProto_Type.SFIXED64]: ScalarType.SFIXED64, + [FieldDescriptorProto_Type.SINT32]: ScalarType.SINT32, + [FieldDescriptorProto_Type.SINT64]: ScalarType.SINT64, +}; + +/** + * Find comments. + */ +function findComments( + sourceCodeInfo: SourceCodeInfo | undefined, + sourcePath: number[] +): DescComments { + if (!sourceCodeInfo) { + return { + leadingDetached: [], + sourcePath, + }; + } + for (const location of sourceCodeInfo.location) { + if (location.path.length !== sourcePath.length) { + continue; + } + if (location.path.some((value, index) => sourcePath[index] !== value)) { + continue; + } + return { + leadingDetached: location.leadingDetachedComments, + leading: location.leadingComments, + trailing: location.trailingComments, + sourcePath, + }; + } + return { + leadingDetached: [], + sourcePath, + }; +} + +/** + * The following field numbers are used to find comments in + * google.protobuf.SourceCodeInfo. + */ +enum FieldNumber { + FileDescriptorProto_Package = 2, + FileDescriptorProto_MessageType = 4, + FileDescriptorProto_EnumType = 5, + FileDescriptorProto_Service = 6, + FileDescriptorProto_Extension = 7, + FileDescriptorProto_Syntax = 12, + DescriptorProto_Field = 2, + DescriptorProto_NestedType = 3, + DescriptorProto_EnumType = 4, + DescriptorProto_Extension = 6, + DescriptorProto_OneofDecl = 8, + EnumDescriptorProto_Value = 2, + ServiceDescriptorProto_Method = 2, +} + +/** + * Return a string that matches the definition of a field in the protobuf + * source. Does not take custom options into account. + */ +function declarationString(this: DescField | DescExtension): string { + const parts: string[] = []; + if (this.repeated) { + parts.push("repeated"); + } + if (this.optional) { + parts.push("optional"); + } + const file = "extendee" in this ? this.file : this.parent.file; + if ( + file.syntax == "proto2" && + this.proto.label === FieldDescriptorProto_Label.REQUIRED + ) { + parts.push("required"); + } + let type: string; + switch (this.kind) { + case "scalar_field": + type = ScalarType[this.scalar].toLowerCase(); + break; + case "enum_field": + type = this.enum.typeName; + break; + case "message_field": + type = this.message.typeName; + break; + case "map_field": { + const k = ScalarType[this.mapKey].toLowerCase(); + let v: string; + switch (this.mapValue.kind) { + case "scalar": + v = ScalarType[this.mapValue.scalar].toLowerCase(); + break; + case "enum": + v = this.mapValue.enum.typeName; + break; + case "message": + v = this.mapValue.message.typeName; + break; + } + type = `map<${k}, ${v}>`; + break; + } + } + parts.push(`${type} ${this.name} = ${this.number}`); + const options: string[] = []; + if (this.proto.options?.packed !== undefined) { + options.push(`packed = ${this.proto.options.packed.toString()}`); + } + let defaultValue = this.proto.defaultValue; + if (defaultValue !== undefined) { + if ( + this.proto.type == FieldDescriptorProto_Type.BYTES || + this.proto.type == FieldDescriptorProto_Type.STRING + ) { + defaultValue = '"' + defaultValue.replace('"', '\\"') + '"'; + } + options.push(`default = ${defaultValue}`); + } + if (this.jsonName !== undefined) { + options.push(`json_name = "${this.jsonName}"`); + } + if (this.proto.options?.deprecated === true) { + options.push(`deprecated = true`); + } + if (options.length > 0) { + parts.push("[" + options.join(", ") + "]"); + } + return parts.join(" "); +} + +/** + * Parses a text-encoded default value (proto2) of a scalar or enum field. + */ +function getDefaultValue( + this: DescField | DescExtension +): number | boolean | string | bigint | Uint8Array | undefined { + const d = this.proto.defaultValue; + if (d === undefined) { + return undefined; + } + switch (this.kind) { + case "enum_field": { + const enumValue = this.enum.values.find((v) => v.name === d); + assert(enumValue, `cannot parse ${this.toString()} default value: ${d}`); + return enumValue.number; + } + case "scalar_field": + switch (this.scalar) { + case ScalarType.STRING: + return d; + case ScalarType.BYTES: { + const u = unescapeBytesDefaultValue(d); + if (u === false) { + throw new Error( + `cannot parse ${this.toString()} default value: ${d}` + ); + } + return u; + } + case ScalarType.INT64: + case ScalarType.SFIXED64: + case ScalarType.SINT64: + return protoInt64.parse(d); + case ScalarType.UINT64: + case ScalarType.FIXED64: + return protoInt64.uParse(d); + case ScalarType.DOUBLE: + case ScalarType.FLOAT: + switch (d) { + case "inf": + return Number.POSITIVE_INFINITY; + case "-inf": + return Number.NEGATIVE_INFINITY; + case "nan": + return Number.NaN; + default: + return parseFloat(d); + } + case ScalarType.BOOL: + return d === "true"; + case ScalarType.INT32: + case ScalarType.UINT32: + case ScalarType.SINT32: + case ScalarType.FIXED32: + case ScalarType.SFIXED32: + return parseInt(d, 10); + } + break; + default: + return undefined; + } +} + +/** + * Parses a text-encoded default value (proto2) of a BYTES field. + */ +function unescapeBytesDefaultValue(str: string): Uint8Array | false { + const b: number[] = []; + const input = { + tail: str, + c: "", + next(): boolean { + if (this.tail.length == 0) { + return false; + } + this.c = this.tail[0]; + this.tail = this.tail.substring(1); + return true; + }, + take(n: number): string | false { + if (this.tail.length >= n) { + const r = this.tail.substring(0, n); + this.tail = this.tail.substring(n); + return r; + } + return false; + }, + }; + while (input.next()) { + switch (input.c) { + case "\\": + if (input.next()) { + switch (input.c as string) { + case "\\": + b.push(input.c.charCodeAt(0)); + break; + case "b": + b.push(0x08); + break; + case "f": + b.push(0x0c); + break; + case "n": + b.push(0x0a); + break; + case "r": + b.push(0x0d); + break; + case "t": + b.push(0x09); + break; + case "v": + b.push(0x0b); + break; + case "0": + case "1": + case "2": + case "3": + case "4": + case "5": + case "6": + case "7": { + const s = input.c; + const t = input.take(2); + if (t === false) { + return false; + } + const n = parseInt(s + t, 8); + if (isNaN(n)) { + return false; + } + b.push(n); + break; + } + case "x": { + const s = input.c; + const t = input.take(2); + if (t === false) { + return false; + } + const n = parseInt(s + t, 16); + if (isNaN(n)) { + return false; + } + b.push(n); + break; + } + case "u": { + const s = input.c; + const t = input.take(4); + if (t === false) { + return false; + } + const n = parseInt(s + t, 16); + if (isNaN(n)) { + return false; + } + const chunk = new Uint8Array(4); + const view = new DataView(chunk.buffer); + view.setInt32(0, n, true); + b.push(chunk[0], chunk[1], chunk[2], chunk[3]); + break; + } + case "U": { + const s = input.c; + const t = input.take(8); + if (t === false) { + return false; + } + const tc = protoInt64.uEnc(s + t); + const chunk = new Uint8Array(8); + const view = new DataView(chunk.buffer); + view.setInt32(0, tc.lo, true); + view.setInt32(4, tc.hi, true); + b.push( + chunk[0], + chunk[1], + chunk[2], + chunk[3], + chunk[4], + chunk[5], + chunk[6], + chunk[7] + ); + break; + } + } + } + break; + default: + b.push(input.c.charCodeAt(0)); + } + } + return new Uint8Array(b); +} diff --git a/packages/protobuf/src/create-registry-from-desc.ts b/packages/protobuf/src/create-registry-from-desc.ts new file mode 100644 index 000000000..e48934f11 --- /dev/null +++ b/packages/protobuf/src/create-registry-from-desc.ts @@ -0,0 +1,523 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { assert } from "./private/assert.js"; +import type { MessageType } from "./message-type.js"; +import { proto3 } from "./proto3.js"; +import { proto2 } from "./proto2.js"; +import type { PartialFieldInfo } from "./field.js"; +import type { EnumType, EnumValueInfo } from "./enum.js"; +import type { + IEnumTypeRegistry, + IMessageTypeRegistry, + IServiceTypeRegistry, +} from "./type-registry.js"; +import type { MethodInfo, ServiceType } from "./service-type.js"; +import { localName } from "./private/names.js"; +import { Timestamp } from "./google/protobuf/timestamp_pb.js"; +import { Duration } from "./google/protobuf/duration_pb.js"; +import { Any } from "./google/protobuf/any_pb.js"; +import { Empty } from "./google/protobuf/empty_pb.js"; +import { FieldMask } from "./google/protobuf/field_mask_pb.js"; +import { + ListValue, + NullValue, + Struct, + Value, +} from "./google/protobuf/struct_pb.js"; +import { getEnumType } from "./private/enum.js"; +import { + BoolValue, + BytesValue, + DoubleValue, + FloatValue, + Int32Value, + Int64Value, + StringValue, + UInt32Value, + UInt64Value, +} from "./google/protobuf/wrappers_pb.js"; +import { FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; +import type { DescField, DescriptorSet } from "./descriptor-set.js"; +import { createDescriptorSet } from "./create-descriptor-set.js"; + +// well-known message types with specialized JSON representation +const wkMessages = [ + Any, + Duration, + Empty, + FieldMask, + Struct, + Value, + ListValue, + Timestamp, + Duration, + DoubleValue, + FloatValue, + Int64Value, + Int32Value, + UInt32Value, + UInt64Value, + BoolValue, + StringValue, + BytesValue, +]; + +// well-known enum types with specialized JSON representation +const wkEnums = [getEnumType(NullValue)]; + +/** + * Create a registry from a set of descriptors. The types returned by this + * registry behave exactly like types from generated code. + * + * This function accepts google.protobuf.FileDescriptorSet in serialized or + * deserialized form. Alternatively, it also accepts a DescriptorSet (see + * createDescriptorSet()). + * + * By default, all well-known types with a specialized JSON representation + * are replaced with their generated counterpart in this package. + */ +export function createRegistryFromDescriptors( + input: DescriptorSet | FileDescriptorSet | Uint8Array, + replaceWkt = true +): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry { + const set: DescriptorSet = + input instanceof Uint8Array || input instanceof FileDescriptorSet + ? createDescriptorSet(input) + : input; + const enums: Record = {}; + const messages: Record = {}; + const services: Record = {}; + if (replaceWkt) { + for (const mt of wkMessages) { + messages[mt.typeName] = mt; + } + for (const et of wkEnums) { + enums[et.typeName] = et; + } + } + return { + /** + * May raise an error on invalid descriptors. + */ + findEnum(typeName: string): EnumType | undefined { + const existing = enums[typeName]; + if (existing) { + return existing; + } + const desc = set.enums.get(typeName); + if (!desc) { + return undefined; + } + const runtime = desc.file.syntax == "proto3" ? proto3 : proto2; + const type = runtime.makeEnumType( + typeName, + desc.values.map( + (u): EnumValueInfo => ({ + no: u.number, + name: u.name, + localName: localName(u), + }) + ), + {} + ); + enums[typeName] = type; + return type; + }, + + /** + * May raise an error on invalid descriptors. + */ + findMessage(typeName: string): MessageType | undefined { + const existing = messages[typeName]; + if (existing) { + return existing; + } + const desc = set.messages.get(typeName); + if (!desc) { + return undefined; + } + const runtime = desc.file.syntax == "proto3" ? proto3 : proto2; + const fields: PartialFieldInfo[] = []; + const type = runtime.makeMessageType(typeName, () => fields, { + localName: localName(desc), + }); + messages[typeName] = type; + for (const field of desc.fields) { + const fieldInfo = makeFieldInfo(field, this); + fields.push(fieldInfo); + } + return type; + }, + + /** + * May raise an error on invalid descriptors. + */ + findService(typeName: string): ServiceType | undefined { + const existing = services[typeName]; + if (existing) { + return existing; + } + const desc = set.services.get(typeName); + if (!desc) { + return undefined; + } + const methods: Record = {}; + for (const method of desc.methods) { + const I = this.findMessage(method.input.typeName); + const O = this.findMessage(method.input.typeName); + assert( + I, + `message "${ + method.input.typeName + }" for ${method.toString()} not found` + ); + assert( + O, + `output message "${ + method.output.typeName + }" for ${method.toString()} not found` + ); + const m = { + name: method.name, + localName: localName(method), + I, + O, + kind: method.methodKind, + idempotency: method.idempotency, + options: {}, + }; + methods[m.localName] = m; + } + return (services[typeName] = { + typeName: desc.typeName, + methods, + }); + }, + }; +} + +/** + * DescriptorRegistry is a type registry that dynamically creates types + * from a set of google.protobuf.FileDescriptorProto. + * + * By default, all well-known types with a specialized JSON representation + * are replaced with their generated counterpart in this package. + */ +export class DescriptorRegistry + implements IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry +{ + private readonly desc: DescriptorSet; + + private readonly enums: Record = {}; + private readonly messages: Record = {}; + private readonly services: Record = {}; + + constructor(descriptorSet: DescriptorSet, replaceWkt = true) { + this.desc = descriptorSet; + if (replaceWkt) { + for (const mt of wkMessages) { + this.messages[mt.typeName] = mt; + } + for (const et of wkEnums) { + this.enums[et.typeName] = et; + } + } + } + + /** + * Conveniently create a DescriptorRegistry from a FileDescriptorSet, + * or a FileDescriptorSet in binary format. + */ + static fromFileDescriptorSet( + input: FileDescriptorSet | Uint8Array + ): DescriptorRegistry { + return new DescriptorRegistry(createDescriptorSet(input)); + } + + /** + * May raise an error on invalid descriptors. + */ + findEnum(typeName: string): EnumType | undefined { + const existing = this.enums[typeName]; + if (existing) { + return existing; + } + const desc = this.desc.enums.get(typeName); + if (!desc) { + return undefined; + } + const runtime = desc.file.syntax == "proto3" ? proto3 : proto2; + const type = runtime.makeEnumType( + typeName, + desc.values.map( + (u): EnumValueInfo => ({ + no: u.number, + name: u.name, + localName: localName(u), + }) + ), + {} + ); + this.enums[typeName] = type; + return type; + } + + /** + * May raise an error on invalid descriptors. + */ + findMessage(typeName: string): MessageType | undefined { + const existing = this.messages[typeName]; + if (existing) { + return existing; + } + const desc = this.desc.messages.get(typeName); + if (!desc) { + return undefined; + } + const runtime = desc.file.syntax == "proto3" ? proto3 : proto2; + const fields: PartialFieldInfo[] = []; + const type = runtime.makeMessageType(typeName, () => fields, { + localName: localName(desc), + }); + this.messages[typeName] = type; + for (const field of desc.fields) { + const fieldInfo = makeFieldInfo(field, this); + fields.push(fieldInfo); + } + return type; + } + + /** + * May raise an error on invalid descriptors. + */ + findService(typeName: string): ServiceType | undefined { + const existing = this.services[typeName]; + if (existing) { + return existing; + } + const desc = this.desc.services.get(typeName); + if (!desc) { + return undefined; + } + const methods: Record = {}; + for (const method of desc.methods) { + const I = this.findMessage(method.input.typeName); + const O = this.findMessage(method.input.typeName); + assert( + I, + `message "${method.input.typeName}" for ${method.toString()} not found` + ); + assert( + O, + `output message "${ + method.output.typeName + }" for ${method.toString()} not found` + ); + const m = { + name: method.name, + localName: localName(method), + I, + O, + kind: method.methodKind, + idempotency: method.idempotency, + options: {}, + }; + methods[m.localName] = m; + } + return (this.services[typeName] = { + typeName: desc.typeName, + methods, + }); + } +} + +interface Resolver extends IMessageTypeRegistry, IEnumTypeRegistry {} + +function makeFieldInfo(desc: DescField, resolver: Resolver): PartialFieldInfo { + switch (desc.kind) { + case "map_field": + return makeMapFieldInfo(desc, resolver); + case "message_field": + return makeMessageFieldInfo(desc, resolver); + case "enum_field": { + const fi = makeEnumFieldInfo(desc, resolver); + fi.default = desc.getDefaultValue(); + return fi; + } + case "scalar_field": { + const fi = makeScalarFieldInfo(desc); + fi.default = desc.getDefaultValue(); + return fi; + } + } +} + +function makeMapFieldInfo( + field: DescField & { kind: "map_field" }, + resolver: Resolver +): PartialFieldInfo { + const base = { + kind: "map", + name: field.name, + no: field.number, + K: field.mapKey, + } as const; + if (field.mapValue.message) { + const messageType = resolver.findMessage(field.mapValue.message.typeName); + assert( + messageType, + `message "${ + field.mapValue.message.typeName + }" for ${field.toString()} not found` + ); + return { + ...base, + V: { + kind: "message", + T: messageType, + }, + }; + } + if (field.mapValue.enum) { + const enumType = resolver.findEnum(field.mapValue.enum.typeName); + assert( + enumType, + `enum "${field.mapValue.enum.typeName}" for ${field.toString()} not found` + ); + return { + ...base, + V: { + kind: "enum", + T: enumType, + }, + }; + } + return { + ...base, + V: { + kind: "scalar", + T: field.mapValue.scalar, + }, + }; +} + +function makeScalarFieldInfo( + field: DescField & { kind: "scalar_field" } +): PartialFieldInfo { + const base = { + no: field.number, + name: field.name, + kind: "scalar", + T: field.scalar, + } as const; + if (field.repeated) { + return { + ...base, + repeated: true, + packed: field.packed, + oneof: undefined, + T: field.scalar, + }; + } + if (field.oneof) { + return { + ...base, + oneof: field.oneof.name, + }; + } + if (field.optional) { + return { + ...base, + opt: true, + }; + } + return base; +} + +function makeMessageFieldInfo( + field: DescField & { kind: "message_field" }, + resolver: Resolver +): PartialFieldInfo { + const messageType = resolver.findMessage(field.message.typeName); + assert( + messageType, + `message "${field.message.typeName}" for ${field.toString()} not found` + ); + const base = { + no: field.number, + name: field.name, + kind: "message", + T: messageType, + } as const; + if (field.repeated) { + return { + ...base, + repeated: true, + packed: field.packed, + oneof: undefined, + }; + } + if (field.oneof) { + return { + ...base, + oneof: field.oneof.name, + }; + } + if (field.optional) { + return { + ...base, + opt: true, + }; + } + return base; +} + +function makeEnumFieldInfo( + field: DescField & { kind: "enum_field" }, + resolver: Resolver +): PartialFieldInfo { + const enumType = resolver.findEnum(field.enum.typeName); + assert( + enumType, + `enum "${field.enum.typeName}" for ${field.toString()} not found` + ); + const base = { + no: field.number, + name: field.name, + kind: "enum", + T: enumType, + } as const; + if (field.repeated) { + return { + ...base, + repeated: true, + packed: field.packed, + oneof: undefined, + }; + } + if (field.oneof) { + return { + ...base, + oneof: field.oneof.name, + }; + } + if (field.optional) { + return { + ...base, + opt: true, + }; + } + return base; +} diff --git a/packages/protobuf/src/create-registry.ts b/packages/protobuf/src/create-registry.ts new file mode 100644 index 000000000..12276dca1 --- /dev/null +++ b/packages/protobuf/src/create-registry.ts @@ -0,0 +1,79 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { MessageType } from "./message-type.js"; +import type { EnumType } from "./enum.js"; +import type { ServiceType } from "./service-type.js"; +import type { + IMessageTypeRegistry, + IEnumTypeRegistry, + IServiceTypeRegistry, +} from "./type-registry.js"; + +/** + * Create a new registry from the given types. Note that + */ +export function createRegistry( + ...types: Array +): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry { + const messages: Record = {}; + const enums: Record = {}; + const services: Record = {}; + const registry = { + /** + * Add a type to the registry. For messages, the types used in message + * fields are added recursively. For services, the message types used + * for requests and responses are added recursively. + */ + add(type: MessageType | EnumType | ServiceType): void { + if ("fields" in type) { + if (!this.findMessage(type.typeName)) { + messages[type.typeName] = type; + for (const field of type.fields.list()) { + if (field.kind == "message") { + this.add(field.T); + } else if (field.kind == "map" && field.V.kind == "message") { + this.add(field.V.T); + } else if (field.kind == "enum") { + this.add(field.T); + } + } + } + } else if ("methods" in type) { + if (!this.findService(type.typeName)) { + services[type.typeName] = type; + for (const method of Object.values(type.methods)) { + this.add(method.I); + this.add(method.O); + } + } + } else { + enums[type.typeName] = type; + } + }, + findMessage(typeName: string): MessageType | undefined { + return messages[typeName]; + }, + findEnum(typeName: string): EnumType | undefined { + return enums[typeName]; + }, + findService(typeName: string): ServiceType | undefined { + return services[typeName]; + }, + }; + for (const type of types) { + registry.add(type); + } + return registry; +} diff --git a/packages/protobuf/src/descriptor-set.ts b/packages/protobuf/src/descriptor-set.ts index 96487196f..24627b2ff 100644 --- a/packages/protobuf/src/descriptor-set.ts +++ b/packages/protobuf/src/descriptor-set.ts @@ -17,713 +17,641 @@ import type { EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto, - OneofDescriptorProto, -} from "./google/protobuf/descriptor_pb.js"; -import { - FieldDescriptorProto_Label, - FieldDescriptorProto_Type, FileDescriptorProto, MethodDescriptorProto, - MethodOptions_IdempotencyLevel, + OneofDescriptorProto, ServiceDescriptorProto, } from "./google/protobuf/descriptor_pb.js"; -import { assert } from "./private/assert.js"; -import { ScalarType } from "./field.js"; -import { MethodIdempotency, MethodKind } from "./service-type.js"; +import type { ScalarType } from "./field.js"; +import type { MethodIdempotency, MethodKind } from "./service-type.js"; /** - * DescriptorSet wraps a set of google.protobuf.FileDescriptorProto, - * asserting basic expectations and providing hierarchical information. + * DescriptorSet provides a convenient interface for working with a set + * of google.protobuf.FileDescriptorProto. * - * Note that all types are kept by their fully qualified type name - * with a leading dot. + * When protobuf sources are compiled, each file is parsed into a + * google.protobuf.FileDescriptorProto. Those messages describe all parts + * of the source file that are required to generate code for them. */ -export class DescriptorSet implements UnresolvedSet { - readonly enums: Record = {}; - readonly messages: Record = {}; - readonly services: Record = {}; - +export interface DescriptorSet { /** - * May raise an error on invalid descriptors. + * All files, in the order they were added to the set. */ - add(...files: FileDescriptorProto[]): void { - for (const file of files) { - newFile(file, this); - } - } - - listEnums(): UnresolvedEnum[] { - return Object.values(this.enums).filter(isDefined); - } - - listMessages(): UnresolvedMessage[] { - return Object.values(this.messages).filter(isDefined); - } - - listServices(): UnresolvedService[] { - return Object.values(this.services).filter(isDefined); - } -} - -function isDefined(v: T | undefined): v is T { - return v !== undefined; -} - -interface UnresolvedSet { - readonly enums: Record; - readonly messages: Record; - readonly services: Record; + readonly files: DescFile[]; + /** + * All enumerations, indexed by their fully qualified type name. + * (We omit the leading dot.) + */ + readonly enums: ReadonlyMap; + /** + * All messages, indexed by their fully qualified type name. + * (We omit the leading dot.) + */ + readonly messages: ReadonlyMap; + /** + * All services, indexed by their fully qualified type name. + * (We omit the leading dot.) + */ + readonly services: ReadonlyMap; + /** + * All extensions, indexed by their fully qualified type name. + */ + readonly extensions: ReadonlyMap; } -const fieldTypeToScalarType: Record< - FieldDescriptorProto_Type, - ScalarType | undefined -> = { - [FieldDescriptorProto_Type.DOUBLE]: ScalarType.DOUBLE, - [FieldDescriptorProto_Type.FLOAT]: ScalarType.FLOAT, - [FieldDescriptorProto_Type.INT64]: ScalarType.INT64, - [FieldDescriptorProto_Type.UINT64]: ScalarType.UINT64, - [FieldDescriptorProto_Type.INT32]: ScalarType.INT32, - [FieldDescriptorProto_Type.FIXED64]: ScalarType.FIXED64, - [FieldDescriptorProto_Type.FIXED32]: ScalarType.FIXED32, - [FieldDescriptorProto_Type.BOOL]: ScalarType.BOOL, - [FieldDescriptorProto_Type.STRING]: ScalarType.STRING, - [FieldDescriptorProto_Type.GROUP]: undefined, - [FieldDescriptorProto_Type.MESSAGE]: undefined, - [FieldDescriptorProto_Type.BYTES]: ScalarType.BYTES, - [FieldDescriptorProto_Type.UINT32]: ScalarType.UINT32, - [FieldDescriptorProto_Type.ENUM]: undefined, - [FieldDescriptorProto_Type.SFIXED32]: ScalarType.SFIXED32, - [FieldDescriptorProto_Type.SFIXED64]: ScalarType.SFIXED64, - [FieldDescriptorProto_Type.SINT32]: ScalarType.SINT32, - [FieldDescriptorProto_Type.SINT64]: ScalarType.SINT64, -}; - -interface File { - readonly proto: FileDescriptorProto; +/** + * Describes a protobuf source file. + */ +export interface DescFile { + kind: "file"; + /** + * The syntax specified in the protobuf source. + */ readonly syntax: "proto3" | "proto2"; - readonly name: string; // name of the file, excluding the .proto suffix + /** + * The name of the file, excluding the .proto suffix. + * For a protobuf file `foo/bar.proto`, this is `foo/bar`. + */ + readonly name: string; + /** + * Top-level enumerations declared in this file. + * Note that more enumerations might be declared within message declarations. + */ + readonly enums: DescEnum[]; + /** + * Top-level messages declared in this file. + * Note that more messages might be declared within message declarations. + */ + readonly messages: DescMessage[]; + /** + * Top-level extensions declared in this file. + * Note that more extensions might be declared within message declarations. + */ + readonly extensions: DescExtension[]; + /** + * Services declared in this file. + */ + readonly services: DescService[]; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: FileDescriptorProto; + /** + * Get comments on the syntax element in the protobuf source. + */ + getSyntaxComments(): DescComments; + /** + * Get comments on the package element in the protobuf source. + */ + getPackageComments(): DescComments; toString(): string; } -function newFile(proto: FileDescriptorProto, ds: UnresolvedSet): File { - assert(proto.name, `missing file descriptor name`); - if (proto.syntax !== undefined && proto.syntax !== "proto3") { - throw new Error(`invalid descriptor: unsupported syntax: ${proto.syntax}`); - } - const file: File = { - proto, - syntax: proto.syntax === "proto3" ? "proto3" : "proto2", - name: proto.name.endsWith(".proto") - ? proto.name.substring(-".proto".length) - : proto.name, - toString(): string { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above - return `file ${this.proto.name}`; - }, - }; - for (const messageType of proto.messageType) { - newMessage(messageType, undefined, file, ds); - } - for (const enumType of proto.enumType) { - newEnum(enumType, undefined, file, ds); - } - for (const extension of proto.extension) { - newExtension(extension, undefined, file, ds); - } - for (const service of proto.service) { - newService(service, file, ds); - } - return file; -} - -interface UnresolvedEnum { - readonly proto: EnumDescriptorProto; - readonly file: File; - readonly parent: UnresolvedMessage | undefined; +/** + * Describes an enumeration in a protobuf source file. + */ +export interface DescEnum { + kind: "enum"; + /** + * The fully qualified name of the enumeration. (We omit the leading dot.) + */ + readonly typeName: string; + /** + * The name of the enumeration, as declared in the protobuf source. + */ readonly name: string; - readonly typeName: string; // fully qualified type name - readonly protoTypeName: string; // fully qualified name with a leading dot - readonly values: UnresolvedEnumValue[]; - + /** + * The file this enumeration was declared in. + */ + readonly file: DescFile; + /** + * The parent message, if this enumeration was declared inside a message declaration. + */ + readonly parent: DescMessage | undefined; + /** + * Values declared for this enumeration. + */ + readonly values: DescEnumValue[]; + /** + * A prefix shared by all enum values. + * For example, `MY_ENUM_` for `enum MyEnum {MY_ENUM_A=0; MY_ENUM_B=1;}` + */ + readonly sharedPrefix?: string; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: EnumDescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; toString(): string; } -function newEnum( - proto: EnumDescriptorProto, - parent: UnresolvedMessage | undefined, - file: File, - us: UnresolvedSet -): UnresolvedEnum { - assert(proto.name, `invalid descriptor: missing enum descriptor name`); - let protoTypeName: string; - if (parent) { - protoTypeName = `${parent.protoTypeName}.${proto.name}`; - } else if (file.proto.package !== undefined) { - protoTypeName = `.${file.proto.package}.${proto.name}`; - } else { - protoTypeName = `.${proto.name}`; - } - const values: UnresolvedEnumValue[] = []; - const enumT = { - proto, - file, - parent, - name: proto.name, - protoTypeName, - typeName: protoTypeName.startsWith(".") - ? protoTypeName.substring(1) - : protoTypeName, - values, - toString(): string { - return `enum ${this.typeName}`; - }, - }; - us.enums[enumT.protoTypeName] = enumT; - for (const value of proto.value) { - values.push(newEnumValue(value, enumT)); - } - return enumT; -} - -interface UnresolvedEnumValue { - readonly proto: EnumValueDescriptorProto; - readonly parent: UnresolvedEnum; +/** + * Describes an individual value of an enumeration in a protobuf source file. + */ +export interface DescEnumValue { + kind: "enum_value"; + /** + * The name of the enumeration value, as specified in the protobuf source. + */ readonly name: string; + /** + * The enumeration this value belongs to. + */ + readonly parent: DescEnum; + /** + * The numeric enumeration value, as specified in the protobuf source. + */ readonly number: number; - + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: EnumValueDescriptorProto; + /** + * Return a string that (closely) matches the definition of the enumeration + * value in the protobuf source. + */ + declarationString(): string; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; toString(): string; } -function newEnumValue( - proto: EnumValueDescriptorProto, - parent: UnresolvedEnum -): UnresolvedEnumValue { - assert(proto.name, `invalid descriptor: missing enum value descriptor name`); - assert( - proto.number !== undefined, - `invalid descriptor: missing enum value descriptor number` - ); - return { - proto, - name: proto.name, - number: proto.number, - parent, - toString(): string { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above - return `enum value ${this.parent.typeName}.${this.proto.name}`; - }, - }; -} - -interface UnresolvedMessage { - readonly proto: DescriptorProto; - readonly file: File; - readonly parent: UnresolvedMessage | undefined; +/** + * Describes a message declaration in a protobuf source file. + */ +export interface DescMessage { + kind: "message"; + /** + * The fully qualified name of the message. (We omit the leading dot.) + */ + readonly typeName: string; + /** + * The name of the message, as specified in the protobuf source. + */ readonly name: string; - readonly typeName: string; // fully qualified type name - readonly protoTypeName: string; // fully qualified name with a leading dot - readonly fields: UnresolvedField[]; - readonly oneofs: UnresolvedOneof[]; // excluding synthetic oneofs for proto3 optional - readonly nestedEnums: UnresolvedEnum[]; - readonly nestedMessages: UnresolvedMessage[]; // excluding synthetic messages like map entries - readonly nestedExtensions: UnresolvedExtension[]; - + /** + * The file this message was declared in. + */ + readonly file: DescFile; + /** + * The parent message, if this message was declared inside a message declaration. + */ + readonly parent: DescMessage | undefined; + /** + * Fields declared for this message, including fields declared in a oneof + * group. + */ + readonly fields: DescField[]; + /** + * Oneof groups declared for this message. + * This does not include synthetic oneofs for proto3 optionals. + */ + readonly oneofs: DescOneof[]; + /** + * Fields and oneof groups for this message, ordered by their appearance in the + * protobuf source. + */ + readonly members: (DescField | DescOneof)[]; + /** + * Enumerations declared within the message, if any. + */ + readonly nestedEnums: DescEnum[]; + /** + * Messages declared within the message, if any. + * This does not include synthetic messages like map entries. + */ + readonly nestedMessages: DescMessage[]; + /** + * Extensions declared within the message, if any. + */ + readonly nestedExtensions: DescExtension[]; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: DescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; toString(): string; } -function newMessage( - proto: DescriptorProto, - parent: UnresolvedMessage | undefined, - file: File, - us: UnresolvedSet -): UnresolvedMessage { - assert(proto.name, `invalid descriptor: missing name`); - const nestedMessages: UnresolvedMessage[] = []; - const fields: UnresolvedField[] = []; - const oneofs: UnresolvedOneof[] = []; - const nestedEnums: UnresolvedEnum[] = []; - const nestedExtensions: UnresolvedExtension[] = []; - let protoTypeName: string; - if (parent) { - protoTypeName = `${parent.protoTypeName}.${proto.name}`; - } else if (file.proto.package !== undefined) { - protoTypeName = `.${file.proto.package}.${proto.name}`; - } else { - protoTypeName = `.${proto.name}`; - } - const message = { - proto, - file, - parent, - name: proto.name, - typeName: protoTypeName.startsWith(".") - ? protoTypeName.substring(1) - : protoTypeName, - protoTypeName, - fields, - oneofs, - nestedEnums, - nestedMessages, - nestedExtensions, - toString(): string { - return `message ${this.typeName}`; - }, +/** + * Describes a field declaration in a protobuf source file. + */ +export type DescField = DescFieldCommon & + (DescFieldScalar | DescFieldMessage | DescFieldEnum | DescFieldMap) & { + /** + * The message this field is declared on. + */ + readonly parent: DescMessage; }; - us.messages[message.protoTypeName] = message; - for (const nestedType of proto.nestedType) { - nestedMessages.push(newMessage(nestedType, message, file, us)); - } - for (const oneofDecl of proto.oneofDecl) { - oneofs.push(newOneof(oneofDecl, message, file)); - } - for (const field of proto.field) { - let oneof: UnresolvedOneof | undefined = undefined; - if (field.oneofIndex !== undefined) { - oneof = oneofs[field.oneofIndex]; - assert( - oneof, - `invalid descriptor: oneof declaration index ${ - field.oneofIndex - } specified by field #${field.number ?? -1} not found` - ); - } - fields.push(newField(field, message, oneof)); - } - for (const enumType of proto.enumType) { - nestedEnums.push(newEnum(enumType, message, file, us)); - } - for (const extension of proto.extension) { - nestedExtensions.push(newExtension(extension, message, file, us)); - } - return message; -} -interface UnresolvedField { - readonly proto: FieldDescriptorProto; - readonly number: number; +/** + * Describes an extension in a protobuf source file. + */ +export type DescExtension = DescFieldCommon & + (DescFieldScalar | DescFieldMessage | DescFieldEnum | DescFieldMap) & { + /** + * The fully qualified name of the extension. + */ + readonly typeName: string; + /** + * The file this extension was declared in. + */ + readonly file: DescFile; + /** + * The parent message, if this extension was declared inside a message declaration. + */ + readonly parent: DescMessage | undefined; + /** + * The message that this extension extends. + */ + readonly extendee: DescMessage; + }; + +interface DescFieldCommon { + /** + * The field name, as specified in the protobuf source + */ readonly name: string; - readonly type: FieldDescriptorProto_Type; - readonly parent: UnresolvedMessage; - readonly oneof: UnresolvedOneof | undefined; - readonly optional: boolean; // whether the field is optional, regardless of syntax - readonly packed: boolean; // pack this repeated field? true in case of `[packed = true]` and if packed by default because of proto3 semantics + /** + * The field number, as specified in the protobuf source. + */ + readonly number: number; + /** + * The `oneof` group this field belongs to, if any. + */ + readonly oneof: DescOneof | undefined; + /** + * Whether this field was declared with `optional` in the protobuf source. + */ + readonly optional: boolean; + /** + * Pack this repeated field? + */ + readonly packed: boolean; + /** + * Is this field packed by default? Only valid for enum fields, and for + * scalar fields except BYTES and STRING. + * In proto3 syntax, fields are packed by default. In proto2 syntax, fields + * are unpacked by default. + */ + readonly packedByDefault: boolean; + /** + * A user-defined name for the JSON format, set with the field option + * [json_name="foo"]. + */ + readonly jsonName: string | undefined; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: FieldDescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; + /** + * Return a string that (closely) matches the definition of the field in the + * protobuf source. + */ + declarationString(): string; toString(): string; +} - resolve(us: UnresolvedSet): ResolvedField; +interface DescFieldScalar { + readonly kind: "scalar_field"; + /** + * Is the field repeated? + */ + readonly repeated: boolean; + /** + * Scalar type, if it is a scalar field. + */ + readonly scalar: ScalarType; + /** + * The message type, if it is a message field. + */ + readonly message: undefined; + /** + * The enum type, if it is an enum field. + */ + readonly enum: undefined; + /** + * The map key type, if this is a map field. + */ + readonly mapKey: undefined; + /** + * The map value type, if this is a map field. + */ + readonly mapValue: undefined; + /** + * Return the default value specified in the protobuf source. + * Only valid for proto2 syntax. + */ + getDefaultValue(): + | number + | boolean + | string + | bigint + | Uint8Array + | undefined; } -function newField( - proto: FieldDescriptorProto, - parent: UnresolvedMessage, - oneof: UnresolvedOneof | undefined -): UnresolvedField { - assert(proto.name, `invalid descriptor: missing name`); - assert(proto.number, `invalid descriptor: missing number`); - assert(proto.type, `invalid descriptor: missing type`); - let optional = false; - let packed = proto.options?.packed === true; - switch (parent.file.syntax) { - case "proto2": - optional = - oneof === undefined && - proto.label === FieldDescriptorProto_Label.OPTIONAL; - break; - case "proto3": - optional = proto.proto3Optional === true; - switch (proto.type) { - case FieldDescriptorProto_Type.DOUBLE: - case FieldDescriptorProto_Type.FLOAT: - case FieldDescriptorProto_Type.INT64: - case FieldDescriptorProto_Type.UINT64: - case FieldDescriptorProto_Type.INT32: - case FieldDescriptorProto_Type.FIXED64: - case FieldDescriptorProto_Type.FIXED32: - case FieldDescriptorProto_Type.UINT32: - case FieldDescriptorProto_Type.SFIXED32: - case FieldDescriptorProto_Type.SFIXED64: - case FieldDescriptorProto_Type.SINT32: - case FieldDescriptorProto_Type.SINT64: - case FieldDescriptorProto_Type.BOOL: - case FieldDescriptorProto_Type.ENUM: - // From the proto3 language guide: - // > In proto3, repeated fields of scalar numeric types are packed by default. - // This information is incomplete - according to the conformance tests, BOOL - // and ENUM are packed by default as well. This means only STRING and BYTES - // are not packed by default, which makes sense because they are length-delimited. - packed = true; - break; - case FieldDescriptorProto_Type.STRING: - case FieldDescriptorProto_Type.GROUP: - case FieldDescriptorProto_Type.MESSAGE: - case FieldDescriptorProto_Type.BYTES: - assert( - !packed, - `invalid descriptor: ${ - FieldDescriptorProto_Type[proto.type] - } cannot be packed` - ); - break; - } - break; - } - const field: UnresolvedField = { - proto, - name: proto.name, - number: proto.number, - type: proto.type, - parent, - oneof: proto.proto3Optional === true ? undefined : oneof, - optional, - packed, - toString(): string { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above - return `field ${parent.typeName}.${proto.name}`; - }, - resolve(us: UnresolvedSet): ResolvedField { - return resolveField(this, us); - }, - }; - if (oneof) { - oneof.fields.push(field); - } - return field; +interface DescFieldMessage { + readonly kind: "message_field"; + /** + * Is the field repeated? + */ + readonly repeated: boolean; + /** + * Scalar type, if it is a scalar field. + */ + readonly scalar: undefined; + /** + * The message type, if it is a message field. + */ + readonly message: DescMessage; + /** + * The enum type, if it is an enum field. + */ + readonly enum: undefined; + /** + * The map key type, if this is a map field. + */ + readonly mapKey: undefined; + /** + * The map value type, if this is a map field. + */ + readonly mapValue: undefined; } -type ResolvedField = - | (UnresolvedField & { - repeated: boolean; - readonly scalarType: ScalarType; - readonly message: undefined; - readonly enum: undefined; - readonly map: undefined; - }) - | (UnresolvedField & { - repeated: boolean; - readonly scalarType: undefined; - readonly message: UnresolvedMessage; - readonly enum: undefined; - readonly map: undefined; - }) - | (UnresolvedField & { - repeated: boolean; - readonly scalarType: undefined; - readonly message: undefined; - readonly enum: UnresolvedEnum; - readonly map: undefined; - }) - | (UnresolvedField & { - repeated: false; - readonly scalarType: undefined; - readonly message: undefined; - readonly enum: undefined; - readonly map: Map; - }); +interface DescFieldEnum { + readonly kind: "enum_field"; + /** + * Is the field repeated? + */ + readonly repeated: boolean; + /** + * Scalar type, if it is a scalar field. + */ + readonly scalar: undefined; + /** + * The message type, if it is a message field. + */ + readonly message: undefined; + /** + * The enum type, if it is an enum field. + */ + readonly enum: DescEnum; + /** + * The map key type, if this is a map field. + */ + readonly mapKey: undefined; + /** + * The map value type, if this is a map field. + */ + readonly mapValue: undefined; + /** + * Return the default value specified in the protobuf source. + * Only valid for proto2 syntax. + */ + getDefaultValue(): + | number + | boolean + | string + | bigint + | Uint8Array + | undefined; +} -type Map = { - key: Exclude< +interface DescFieldMap { + readonly kind: "map_field"; + /** + * Is the field repeated? + */ + readonly repeated: false; + /** + * Scalar type, if it is a scalar field. + */ + readonly scalar: undefined; + /** + * The message type, if it is a message field. + */ + readonly message: undefined; + /** + * The enum type, if it is an enum field. + */ + readonly enum: undefined; + /** + * The map key type, if this is a map field. + */ + readonly mapKey: Exclude< ScalarType, ScalarType.FLOAT | ScalarType.DOUBLE | ScalarType.BYTES >; - value: - | { enum: UnresolvedEnum; message: undefined; scalar: undefined } - | { enum: undefined; message: UnresolvedMessage; scalar: undefined } - | { enum: undefined; message: undefined; scalarType: ScalarType }; -}; - -function resolveField(u: UnresolvedField, us: UnresolvedSet): ResolvedField { - const repeated = u.proto.label === FieldDescriptorProto_Label.REPEATED; - switch (u.type) { - case FieldDescriptorProto_Type.MESSAGE: - case FieldDescriptorProto_Type.GROUP: { - assert( - u.proto.typeName, - `invalid descriptor: ${u.toString()} has type ${ - FieldDescriptorProto_Type[u.type] - }, but type_name is unset` - ); - const refMessage = us.messages[u.proto.typeName]; - assert( - refMessage, - `invalid descriptor: cannot find type_name "${ - u.proto.typeName - }" specified by ${u.toString()}` - ); - if (refMessage.proto.options?.mapEntry !== undefined) { - return { - ...u, - repeated: false, - scalarType: undefined, - message: undefined, - enum: undefined, - map: resolveMap(refMessage, us), - }; - } - return { - ...u, - repeated, - scalarType: undefined, - message: refMessage, - enum: undefined, - map: undefined, - }; - } - case FieldDescriptorProto_Type.ENUM: { - assert( - u.proto.typeName, - `invalid descriptor: ${u.toString()} has type ${ - FieldDescriptorProto_Type[u.type] - }, but type_name is unset` - ); - const refEnum = us.enums[u.proto.typeName]; - assert( - refEnum, - `invalid descriptor: cannot find type_name "${ - u.proto.typeName - }" specified by ${u.toString()}` - ); - return { - ...u, - repeated, - scalarType: undefined, - message: undefined, - enum: refEnum, - map: undefined, - }; - } - default: { - const scalarType = fieldTypeToScalarType[u.type]; - assert( - scalarType, - `invalid descriptor: unable to convert google.protobuf.FieldDescriptorProto.Type ${ - FieldDescriptorProto_Type[u.type] - } to ScalarType` - ); - return { - ...u, - repeated, - scalarType, - message: undefined, - enum: undefined, - map: undefined, - }; - } - } -} - -function resolveMap(mapEntry: UnresolvedMessage, us: UnresolvedSet): Map { - assert( - mapEntry.proto.options?.mapEntry, - `invalid descriptor: expected ${mapEntry.toString()} to be a map entry` - ); - assert( - mapEntry.fields.length === 2, - `invalid descriptor: map entry ${mapEntry.toString()} has ${ - mapEntry.fields.length - } fields` - ); - const uKeyField = mapEntry.fields.find((f) => f.proto.number === 1); - assert( - uKeyField, - `invalid descriptor: map entry ${mapEntry.toString()} is missing key field` - ); - const keyField = resolveField(uKeyField, us); - assert( - keyField.scalarType !== undefined && - keyField.scalarType !== ScalarType.BYTES && - keyField.scalarType !== ScalarType.FLOAT && - keyField.scalarType !== ScalarType.DOUBLE, - `invalid descriptor: map entry ${mapEntry.toString()} has unexpected key type ${ - FieldDescriptorProto_Type[keyField.type] - }` - ); - const uValueField = mapEntry.fields.find((f) => f.proto.number === 2); - assert( - uValueField, - `invalid descriptor: map entry ${mapEntry.toString()} is missing value field` - ); - const valueField = resolveField(uValueField, us); - if (valueField.scalarType !== undefined) { - return { - key: keyField.scalarType, - value: { - scalarType: valueField.scalarType, - enum: undefined, - message: undefined, - }, - }; - } - if (valueField.enum !== undefined) { - return { - key: keyField.scalarType, - value: { scalar: undefined, enum: valueField.enum, message: undefined }, - }; - } - if (valueField.message !== undefined) { - return { - key: keyField.scalarType, - value: { - scalar: undefined, - enum: undefined, - message: valueField.message, - }, - }; - } - throw new Error( - `invalid descriptor: map entry ${mapEntry.toString()} has unexpected value type ${ - FieldDescriptorProto_Type[keyField.type] - }` - ); + /** + * The map value type, if this is a map field. + */ + readonly mapValue: + | DescFieldMapValueEnum + | DescFieldMapValueMessage + | DescFieldMapValueScalar; } -interface UnresolvedOneof { - readonly proto: OneofDescriptorProto; - readonly name: string; - readonly parent: UnresolvedMessage; - readonly file: File; - readonly fields: UnresolvedField[]; - - toString(): string; +interface DescFieldMapValueEnum { + readonly kind: "enum"; + /** + * The enum type, if this is a map field with enum values. + */ + readonly enum: DescEnum; + /** + * The message this message field uses. + */ + readonly message: undefined; + /** + * Scalar type, if this is a map field with scalar values. + */ + readonly scalar: undefined; } -function newOneof( - proto: OneofDescriptorProto, - parent: UnresolvedMessage, - file: File -): UnresolvedOneof { - assert(proto.name, `invalid descriptor: missing oneof descriptor name`); - return { - proto, - parent, - file, - fields: [], - name: proto.name, - toString(): string { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above - return `oneof ${parent.typeName}.${proto.name}`; - }, - }; +interface DescFieldMapValueMessage { + readonly kind: "message"; + /** + * The enum type, if this is a map field with enum values. + */ + readonly enum: undefined; + /** + * The message type, if this is a map field with message values. + */ + readonly message: DescMessage; + /** + * Scalar type, if this is a map field with scalar values. + */ + readonly scalar: undefined; } -interface UnresolvedExtension { - readonly proto: FieldDescriptorProto; - readonly parent: UnresolvedMessage | undefined; - readonly file: File; +interface DescFieldMapValueScalar { + readonly kind: "scalar"; + /** + * The enum type, if this is a map field with enum values. + */ + readonly enum: undefined; + /** + * The message type, if this is a map field with message values. + */ + readonly message: undefined; + /** + * Scalar type, if this is a map field with scalar values. + */ + readonly scalar: ScalarType; } -function newExtension( - proto: FieldDescriptorProto, - parent: UnresolvedMessage | undefined, - file: File, - us: UnresolvedSet // eslint-disable-line @typescript-eslint/no-unused-vars -): UnresolvedExtension { - assert(proto.name, `invalid descriptor: missing field descriptor name`); - return { - proto, - file, - parent, - }; +/** + * Describes a oneof group in a protobuf source file. + */ +export interface DescOneof { + kind: "oneof"; + /** + * The name of the oneof group, as specified in the protobuf source. + */ + readonly name: string; + /** + * The message this oneof group was declared in. + */ + readonly parent: DescMessage; + /** + * The fields declared in this oneof group. + */ + readonly fields: DescField[]; + /** + * Marked as deprecated in the protobuf source. + * Note that oneof groups cannot be marked as deprecated, this property + * only exists for consistency and will always be false. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: OneofDescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; + toString(): string; } -interface UnresolvedService { - readonly proto: ServiceDescriptorProto; - readonly file: File; - readonly methods: UnresolvedMethod[]; +/** + * Describes a service declaration in a protobuf source file. + */ +export interface DescService { + kind: "service"; + /** + * The fully qualified name of the service. (We omit the leading dot.) + */ readonly typeName: string; - readonly protoTypeName: string; + /** + * The name of the service, as specified in the protobuf source. + */ + readonly name: string; + /** + * The file this service was declared in. + */ + readonly file: DescFile; + /** + * The RPCs this service declares. + */ + readonly methods: DescMethod[]; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: ServiceDescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; toString(): string; } -function newService( - proto: ServiceDescriptorProto, - file: File, - us: UnresolvedSet -): UnresolvedService { - assert(proto.name, `invalid descriptor: missing service descriptor name`); - let protoTypeName: string; - if (file.proto.package !== undefined) { - protoTypeName = `.${file.proto.package}.${proto.name}`; - } else { - protoTypeName = `.${proto.name}`; - } - const methods: UnresolvedMethod[] = []; - const service: UnresolvedService = { - proto, - file, - typeName: protoTypeName.startsWith(".") - ? protoTypeName.substring(1) - : protoTypeName, - protoTypeName, - methods, - toString(): string { - return `service ${this.typeName}`; - }, - }; - for (const method of proto.method) { - methods.push(newMethod(method, service)); - } - us.services[service.protoTypeName] = service; - return service; -} - -interface UnresolvedMethod { - readonly proto: MethodDescriptorProto; - readonly parent: UnresolvedService; +/** + * Describes an RPC declaration in a protobuf source file. + */ +export interface DescMethod { + kind: "rpc"; + /** + * The name of the RPC, as specified in the protobuf source. + */ readonly name: string; - readonly kind: MethodKind; - readonly inputTypeName: string; - readonly outputTypeName: string; + /** + * The parent service. + */ + readonly parent: DescService; + /** + * One of the four available method types. + */ + readonly methodKind: MethodKind; + /** + * The message type for requests. + */ + readonly input: DescMessage; + /** + * The message type for responses. + */ + readonly output: DescMessage; + /** + * The idempotency level declared in the protobuf source, if any. + */ readonly idempotency?: MethodIdempotency; + /** + * Marked as deprecated in the protobuf source. + */ + readonly deprecated: boolean; + /** + * The compiler-generated descriptor. + */ + readonly proto: MethodDescriptorProto; + /** + * Get comments on the element in the protobuf source. + */ + getComments(): DescComments; toString(): string; } -function newMethod( - proto: MethodDescriptorProto, - parent: UnresolvedService -): UnresolvedMethod { - assert(proto.name, `invalid descriptor: missing method descriptor name`); - assert(proto.inputType, `invalid descriptor: missing method input type`); - assert(proto.outputType, `invalid descriptor: missing method output type`); - let kind: MethodKind; - if (proto.clientStreaming === true && proto.serverStreaming === true) { - kind = MethodKind.BiDiStreaming; - } else if (proto.clientStreaming === true) { - kind = MethodKind.ClientStreaming; - } else if (proto.serverStreaming === true) { - kind = MethodKind.ServerStreaming; - } else { - kind = MethodKind.Unary; - } - let idempotency: MethodIdempotency | undefined; - switch (proto.options?.idempotencyLevel) { - case MethodOptions_IdempotencyLevel.IDEMPOTENT: - idempotency = MethodIdempotency.Idempotent; - break; - case MethodOptions_IdempotencyLevel.NO_SIDE_EFFECTS: - idempotency = MethodIdempotency.NoSideEffects; - break; - case MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN: - case undefined: - idempotency = undefined; - break; - } - const inputTypeName = proto.inputType.startsWith(".") - ? proto.inputType.substring(1) - : proto.inputType; - const outputTypeName = proto.outputType.startsWith(".") - ? proto.outputType.substring(1) - : proto.outputType; - return { - proto, - parent, - name: proto.name, - kind, - idempotency, - inputTypeName, - outputTypeName, - toString(): string { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above - return `rpc ${this.parent.typeName}.${proto.name}`; - }, - }; +/** + * Comments on an element in a protobuf source file. + */ +export interface DescComments { + readonly leadingDetached: readonly string[]; + readonly leading?: string; + readonly trailing?: string; + readonly sourcePath: readonly number[]; } diff --git a/packages/protobuf/src/enum.ts b/packages/protobuf/src/enum.ts index f6f9a4fda..cb6dc60ff 100644 --- a/packages/protobuf/src/enum.ts +++ b/packages/protobuf/src/enum.ts @@ -13,11 +13,11 @@ // limitations under the License. /** - * Reflection information for a protobuf enum. + * Reflection information for a protobuf enumeration. */ export interface EnumType { /** - * The fully qualified name of the enum. + * The fully qualified name of the enumeration. */ readonly typeName: string; @@ -38,19 +38,24 @@ export interface EnumType { } /** - * Reflection information for a protobuf enum value. + * Reflection information for a protobuf enumeration value. */ export interface EnumValueInfo { /** - * The number of the value as specified in proto. + * The numeric enumeration value, as specified in the protobuf source. */ readonly no: number; /** - * The name of the value as specified in proto. + * The name of the enumeration value, as specified in the protobuf source. */ readonly name: string; + /** + * The name of the enumeration value in generated code. + */ + readonly localName: string; + // We do not surface options at this time // readonly options: OptionsMap; } diff --git a/packages/protobuf/src/index.ts b/packages/protobuf/src/index.ts index b9965ca19..82c74b965 100644 --- a/packages/protobuf/src/index.ts +++ b/packages/protobuf/src/index.ts @@ -16,6 +16,7 @@ export { proto3 } from "./proto3.js"; export { proto2 } from "./proto2.js"; export { protoInt64 } from "./proto-int64.js"; export { protoBase64 } from "./proto-base64.js"; +export { codegenInfo } from "./codegen-info.js"; export { Message, @@ -39,9 +40,6 @@ export type { MethodInfoBiDiStreaming, } from "./service-type.js"; export { MethodKind, MethodIdempotency } from "./service-type.js"; -export { TypeRegistry, IMessageTypeRegistry } from "./type-registry.js"; -export { DescriptorRegistry } from "./descriptor-registry.js"; -export { DescriptorSet } from "./descriptor-set.js"; export { WireType, BinaryWriter, BinaryReader } from "./binary-encoding.js"; export type { IBinaryReader, IBinaryWriter } from "./binary-encoding.js"; @@ -60,6 +58,27 @@ export { JsonWriteStringOptions, } from "./json-format.js"; +export { + DescriptorSet, + DescFile, + DescEnum, + DescEnumValue, + DescMessage, + DescOneof, + DescField, + DescService, + DescMethod, + DescExtension, + DescComments, +} from "./descriptor-set.js"; +export { createDescriptorSet } from "./create-descriptor-set.js"; +export { IMessageTypeRegistry } from "./type-registry.js"; +export { createRegistry } from "./create-registry.js"; +export { createRegistryFromDescriptors } from "./create-registry-from-desc.js"; +export { LegacyDescriptorRegistry } from "./legacy-descriptor-registry.js"; +export { LegacyDescriptorSet } from "./legacy-descriptor-set.js"; +export { TypeRegistry } from "./legacy-type-registry.js"; + // ideally, we would export these types with sub-path exports: export * from "./google/protobuf/compiler/plugin_pb.js"; export * from "./google/protobuf/api_pb.js"; diff --git a/packages/protobuf/src/descriptor-registry.ts b/packages/protobuf/src/legacy-descriptor-registry.ts similarity index 95% rename from packages/protobuf/src/descriptor-registry.ts rename to packages/protobuf/src/legacy-descriptor-registry.ts index 4bfeb9091..136bac15d 100644 --- a/packages/protobuf/src/descriptor-registry.ts +++ b/packages/protobuf/src/legacy-descriptor-registry.ts @@ -13,6 +13,7 @@ // limitations under the License. import type { FileDescriptorProto } from "./google/protobuf/descriptor_pb.js"; +import { FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; import { assert } from "./private/assert.js"; import type { MessageType } from "./message-type.js"; import { proto3 } from "./proto3.js"; @@ -20,7 +21,7 @@ import { proto2 } from "./proto2.js"; import type { PartialFieldInfo } from "./field.js"; import { ScalarType } from "./field.js"; import type { EnumType, EnumValueInfo } from "./enum.js"; -import { DescriptorSet } from "./descriptor-set.js"; +import { LegacyDescriptorSet } from "./legacy-descriptor-set.js"; import { protoInt64 } from "./proto-int64.js"; import type { IEnumTypeRegistry, @@ -28,7 +29,6 @@ import type { IServiceTypeRegistry, } from "./type-registry.js"; import type { MethodInfo, ServiceType } from "./service-type.js"; -import { makeMethodName } from "./private/names.js"; import { Timestamp } from "./google/protobuf/timestamp_pb.js"; import { Duration } from "./google/protobuf/duration_pb.js"; import { Any } from "./google/protobuf/any_pb.js"; @@ -52,7 +52,6 @@ import { UInt32Value, UInt64Value, } from "./google/protobuf/wrappers_pb.js"; -import { FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; import type { PartialMessage } from "./message.js"; // well-known message types with specialized JSON representation @@ -81,23 +80,25 @@ const wkMessages = [ const wkEnums = [getEnumType(NullValue)]; /** - * DescriptorRegistry is a type registry that dynamically creates types + * LegacyDescriptorRegistry is a type registry that dynamically creates types * from a set of google.protobuf.FileDescriptorProto. * * By default, all well-known types with a specialized JSON representation * are replaced with their generated counterpart in this package. + * + * @deprecated */ -export class DescriptorRegistry +export class LegacyDescriptorRegistry implements IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry { - private readonly ds: DescriptorSet; + private readonly ds: LegacyDescriptorSet; private readonly enums: Record = {}; private readonly messages: Record = {}; private readonly services: Record = {}; - constructor(descriptorSet?: DescriptorSet, replaceWkt = true) { - this.ds = descriptorSet ?? new DescriptorSet(); + constructor(descriptorSet?: LegacyDescriptorSet, replaceWkt = true) { + this.ds = descriptorSet ?? new LegacyDescriptorSet(); if (replaceWkt) { for (const mt of wkMessages) { this.messages["." + mt.typeName] = mt; @@ -117,12 +118,12 @@ export class DescriptorRegistry | Uint8Array | FileDescriptorSet | PartialMessage - ): DescriptorRegistry { + ): LegacyDescriptorRegistry { const set = bytesOrSet instanceof Uint8Array ? FileDescriptorSet.fromBinary(bytesOrSet) : new FileDescriptorSet(bytesOrSet); - const dr = new DescriptorRegistry(); + const dr = new LegacyDescriptorRegistry(); dr.add(...set.file); return dr; } @@ -154,6 +155,7 @@ export class DescriptorRegistry (u): EnumValueInfo => ({ no: u.number, name: u.name, + localName: u.name, }) ), {} @@ -212,7 +214,7 @@ export class DescriptorRegistry ); const m = { name: u.name, - localName: makeMethodName(u.name), + localName: localMethodName(u.name), I: it, O: ot, kind: u.kind, @@ -228,6 +230,13 @@ export class DescriptorRegistry } } +function localMethodName(protoName: string): string { + if (protoName.length == 0) { + return protoName; + } + return protoName[0].toLowerCase() + protoName.substring(1); +} + function makeTypeLocalName(type: UnresolvedEnum | UnresolvedMessage): string { const typeName = type.typeName; const packagePrefix = (type.file.proto.package ?? "") + "."; @@ -245,7 +254,7 @@ interface Resolver { type ResolvedField = ReturnType< Exclude< - DescriptorSet["messages"][string], + LegacyDescriptorSet["messages"][string], undefined >["fields"][number]["resolve"] >; diff --git a/packages/protobuf/src/legacy-descriptor-set.ts b/packages/protobuf/src/legacy-descriptor-set.ts new file mode 100644 index 000000000..ab2376a3e --- /dev/null +++ b/packages/protobuf/src/legacy-descriptor-set.ts @@ -0,0 +1,731 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { + DescriptorProto, + EnumDescriptorProto, + EnumValueDescriptorProto, + FieldDescriptorProto, + OneofDescriptorProto, +} from "./google/protobuf/descriptor_pb.js"; +import { + FieldDescriptorProto_Label, + FieldDescriptorProto_Type, + FileDescriptorProto, + MethodDescriptorProto, + MethodOptions_IdempotencyLevel, + ServiceDescriptorProto, +} from "./google/protobuf/descriptor_pb.js"; +import { assert } from "./private/assert.js"; +import { ScalarType } from "./field.js"; +import { MethodIdempotency, MethodKind } from "./service-type.js"; + +/** + * LegacyDescriptorSet wraps a set of google.protobuf.FileDescriptorProto, + * asserting basic expectations and providing hierarchical information. + * + * Note that all types are kept by their fully qualified type name + * with a leading dot. + * + * @deprecated + */ +export class LegacyDescriptorSet implements UnresolvedSet { + readonly enums: Record = {}; + readonly messages: Record = {}; + readonly services: Record = {}; + + /** + * May raise an error on invalid descriptors. + */ + add(...files: FileDescriptorProto[]): void { + for (const file of files) { + newFile(file, this); + } + } + + listEnums(): UnresolvedEnum[] { + return Object.values(this.enums).filter(isDefined); + } + + listMessages(): UnresolvedMessage[] { + return Object.values(this.messages).filter(isDefined); + } + + listServices(): UnresolvedService[] { + return Object.values(this.services).filter(isDefined); + } +} + +function isDefined(v: T | undefined): v is T { + return v !== undefined; +} + +interface UnresolvedSet { + readonly enums: Record; + readonly messages: Record; + readonly services: Record; +} + +const fieldTypeToScalarType: Record< + FieldDescriptorProto_Type, + ScalarType | undefined +> = { + [FieldDescriptorProto_Type.DOUBLE]: ScalarType.DOUBLE, + [FieldDescriptorProto_Type.FLOAT]: ScalarType.FLOAT, + [FieldDescriptorProto_Type.INT64]: ScalarType.INT64, + [FieldDescriptorProto_Type.UINT64]: ScalarType.UINT64, + [FieldDescriptorProto_Type.INT32]: ScalarType.INT32, + [FieldDescriptorProto_Type.FIXED64]: ScalarType.FIXED64, + [FieldDescriptorProto_Type.FIXED32]: ScalarType.FIXED32, + [FieldDescriptorProto_Type.BOOL]: ScalarType.BOOL, + [FieldDescriptorProto_Type.STRING]: ScalarType.STRING, + [FieldDescriptorProto_Type.GROUP]: undefined, + [FieldDescriptorProto_Type.MESSAGE]: undefined, + [FieldDescriptorProto_Type.BYTES]: ScalarType.BYTES, + [FieldDescriptorProto_Type.UINT32]: ScalarType.UINT32, + [FieldDescriptorProto_Type.ENUM]: undefined, + [FieldDescriptorProto_Type.SFIXED32]: ScalarType.SFIXED32, + [FieldDescriptorProto_Type.SFIXED64]: ScalarType.SFIXED64, + [FieldDescriptorProto_Type.SINT32]: ScalarType.SINT32, + [FieldDescriptorProto_Type.SINT64]: ScalarType.SINT64, +}; + +interface File { + readonly proto: FileDescriptorProto; + readonly syntax: "proto3" | "proto2"; + readonly name: string; // name of the file, excluding the .proto suffix + toString(): string; +} + +function newFile(proto: FileDescriptorProto, ds: UnresolvedSet): File { + assert(proto.name, `missing file descriptor name`); + if (proto.syntax !== undefined && proto.syntax !== "proto3") { + throw new Error(`invalid descriptor: unsupported syntax: ${proto.syntax}`); + } + const file: File = { + proto, + syntax: proto.syntax === "proto3" ? "proto3" : "proto2", + name: proto.name.endsWith(".proto") + ? proto.name.substring(-".proto".length) + : proto.name, + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `file ${this.proto.name}`; + }, + }; + for (const messageType of proto.messageType) { + newMessage(messageType, undefined, file, ds); + } + for (const enumType of proto.enumType) { + newEnum(enumType, undefined, file, ds); + } + for (const extension of proto.extension) { + newExtension(extension, undefined, file, ds); + } + for (const service of proto.service) { + newService(service, file, ds); + } + return file; +} + +interface UnresolvedEnum { + readonly proto: EnumDescriptorProto; + readonly file: File; + readonly parent: UnresolvedMessage | undefined; + readonly name: string; + readonly typeName: string; // fully qualified type name + readonly protoTypeName: string; // fully qualified name with a leading dot + readonly values: UnresolvedEnumValue[]; + + toString(): string; +} + +function newEnum( + proto: EnumDescriptorProto, + parent: UnresolvedMessage | undefined, + file: File, + us: UnresolvedSet +): UnresolvedEnum { + assert(proto.name, `invalid descriptor: missing enum descriptor name`); + let protoTypeName: string; + if (parent) { + protoTypeName = `${parent.protoTypeName}.${proto.name}`; + } else if (file.proto.package !== undefined) { + protoTypeName = `.${file.proto.package}.${proto.name}`; + } else { + protoTypeName = `.${proto.name}`; + } + const values: UnresolvedEnumValue[] = []; + const enumT = { + proto, + file, + parent, + name: proto.name, + protoTypeName, + typeName: protoTypeName.startsWith(".") + ? protoTypeName.substring(1) + : protoTypeName, + values, + toString(): string { + return `enum ${this.typeName}`; + }, + }; + us.enums[enumT.protoTypeName] = enumT; + for (const value of proto.value) { + values.push(newEnumValue(value, enumT)); + } + return enumT; +} + +interface UnresolvedEnumValue { + readonly proto: EnumValueDescriptorProto; + readonly parent: UnresolvedEnum; + readonly name: string; + readonly number: number; + + toString(): string; +} + +function newEnumValue( + proto: EnumValueDescriptorProto, + parent: UnresolvedEnum +): UnresolvedEnumValue { + assert(proto.name, `invalid descriptor: missing enum value descriptor name`); + assert( + proto.number !== undefined, + `invalid descriptor: missing enum value descriptor number` + ); + return { + proto, + name: proto.name, + number: proto.number, + parent, + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `enum value ${this.parent.typeName}.${this.proto.name}`; + }, + }; +} + +interface UnresolvedMessage { + readonly proto: DescriptorProto; + readonly file: File; + readonly parent: UnresolvedMessage | undefined; + readonly name: string; + readonly typeName: string; // fully qualified type name + readonly protoTypeName: string; // fully qualified name with a leading dot + readonly fields: UnresolvedField[]; + readonly oneofs: UnresolvedOneof[]; // excluding synthetic oneofs for proto3 optional + readonly nestedEnums: UnresolvedEnum[]; + readonly nestedMessages: UnresolvedMessage[]; // excluding synthetic messages like map entries + readonly nestedExtensions: UnresolvedExtension[]; + + toString(): string; +} + +function newMessage( + proto: DescriptorProto, + parent: UnresolvedMessage | undefined, + file: File, + us: UnresolvedSet +): UnresolvedMessage { + assert(proto.name, `invalid descriptor: missing name`); + const nestedMessages: UnresolvedMessage[] = []; + const fields: UnresolvedField[] = []; + const oneofs: UnresolvedOneof[] = []; + const nestedEnums: UnresolvedEnum[] = []; + const nestedExtensions: UnresolvedExtension[] = []; + let protoTypeName: string; + if (parent) { + protoTypeName = `${parent.protoTypeName}.${proto.name}`; + } else if (file.proto.package !== undefined) { + protoTypeName = `.${file.proto.package}.${proto.name}`; + } else { + protoTypeName = `.${proto.name}`; + } + const message = { + proto, + file, + parent, + name: proto.name, + typeName: protoTypeName.startsWith(".") + ? protoTypeName.substring(1) + : protoTypeName, + protoTypeName, + fields, + oneofs, + nestedEnums, + nestedMessages, + nestedExtensions, + toString(): string { + return `message ${this.typeName}`; + }, + }; + us.messages[message.protoTypeName] = message; + for (const nestedType of proto.nestedType) { + nestedMessages.push(newMessage(nestedType, message, file, us)); + } + for (const oneofDecl of proto.oneofDecl) { + oneofs.push(newOneof(oneofDecl, message, file)); + } + for (const field of proto.field) { + let oneof: UnresolvedOneof | undefined = undefined; + if (field.oneofIndex !== undefined) { + oneof = oneofs[field.oneofIndex]; + assert( + oneof, + `invalid descriptor: oneof declaration index ${ + field.oneofIndex + } specified by field #${field.number ?? -1} not found` + ); + } + fields.push(newField(field, message, oneof)); + } + for (const enumType of proto.enumType) { + nestedEnums.push(newEnum(enumType, message, file, us)); + } + for (const extension of proto.extension) { + nestedExtensions.push(newExtension(extension, message, file, us)); + } + return message; +} + +interface UnresolvedField { + readonly proto: FieldDescriptorProto; + readonly number: number; + readonly name: string; + readonly type: FieldDescriptorProto_Type; + readonly parent: UnresolvedMessage; + readonly oneof: UnresolvedOneof | undefined; + readonly optional: boolean; // whether the field is optional, regardless of syntax + readonly packed: boolean; // pack this repeated field? true in case of `[packed = true]` and if packed by default because of proto3 semantics + toString(): string; + + resolve(us: UnresolvedSet): ResolvedField; +} + +function newField( + proto: FieldDescriptorProto, + parent: UnresolvedMessage, + oneof: UnresolvedOneof | undefined +): UnresolvedField { + assert(proto.name, `invalid descriptor: missing name`); + assert(proto.number, `invalid descriptor: missing number`); + assert(proto.type, `invalid descriptor: missing type`); + let optional = false; + let packed = proto.options?.packed === true; + switch (parent.file.syntax) { + case "proto2": + optional = + oneof === undefined && + proto.label === FieldDescriptorProto_Label.OPTIONAL; + break; + case "proto3": + optional = proto.proto3Optional === true; + switch (proto.type) { + case FieldDescriptorProto_Type.DOUBLE: + case FieldDescriptorProto_Type.FLOAT: + case FieldDescriptorProto_Type.INT64: + case FieldDescriptorProto_Type.UINT64: + case FieldDescriptorProto_Type.INT32: + case FieldDescriptorProto_Type.FIXED64: + case FieldDescriptorProto_Type.FIXED32: + case FieldDescriptorProto_Type.UINT32: + case FieldDescriptorProto_Type.SFIXED32: + case FieldDescriptorProto_Type.SFIXED64: + case FieldDescriptorProto_Type.SINT32: + case FieldDescriptorProto_Type.SINT64: + case FieldDescriptorProto_Type.BOOL: + case FieldDescriptorProto_Type.ENUM: + // From the proto3 language guide: + // > In proto3, repeated fields of scalar numeric types are packed by default. + // This information is incomplete - according to the conformance tests, BOOL + // and ENUM are packed by default as well. This means only STRING and BYTES + // are not packed by default, which makes sense because they are length-delimited. + packed = true; + break; + case FieldDescriptorProto_Type.STRING: + case FieldDescriptorProto_Type.GROUP: + case FieldDescriptorProto_Type.MESSAGE: + case FieldDescriptorProto_Type.BYTES: + assert( + !packed, + `invalid descriptor: ${ + FieldDescriptorProto_Type[proto.type] + } cannot be packed` + ); + break; + } + break; + } + const field: UnresolvedField = { + proto, + name: proto.name, + number: proto.number, + type: proto.type, + parent, + oneof: proto.proto3Optional === true ? undefined : oneof, + optional, + packed, + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `field ${parent.typeName}.${proto.name}`; + }, + resolve(us: UnresolvedSet): ResolvedField { + return resolveField(this, us); + }, + }; + if (oneof) { + oneof.fields.push(field); + } + return field; +} + +type ResolvedField = + | (UnresolvedField & { + repeated: boolean; + readonly scalarType: ScalarType; + readonly message: undefined; + readonly enum: undefined; + readonly map: undefined; + }) + | (UnresolvedField & { + repeated: boolean; + readonly scalarType: undefined; + readonly message: UnresolvedMessage; + readonly enum: undefined; + readonly map: undefined; + }) + | (UnresolvedField & { + repeated: boolean; + readonly scalarType: undefined; + readonly message: undefined; + readonly enum: UnresolvedEnum; + readonly map: undefined; + }) + | (UnresolvedField & { + repeated: false; + readonly scalarType: undefined; + readonly message: undefined; + readonly enum: undefined; + readonly map: Map; + }); + +type Map = { + key: Exclude< + ScalarType, + ScalarType.FLOAT | ScalarType.DOUBLE | ScalarType.BYTES + >; + value: + | { enum: UnresolvedEnum; message: undefined; scalar: undefined } + | { enum: undefined; message: UnresolvedMessage; scalar: undefined } + | { enum: undefined; message: undefined; scalarType: ScalarType }; +}; + +function resolveField(u: UnresolvedField, us: UnresolvedSet): ResolvedField { + const repeated = u.proto.label === FieldDescriptorProto_Label.REPEATED; + switch (u.type) { + case FieldDescriptorProto_Type.MESSAGE: + case FieldDescriptorProto_Type.GROUP: { + assert( + u.proto.typeName, + `invalid descriptor: ${u.toString()} has type ${ + FieldDescriptorProto_Type[u.type] + }, but type_name is unset` + ); + const refMessage = us.messages[u.proto.typeName]; + assert( + refMessage, + `invalid descriptor: cannot find type_name "${ + u.proto.typeName + }" specified by ${u.toString()}` + ); + if (refMessage.proto.options?.mapEntry !== undefined) { + return { + ...u, + repeated: false, + scalarType: undefined, + message: undefined, + enum: undefined, + map: resolveMap(refMessage, us), + }; + } + return { + ...u, + repeated, + scalarType: undefined, + message: refMessage, + enum: undefined, + map: undefined, + }; + } + case FieldDescriptorProto_Type.ENUM: { + assert( + u.proto.typeName, + `invalid descriptor: ${u.toString()} has type ${ + FieldDescriptorProto_Type[u.type] + }, but type_name is unset` + ); + const refEnum = us.enums[u.proto.typeName]; + assert( + refEnum, + `invalid descriptor: cannot find type_name "${ + u.proto.typeName + }" specified by ${u.toString()}` + ); + return { + ...u, + repeated, + scalarType: undefined, + message: undefined, + enum: refEnum, + map: undefined, + }; + } + default: { + const scalarType = fieldTypeToScalarType[u.type]; + assert( + scalarType, + `invalid descriptor: unable to convert google.protobuf.FieldDescriptorProto.Type ${ + FieldDescriptorProto_Type[u.type] + } to ScalarType` + ); + return { + ...u, + repeated, + scalarType, + message: undefined, + enum: undefined, + map: undefined, + }; + } + } +} + +function resolveMap(mapEntry: UnresolvedMessage, us: UnresolvedSet): Map { + assert( + mapEntry.proto.options?.mapEntry, + `invalid descriptor: expected ${mapEntry.toString()} to be a map entry` + ); + assert( + mapEntry.fields.length === 2, + `invalid descriptor: map entry ${mapEntry.toString()} has ${ + mapEntry.fields.length + } fields` + ); + const uKeyField = mapEntry.fields.find((f) => f.proto.number === 1); + assert( + uKeyField, + `invalid descriptor: map entry ${mapEntry.toString()} is missing key field` + ); + const keyField = resolveField(uKeyField, us); + assert( + keyField.scalarType !== undefined && + keyField.scalarType !== ScalarType.BYTES && + keyField.scalarType !== ScalarType.FLOAT && + keyField.scalarType !== ScalarType.DOUBLE, + `invalid descriptor: map entry ${mapEntry.toString()} has unexpected key type ${ + FieldDescriptorProto_Type[keyField.type] + }` + ); + const uValueField = mapEntry.fields.find((f) => f.proto.number === 2); + assert( + uValueField, + `invalid descriptor: map entry ${mapEntry.toString()} is missing value field` + ); + const valueField = resolveField(uValueField, us); + if (valueField.scalarType !== undefined) { + return { + key: keyField.scalarType, + value: { + scalarType: valueField.scalarType, + enum: undefined, + message: undefined, + }, + }; + } + if (valueField.enum !== undefined) { + return { + key: keyField.scalarType, + value: { scalar: undefined, enum: valueField.enum, message: undefined }, + }; + } + if (valueField.message !== undefined) { + return { + key: keyField.scalarType, + value: { + scalar: undefined, + enum: undefined, + message: valueField.message, + }, + }; + } + throw new Error( + `invalid descriptor: map entry ${mapEntry.toString()} has unexpected value type ${ + FieldDescriptorProto_Type[keyField.type] + }` + ); +} + +interface UnresolvedOneof { + readonly proto: OneofDescriptorProto; + readonly name: string; + readonly parent: UnresolvedMessage; + readonly file: File; + readonly fields: UnresolvedField[]; + + toString(): string; +} + +function newOneof( + proto: OneofDescriptorProto, + parent: UnresolvedMessage, + file: File +): UnresolvedOneof { + assert(proto.name, `invalid descriptor: missing oneof descriptor name`); + return { + proto, + parent, + file, + fields: [], + name: proto.name, + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `oneof ${parent.typeName}.${proto.name}`; + }, + }; +} + +interface UnresolvedExtension { + readonly proto: FieldDescriptorProto; + readonly parent: UnresolvedMessage | undefined; + readonly file: File; +} + +function newExtension( + proto: FieldDescriptorProto, + parent: UnresolvedMessage | undefined, + file: File, + us: UnresolvedSet // eslint-disable-line @typescript-eslint/no-unused-vars +): UnresolvedExtension { + assert(proto.name, `invalid descriptor: missing field descriptor name`); + return { + proto, + file, + parent, + }; +} + +interface UnresolvedService { + readonly proto: ServiceDescriptorProto; + readonly file: File; + readonly methods: UnresolvedMethod[]; + readonly typeName: string; + readonly protoTypeName: string; + toString(): string; +} + +function newService( + proto: ServiceDescriptorProto, + file: File, + us: UnresolvedSet +): UnresolvedService { + assert(proto.name, `invalid descriptor: missing service descriptor name`); + let protoTypeName: string; + if (file.proto.package !== undefined) { + protoTypeName = `.${file.proto.package}.${proto.name}`; + } else { + protoTypeName = `.${proto.name}`; + } + const methods: UnresolvedMethod[] = []; + const service: UnresolvedService = { + proto, + file, + typeName: protoTypeName.startsWith(".") + ? protoTypeName.substring(1) + : protoTypeName, + protoTypeName, + methods, + toString(): string { + return `service ${this.typeName}`; + }, + }; + for (const method of proto.method) { + methods.push(newMethod(method, service)); + } + us.services[service.protoTypeName] = service; + return service; +} + +interface UnresolvedMethod { + readonly proto: MethodDescriptorProto; + readonly parent: UnresolvedService; + readonly name: string; + readonly kind: MethodKind; + readonly inputTypeName: string; + readonly outputTypeName: string; + readonly idempotency?: MethodIdempotency; + toString(): string; +} + +function newMethod( + proto: MethodDescriptorProto, + parent: UnresolvedService +): UnresolvedMethod { + assert(proto.name, `invalid descriptor: missing method descriptor name`); + assert(proto.inputType, `invalid descriptor: missing method input type`); + assert(proto.outputType, `invalid descriptor: missing method output type`); + let kind: MethodKind; + if (proto.clientStreaming === true && proto.serverStreaming === true) { + kind = MethodKind.BiDiStreaming; + } else if (proto.clientStreaming === true) { + kind = MethodKind.ClientStreaming; + } else if (proto.serverStreaming === true) { + kind = MethodKind.ServerStreaming; + } else { + kind = MethodKind.Unary; + } + let idempotency: MethodIdempotency | undefined; + switch (proto.options?.idempotencyLevel) { + case MethodOptions_IdempotencyLevel.IDEMPOTENT: + idempotency = MethodIdempotency.Idempotent; + break; + case MethodOptions_IdempotencyLevel.NO_SIDE_EFFECTS: + idempotency = MethodIdempotency.NoSideEffects; + break; + case MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN: + case undefined: + idempotency = undefined; + break; + } + const inputTypeName = proto.inputType.startsWith(".") + ? proto.inputType.substring(1) + : proto.inputType; + const outputTypeName = proto.outputType.startsWith(".") + ? proto.outputType.substring(1) + : proto.outputType; + return { + proto, + parent, + name: proto.name, + kind, + idempotency, + inputTypeName, + outputTypeName, + toString(): string { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- we asserted above + return `rpc ${this.parent.typeName}.${proto.name}`; + }, + }; +} diff --git a/packages/protobuf/src/legacy-type-registry.ts b/packages/protobuf/src/legacy-type-registry.ts new file mode 100644 index 000000000..bd4ba3e46 --- /dev/null +++ b/packages/protobuf/src/legacy-type-registry.ts @@ -0,0 +1,115 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { MessageType } from "./message-type.js"; +import type { EnumType } from "./enum.js"; +import type { ServiceType } from "./service-type.js"; +import type { + IEnumTypeRegistry, + IMessageTypeRegistry, + IServiceTypeRegistry, +} from "./type-registry.js"; + +/** + * @deprecated use createRegistry() instead + * + * TypeRegistry is a simple registry for all message, enum, or service types. + */ +export class TypeRegistry + implements IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry +{ + private readonly messages: Record = {}; + private readonly enums: Record = {}; + private readonly services: Record = {}; + + /** + * Find a message type by its protobuf type name. + */ + findMessage(typeName: string): MessageType | undefined { + return this.messages[typeName]; + } + + /** + * Find an enum type by its protobuf type name. + */ + findEnum(typeName: string): EnumType | undefined { + return this.enums[typeName]; + } + + /** + * Find a service type by its protobuf type name. + */ + findService(typeName: string): ServiceType | undefined { + return this.services[typeName]; + } + + /** + * Create a new TypeRegistry from the given types. + */ + static from( + ...types: Array + ): TypeRegistry { + const registry = new TypeRegistry(); + for (const type of types) { + registry.add(type); + } + return registry; + } + + /** + * @deprecated use TypeRegistry.from() + */ + static fromIterable(types: Iterable): TypeRegistry { + return TypeRegistry.from(...types); + } + + /** + * @deprecated use TypeRegistry.from() + */ + static fromTypes(...types: MessageType[]): TypeRegistry { + return TypeRegistry.from(...types); + } + + /** + * Add a type to the registry. For messages, the types used in message + * fields are added recursively. For services, the message types used + * for requests and responses are added recursively. + */ + add(type: MessageType | EnumType | ServiceType): void { + if ("fields" in type) { + if (!this.findMessage(type.typeName)) { + this.messages[type.typeName] = type; + for (const field of type.fields.list()) { + if (field.kind == "message") { + this.add(field.T); + } else if (field.kind == "map" && field.V.kind == "message") { + this.add(field.V.T); + } else if (field.kind == "enum") { + this.add(field.T); + } + } + } + } else if ("methods" in type) { + if (!this.findService(type.typeName)) { + this.services[type.typeName] = type; + for (const method of Object.values(type.methods)) { + this.add(method.I); + this.add(method.O); + } + } + } else { + this.enums[type.typeName] = type; + } + } +} diff --git a/packages/protobuf/src/private/enum.ts b/packages/protobuf/src/private/enum.ts index 5a4043622..aeb1da4ae 100644 --- a/packages/protobuf/src/private/enum.ts +++ b/packages/protobuf/src/private/enum.ts @@ -44,29 +44,35 @@ export function getEnumType(enumObject: EnumObject): EnumType { export function setEnumType( enumObject: EnumObject, typeName: string, - values: EnumValueInfo[] - // We do not surface options at this time - // opt?: { - // options?: { readonly [extensionName: string]: JsonValue }; - // }, + values: Omit[], + opt?: { + // We do not surface options at this time + // options?: { readonly [extensionName: string]: JsonValue }; + } ): void { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any - (enumObject as any)[enumTypeSymbol] = makeEnumType(typeName, values); + (enumObject as any)[enumTypeSymbol] = makeEnumType( + typeName, + values.map((v) => ({ + no: v.no, + name: v.name, + localName: enumObject[v.no], + })), + opt + ); } -// We do not surface options at this time -// export type PartialEnumValue = Omit & Partial>; - /** * Create a new EnumType with the given values. */ export function makeEnumType( typeName: string, - values: EnumValueInfo[] - // We do not surface options at this time - // opt?: { - // options?: { readonly [extensionName: string]: JsonValue }; - // }, + values: (EnumValueInfo | Omit)[], + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _opt?: { + // We do not surface options at this time + // options?: { readonly [extensionName: string]: JsonValue }; + } ): EnumType { const names = Object.create(null) as Record; const numbers = Object.create(null) as Record; @@ -74,9 +80,10 @@ export function makeEnumType( for (const value of values) { // We do not surface options at this time // const value: EnumValueInfo = {...v, options: v.options ?? emptyReadonlyObject}; - normalValues.push(value); - names[value.name] = value; - numbers[value.no] = value; + const n = normalizeEnumValue(value); + normalValues.push(n); + names[value.name] = n; + numbers[value.no] = n; } return { typeName, @@ -94,40 +101,31 @@ export function makeEnumType( /** * Create a new enum object with the given values. + * Sets reflection information. */ export function makeEnum( typeName: string, - values: EnumValueInfo[], + values: (EnumValueInfo | Omit)[], opt?: { - /** - * MY_ENUM_ for `enum MyEnum {MY_ENUM_A=0; MY_ENUM_B=1;}`, or blank string - */ - sharedPrefix?: string; // We do not surface options at this time // options?: { readonly [extensionName: string]: JsonValue }; } ): EnumObject { const enumObject: EnumObject = {}; for (const value of values) { - const name = makeEnumValueName(value, opt?.sharedPrefix); - enumObject[name] = value.no; - enumObject[value.no] = name; + const n = normalizeEnumValue(value); + enumObject[n.localName] = n.no; + enumObject[n.no] = n.localName; } - setEnumType(enumObject, typeName, values); + setEnumType(enumObject, typeName, values, opt); return enumObject; } -// Construct a local name for an enum value. -// This logic matches the Go function with the same name in private/protoplugin/names.go -function makeEnumValueName( - value: EnumValueInfo, - sharedPrefix: string | undefined -): string { - if (sharedPrefix === undefined) { - return value.name; - } - if (!value.name.startsWith(sharedPrefix)) { - return value.name; +function normalizeEnumValue( + value: EnumValueInfo | Omit +): EnumValueInfo { + if ("localName" in value) { + return value; } - return value.name.substring(sharedPrefix.length); + return { ...value, localName: value.name }; } diff --git a/packages/protobuf/src/private/field-wrapper.ts b/packages/protobuf/src/private/field-wrapper.ts index 217a8b16c..cfa073d8f 100644 --- a/packages/protobuf/src/private/field-wrapper.ts +++ b/packages/protobuf/src/private/field-wrapper.ts @@ -14,6 +14,8 @@ import type { Message } from "../message.js"; import type { MessageType } from "../message-type.js"; +import type { DescField } from "../descriptor-set.js"; +import { ScalarType } from "../field.js"; /* eslint-disable @typescript-eslint/no-explicit-any -- unknown fields are represented with any */ @@ -57,3 +59,34 @@ export function unwrapField>( ): any { return type.fieldWrapper ? type.fieldWrapper.unwrapField(value) : value; } + +/** + * If the given field uses one of the well-known wrapper types, return + * the base type it wraps. + */ +export function getUnwrappedFieldType( + field: DescField +): ScalarType | undefined { + if (field.kind !== "message_field") { + return undefined; + } + if (field.repeated) { + return undefined; + } + if (field.oneof != undefined) { + return undefined; + } + return wktWrapperToScalarType[field.message.typeName]; +} + +const wktWrapperToScalarType: Record = { + "google.protobuf.DoubleValue": ScalarType.DOUBLE, + "google.protobuf.FloatValue": ScalarType.FLOAT, + "google.protobuf.Int64Value": ScalarType.INT64, + "google.protobuf.UInt64Value": ScalarType.UINT64, + "google.protobuf.Int32Value": ScalarType.INT32, + "google.protobuf.UInt32Value": ScalarType.UINT32, + "google.protobuf.BoolValue": ScalarType.BOOL, + "google.protobuf.StringValue": ScalarType.STRING, + "google.protobuf.BytesValue": ScalarType.BYTES, +}; diff --git a/packages/protobuf/src/private/field.ts b/packages/protobuf/src/private/field.ts index 565ba12f1..fd7ef2f03 100644 --- a/packages/protobuf/src/private/field.ts +++ b/packages/protobuf/src/private/field.ts @@ -13,7 +13,7 @@ // limitations under the License. import type { FieldInfo, OneofInfo } from "../field.js"; -import { makeOneofName } from "./names.js"; +import { localOneofName } from "./names.js"; import { assert } from "./assert.js"; export class InternalOneofInfo implements OneofInfo { @@ -29,7 +29,7 @@ export class InternalOneofInfo implements OneofInfo { constructor(name: string) { this.name = name; - this.localName = makeOneofName(name); + this.localName = localOneofName(name); } addField(field: FieldInfo) { diff --git a/packages/protobuf/src/private/message-type.ts b/packages/protobuf/src/private/message-type.ts index 7a9bdc2f7..7ebfb0fef 100644 --- a/packages/protobuf/src/private/message-type.ts +++ b/packages/protobuf/src/private/message-type.ts @@ -37,10 +37,7 @@ export function makeMessageType = AnyMessage>( * It is useful in stack traces, debuggers and test frameworks, * but has no other implications. * - * This property is optional because by default, the last part - * from the given typeName is used. Since this does not take - * reserved words into account, we provide this property so that - * an escaped name can be given. + * If omitted, the last part of the typeName is used. */ localName?: string; // We do not surface options at this time diff --git a/packages/protobuf/src/private/names.ts b/packages/protobuf/src/private/names.ts index f430f578d..0193c4b0c 100644 --- a/packages/protobuf/src/private/names.ts +++ b/packages/protobuf/src/private/names.ts @@ -12,43 +12,143 @@ // See the License for the specific language governing permissions and // limitations under the License. +import type { + DescEnum, + DescEnumValue, + DescField, + DescMessage, + DescService, +} from "../descriptor-set.js"; +import type { DescMethod, DescOneof } from "../descriptor-set.js"; + /** - * Returns the JSON name for a protobuf field, exactly like protoc does. + * Returns the name of a protobuf element in generated code. + * + * Field names - including oneofs - are converted to lowerCamelCase. For + * messages, enumerations and services, the package name is stripped from + * the type name. For nested messages and enumerations, the names are joined + * with an underscore. For methods, the first character is made lowercase. */ -export function makeJsonName(protoName: string) { - return protoCamelCase(protoName); +export function localName( + desc: + | DescEnum + | DescEnumValue + | DescMessage + | DescOneof + | DescField + | DescService + | DescMethod +): string { + switch (desc.kind) { + case "enum_field": + case "message_field": + case "map_field": + case "scalar_field": + return localFieldName(desc.name, desc.oneof !== undefined); + case "oneof": + return localOneofName(desc.name); + case "enum": + case "message": + case "service": { + const pkg = desc.file.proto.package; + const offset = pkg === undefined ? 0 : pkg.length + 1; + const name = desc.typeName.substring(offset).replace(/\./g, "_"); + if (reservedIdent[name]) { + return name + "$"; + } + return name; + } + case "enum_value": { + const sharedPrefix = desc.parent.sharedPrefix; + if (sharedPrefix === undefined) { + return desc.name; + } + const name = desc.name.substring(sharedPrefix.length); + if (reservedObjectProperties[name]) { + return name + "$"; + } + return name; + } + case "rpc": { + let name = desc.name; + if (name.length == 0) { + return name; + } + name = name[0].toLowerCase() + name.substring(1); + if (reservedObjectProperties[name]) { + return name + "$"; + } + return name; + } + } } /** - * Returns the local name of a field, exactly like protoc-gen-es does. + * Returns the name of a field in generated code. */ -export function makeFieldName(protoName: string, inOneof: boolean) { - const n = protoCamelCase(protoName); +export function localFieldName(protoName: string, inOneof: boolean) { + let name = protoCamelCase(protoName); if (inOneof) { - return n; + // oneof member names are not properties, but values of the `case` property. + return name; + } + if (reservedObjectProperties[name] || reservedMessageProperties[name]) { + name = name + "$"; } - return rProp[n] ? n + escapeChar : n; + return name; } /** - * Returns the local name of a oneof group, exactly like protoc-gen-es does. + * Returns the name of a oneof group in generated code. */ -export function makeOneofName(protoName: string): string { - return makeFieldName(protoName, false); +export function localOneofName(protoName: string): string { + return localFieldName(protoName, false); } /** - * Returns the local name of a rpc, exactly like protoc-gen-es does. + * Returns the JSON name for a protobuf field, exactly like protoc does. + */ +export const fieldJsonName = protoCamelCase; + +/** + * Finds a prefix shared by enum values, for example `MY_ENUM_` for + * `enum MyEnum {MY_ENUM_A=0; MY_ENUM_B=1;}`. */ -export function makeMethodName(protoName: string): string { - if (protoName.length == 0) { - return protoName; +export function findEnumSharedPrefix( + enumName: string, + valueNames: string[] +): string | undefined { + const prefix = camelToSnakeCase(enumName) + "_"; + for (const name of valueNames) { + if (!name.toLowerCase().startsWith(prefix)) { + return undefined; + } + const shortName = name.substring(prefix.length); + if (shortName.length == 0) { + return undefined; + } + if (/^\d/.test(shortName)) { + // identifiers must not start with numbers + return undefined; + } } - return protoName[0].toLowerCase() + protoName.substring(1); + return prefix; } -// Converts snake_case to protoCamelCase according to the convention -// used by protoc to convert a field name to a JSON name. +/** + * Converts lowerCamelCase or UpperCamelCase into lower_snake_case. + * This is used to find shared prefixes in an enum. + */ +function camelToSnakeCase(camel: string): string { + return ( + camel.substring(0, 1) + camel.substring(1).replace(/[A-Z]/g, (c) => "_" + c) + ).toLowerCase(); +} + +/** + * Converts snake_case to protoCamelCase according to the convention + * used by protoc to convert a field name to a JSON name. + */ function protoCamelCase(snakeCase: string): string { let capNext = false; const b = []; @@ -83,19 +183,87 @@ function protoCamelCase(snakeCase: string): string { return b.join(""); } -// escapeChar must be appended to a reserved name. -// We choose '$' because it is invalid in proto identifiers. -const escapeChar = "$"; +// Names that cannot be used for identifiers, such as class names, +// but _can_ be used for object properties. +const reservedIdent: { [k: string]: boolean } = { + // ECMAScript 2015 keywords + break: true, + case: true, + catch: true, + class: true, + const: true, + continue: true, + debugger: true, + default: true, + delete: true, + do: true, + else: true, + export: true, + extends: true, + false: true, + finally: true, + for: true, + function: true, + if: true, + import: true, + in: true, + instanceof: true, + new: true, + null: true, + return: true, + super: true, + switch: true, + this: true, + throw: true, + true: true, + try: true, + typeof: true, + var: true, + void: true, + while: true, + with: true, + yield: true, -// Names that cannot be used for object properties. -// See buf_es/protoc-gen-es/internal/protoplugin/names.go -const rProp: { [k: string]: boolean } = { + // ECMAScript 2015 future reserved keywords + enum: true, + implements: true, + interface: true, + let: true, + package: true, + private: true, + protected: true, + public: true, + static: true, + + // Class name cannot be 'Object' when targeting ES5 with module CommonJS + Object: true, + + // TypeScript keywords that cannot be used for types (as opposed to variables) + bigint: true, + number: true, + boolean: true, + string: true, + object: true, + + // Identifiers reserved for the runtime, so we can generate legible code + globalThis: true, + Uint8Array: true, + Partial: true, +}; + +// Names that cannot be used for object properties because they are reserved +// by built-in JavaScript properties. +const reservedObjectProperties: { [k: string]: boolean } = { // names reserved by JavaScript constructor: true, toString: true, toJSON: true, valueOf: true, +}; +// Names that cannot be used for object properties because they are reserved +// by the runtime. +const reservedMessageProperties: { [k: string]: boolean } = { // names reserved by the runtime getType: true, clone: true, diff --git a/packages/protobuf/src/private/proto-runtime.ts b/packages/protobuf/src/private/proto-runtime.ts index cdf60ec19..c90386285 100644 --- a/packages/protobuf/src/private/proto-runtime.ts +++ b/packages/protobuf/src/private/proto-runtime.ts @@ -57,7 +57,7 @@ export interface ProtoRuntime { */ makeEnum( typeName: string, - values: EnumValueInfo[], + values: (EnumValueInfo | Omit)[], opt?: { // We do not surface options at this time // options?: { readonly [extensionName: string]: JsonValue }; @@ -71,7 +71,7 @@ export interface ProtoRuntime { */ makeEnumType( typeName: string, - values: EnumValueInfo[], + values: (EnumValueInfo | Omit)[], opt?: { // We do not surface options at this time // options?: { readonly [extensionName: string]: JsonValue }; diff --git a/packages/protobuf/src/private/util.ts b/packages/protobuf/src/private/util.ts index 8dd4c39a2..27d168ab0 100644 --- a/packages/protobuf/src/private/util.ts +++ b/packages/protobuf/src/private/util.ts @@ -15,7 +15,6 @@ import type { FieldListSource } from "./field-list.js"; import type { FieldList } from "../field-list.js"; import type { EnumObject } from "./enum.js"; -import type { JsonValue } from "../json-format.js"; import type { Message, PartialMessage, PlainMessage } from "../message.js"; import type { MessageType } from "../message-type.js"; import type { EnumValueInfo } from "../enum.js"; @@ -37,8 +36,11 @@ export interface Util { setEnumType( enumObject: EnumObject, typeName: string, - values: EnumValueInfo[], - opt?: { options?: { readonly [extensionName: string]: JsonValue } } + values: Omit[], + opt?: { + // We do not surface options at this time + // options?: { readonly [extensionName: string]: JsonValue }; + } ): void; /** diff --git a/packages/protobuf/src/proto2.ts b/packages/protobuf/src/proto2.ts index 28aaabc3b..baa183275 100644 --- a/packages/protobuf/src/proto2.ts +++ b/packages/protobuf/src/proto2.ts @@ -20,7 +20,7 @@ import type { FieldList } from "./field-list.js"; import type { AnyMessage, Message } from "./message.js"; import type { FieldInfo } from "./field.js"; import { InternalOneofInfo } from "./private/field.js"; -import { makeFieldName, makeJsonName } from "./private/names.js"; +import { localFieldName, fieldJsonName } from "./private/names.js"; import { makeJsonFormatProto2 } from "./private/json-format-proto2.js"; /** @@ -75,8 +75,8 @@ function normalizeFieldInfosProto2(fieldInfos: FieldListSource): FieldInfo[] { ? fieldInfos() : fieldInfos) { const f = field as any; - f.localName = makeFieldName(field.name, field.oneof !== undefined); - f.jsonName = field.jsonName ?? makeJsonName(field.name); + f.localName = localFieldName(field.name, field.oneof !== undefined); + f.jsonName = field.jsonName ?? fieldJsonName(field.name); f.repeated = field.repeated ?? false; // In contrast to proto3, repeated fields are unpacked except when explicitly specified. f.packed = field.packed ?? false; diff --git a/packages/protobuf/src/proto3.ts b/packages/protobuf/src/proto3.ts index 34ea22057..732386a87 100644 --- a/packages/protobuf/src/proto3.ts +++ b/packages/protobuf/src/proto3.ts @@ -22,7 +22,7 @@ import type { AnyMessage, Message } from "./message.js"; import { scalarDefaultValue } from "./private/scalars.js"; import { FieldInfo, ScalarType } from "./field.js"; import { InternalOneofInfo } from "./private/field.js"; -import { makeFieldName, makeJsonName } from "./private/names.js"; +import { localFieldName, fieldJsonName } from "./private/names.js"; /** * Provides functionality for messages defined with the proto3 syntax. @@ -78,8 +78,8 @@ function normalizeFieldInfosProto3(fieldInfos: FieldListSource): FieldInfo[] { ? fieldInfos() : fieldInfos) { const f = field as any; - f.localName = makeFieldName(field.name, field.oneof !== undefined); - f.jsonName = field.jsonName ?? makeJsonName(field.name); + f.localName = localFieldName(field.name, field.oneof !== undefined); + f.jsonName = field.jsonName ?? fieldJsonName(field.name); f.repeated = field.repeated ?? false; // From the proto3 language guide: // > In proto3, repeated fields of scalar numeric types are packed by default. diff --git a/packages/protobuf/src/type-registry.ts b/packages/protobuf/src/type-registry.ts index c55698ee1..d28be2412 100644 --- a/packages/protobuf/src/type-registry.ts +++ b/packages/protobuf/src/type-registry.ts @@ -45,94 +45,3 @@ export interface IServiceTypeRegistry { */ findService(typeName: string): ServiceType | undefined; } - -/** - * TypeRegistry is a simple registry for all message, enum, or service types. - */ -export class TypeRegistry - implements IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry -{ - private readonly messages: Record = {}; - private readonly enums: Record = {}; - private readonly services: Record = {}; - - /** - * Find a message type by its protobuf type name. - */ - findMessage(typeName: string): MessageType | undefined { - return this.messages[typeName]; - } - - /** - * Find an enum type by its protobuf type name. - */ - findEnum(typeName: string): EnumType | undefined { - return this.enums[typeName]; - } - - /** - * Find a service type by its protobuf type name. - */ - findService(typeName: string): ServiceType | undefined { - return this.services[typeName]; - } - - /** - * Create a new TypeRegistry from the given types. - */ - static from( - ...types: Array - ): TypeRegistry { - const registry = new TypeRegistry(); - for (const type of types) { - registry.add(type); - } - return registry; - } - - /** - * @deprecated use TypeRegistry.from() - */ - static fromIterable(types: Iterable): TypeRegistry { - return TypeRegistry.from(...types); - } - - /** - * @deprecated use TypeRegistry.from() - */ - static fromTypes(...types: MessageType[]): TypeRegistry { - return TypeRegistry.from(...types); - } - - /** - * Add a type to the registry. For messages, the types used in message - * fields are added recursively. For services, the message types used - * for requests and responses are added recursively. - */ - add(type: MessageType | EnumType | ServiceType): void { - if ("fields" in type) { - if (!this.findMessage(type.typeName)) { - this.messages[type.typeName] = type; - for (const field of type.fields.list()) { - if (field.kind == "message") { - this.add(field.T); - } else if (field.kind == "map" && field.V.kind == "message") { - this.add(field.V.T); - } else if (field.kind == "enum") { - this.add(field.T); - } - } - } - } else if ("methods" in type) { - if (!this.findService(type.typeName)) { - this.services[type.typeName] = type; - for (const method of Object.values(type.methods)) { - this.add(method.I); - this.add(method.O); - } - } - } else { - this.enums[type.typeName] = type; - } - } -} diff --git a/packages/protoc-gen-es-darwin-64/package.json b/packages/protoc-gen-es-darwin-64/package.json deleted file mode 100644 index 24fe951f7..000000000 --- a/packages/protoc-gen-es-darwin-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-darwin-64", - "version": "0.0.8", - "description": "protoc-gen-es (darwin / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "darwin" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-darwin-arm64/package.json b/packages/protoc-gen-es-darwin-arm64/package.json deleted file mode 100644 index 1a4d27e1a..000000000 --- a/packages/protoc-gen-es-darwin-arm64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-darwin-arm64", - "version": "0.0.8", - "description": "protoc-gen-es (darwin / arm64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "darwin" - ], - "cpu": [ - "arm64" - ] -} diff --git a/packages/protoc-gen-es-freebsd-64/package.json b/packages/protoc-gen-es-freebsd-64/package.json deleted file mode 100644 index ddd00b93e..000000000 --- a/packages/protoc-gen-es-freebsd-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-freebsd-64", - "version": "0.0.8", - "description": "protoc-gen-es (freebsd / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "freebsd" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-freebsd-arm64/package.json b/packages/protoc-gen-es-freebsd-arm64/package.json deleted file mode 100644 index 10bd51950..000000000 --- a/packages/protoc-gen-es-freebsd-arm64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-freebsd-arm64", - "version": "0.0.8", - "description": "protoc-gen-es (freebsd / arm64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "freebsd" - ], - "cpu": [ - "arm64" - ] -} diff --git a/packages/protoc-gen-es-linux-32/package.json b/packages/protoc-gen-es-linux-32/package.json deleted file mode 100644 index 392f2cc50..000000000 --- a/packages/protoc-gen-es-linux-32/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-linux-32", - "version": "0.0.8", - "description": "protoc-gen-es (linux / ia32)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "linux" - ], - "cpu": [ - "ia32" - ] -} diff --git a/packages/protoc-gen-es-linux-64/package.json b/packages/protoc-gen-es-linux-64/package.json deleted file mode 100644 index f52685fc0..000000000 --- a/packages/protoc-gen-es-linux-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-linux-64", - "version": "0.0.8", - "description": "protoc-gen-es (linux / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "linux" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-linux-arm/package.json b/packages/protoc-gen-es-linux-arm/package.json deleted file mode 100644 index b48bb45dc..000000000 --- a/packages/protoc-gen-es-linux-arm/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-linux-arm", - "version": "0.0.8", - "description": "protoc-gen-es (linux / arm)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "linux" - ], - "cpu": [ - "arm" - ] -} diff --git a/packages/protoc-gen-es-linux-arm64/package.json b/packages/protoc-gen-es-linux-arm64/package.json deleted file mode 100644 index 27410121e..000000000 --- a/packages/protoc-gen-es-linux-arm64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-linux-arm64", - "version": "0.0.8", - "description": "protoc-gen-es (linux / arm64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "linux" - ], - "cpu": [ - "arm64" - ] -} diff --git a/packages/protoc-gen-es-netbsd-64/package.json b/packages/protoc-gen-es-netbsd-64/package.json deleted file mode 100644 index 59e07b275..000000000 --- a/packages/protoc-gen-es-netbsd-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-netbsd-64", - "version": "0.0.8", - "description": "protoc-gen-es (netbsd / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "netbsd" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-openbsd-64/package.json b/packages/protoc-gen-es-openbsd-64/package.json deleted file mode 100644 index 757e2a75f..000000000 --- a/packages/protoc-gen-es-openbsd-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-openbsd-64", - "version": "0.0.8", - "description": "protoc-gen-es (openbsd / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "openbsd" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-windows-32/package.json b/packages/protoc-gen-es-windows-32/package.json deleted file mode 100644 index 8f3ff7559..000000000 --- a/packages/protoc-gen-es-windows-32/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-windows-32", - "version": "0.0.8", - "description": "protoc-gen-es (win32 / ia32)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "win32" - ], - "cpu": [ - "ia32" - ] -} diff --git a/packages/protoc-gen-es-windows-64/package.json b/packages/protoc-gen-es-windows-64/package.json deleted file mode 100644 index d611a6001..000000000 --- a/packages/protoc-gen-es-windows-64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-windows-64", - "version": "0.0.8", - "description": "protoc-gen-es (win32 / x64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "win32" - ], - "cpu": [ - "x64" - ] -} diff --git a/packages/protoc-gen-es-windows-arm64/package.json b/packages/protoc-gen-es-windows-arm64/package.json deleted file mode 100644 index b338aa47f..000000000 --- a/packages/protoc-gen-es-windows-arm64/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@bufbuild/protoc-gen-es-windows-arm64", - "version": "0.0.8", - "description": "protoc-gen-es (win32 / arm64)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" - }, - "preferUnplugged": true, - "peerDependencies": { - "@bufbuild/protobuf": "^0.0.8" - }, - "peerDependenciesMeta": { - "@bufbuild/protobuf": { - "optional": true - } - }, - "os": [ - "win32" - ], - "cpu": [ - "arm64" - ] -} diff --git a/packages/protoc-gen-es/README.md b/packages/protoc-gen-es/README.md index f337b2b50..a40766b87 100644 --- a/packages/protoc-gen-es/README.md +++ b/packages/protoc-gen-es/README.md @@ -1,12 +1,37 @@ # @bufbuild/protoc-gen-es -[![npm](https://img.shields.io/npm/v/@bufbuild/protoc-gen-es?style=flat-square)](https://www.npmjs.com/package/@bufbuild/protoc-gen-es) +This package provides the code generator plugin `protoc-gen-es`. The code it +generates depends on `@bufbuild/protobuf`. -A complete implementation of protocol buffers in TypeScript, -suitable for web browsers and Node.js. -Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). +## Protocol Buffers for ECMAScript + +A complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) +in TypeScript, suitable for web browsers and Node.js. + +For example, the following definition: -This is a code generator plugin for `protoc` and [`buf`](https://github.com/bufbuild/buf). +```protobuf +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; +} +``` + +Is compiled to an ECMAScript class that can be used like this: + +```typescript +let pete = new Person({ + name: "pete", + id: 123 +}); + +let bytes = pete.toBinary(); +pete = Person.fromBinary(bytes); +pete = Person.fromJsonString('{"name": "pete", "id": 123}'); +``` + +Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). ## Installation @@ -24,14 +49,6 @@ Note that npm does not add the executable to your `$PATH`. You can do so with: PATH=$PATH:$(pwd)/node_modules/.bin ``` -Note that `protoc-gen-es` is actually just a simple node script that selects the -correct precompiled binary for your platform. For example, if you are on a 32-bit -linux machine, the optional dependency `@bufbuild/protoc-gen-es-linux-32` is -automatically installed by `npm`, and our node script will run it. Note that this -means you cannot move your `node_modules` directory to a different platform and -run it. We recommend you run `npm ci` in CI or your docker images instead. - - ### With yarn ```shell @@ -42,29 +59,12 @@ Note that yarn v2 does not use a `node_modules` directory anymore. To find the p where yarn stores the executable, run `yarn bin protoc-gen-es` (it is "unplugged" automatically). -Yarn supports installing dependencies for several platforms at the same time, by -adding the configuration field [`supportedArchitectures`](https://yarnpkg.com/configuration/yarnrc#supportedArchitectures) -in your `.yarnrc.yml`. - - -### With go - -Alternatively, you can install the plugin with `go`: - -```shell -go install github.com/bufbuild/protobuf-es/cmd/protoc-gen-es@latest -``` - -If your go environment is set up correctly, the executable is now available on -your `$PATH`. - You can always confirm successful installation with: ```shell protoc-gen-es --version ``` - ## Plugin options ### `target` diff --git a/packages/protoc-gen-es/bin/protoc-gen-es b/packages/protoc-gen-es/bin/protoc-gen-es new file mode 100755 index 000000000..ac768e4dd --- /dev/null +++ b/packages/protoc-gen-es/bin/protoc-gen-es @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +const {runNodeJs} = require("@bufbuild/protoplugin"); +const {protocGenEs} = require("../dist/cjs/protoc-gen-es-plugin.js"); + +runNodeJs(protocGenEs); diff --git a/packages/protoc-gen-es/package.json b/packages/protoc-gen-es/package.json index 9d2712c81..6fb49afcb 100644 --- a/packages/protoc-gen-es/package.json +++ b/packages/protoc-gen-es/package.json @@ -1,16 +1,27 @@ { "name": "@bufbuild/protoc-gen-es", "version": "0.0.8", - "description": "protoc-gen-es", + "description": "Protocol Buffers code generator for ECMAScript", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/bufbuild/protobuf-es.git" + "url": "https://github.com/bufbuild/protobuf-es.git", + "directory": "packages/protoc-gen-es" }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" }, + "engines": { + "node": ">=14" + }, + "scripts": { + "clean": "rm -rf ./dist/cjs/*", + "build": "npx tsc --project tsconfig.json --module commonjs --outDir ./dist/cjs" + }, "preferUnplugged": true, + "dependencies": { + "@bufbuild/protoplugin": "^0.0.8" + }, "peerDependencies": { "@bufbuild/protobuf": "^0.0.8" }, @@ -18,20 +29,5 @@ "@bufbuild/protobuf": { "optional": true } - }, - "optionalDependencies": { - "@bufbuild/protoc-gen-es-darwin-64": "0.0.8", - "@bufbuild/protoc-gen-es-darwin-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-windows-32": "0.0.8", - "@bufbuild/protoc-gen-es-linux-64": "0.0.8", - "@bufbuild/protoc-gen-es-linux-32": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm": "0.0.8", - "@bufbuild/protoc-gen-es-linux-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-freebsd-arm64": "0.0.8", - "@bufbuild/protoc-gen-es-netbsd-64": "0.0.8", - "@bufbuild/protoc-gen-es-openbsd-64": "0.0.8" } } diff --git a/packages/protoc-gen-es/src/declaration.ts b/packages/protoc-gen-es/src/declaration.ts new file mode 100644 index 000000000..4b6fd42d5 --- /dev/null +++ b/packages/protoc-gen-es/src/declaration.ts @@ -0,0 +1,221 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { + DescEnum, + DescField, + DescMessage, + DescOneof, +} from "@bufbuild/protobuf"; +import type { GeneratedFile, Schema } from "@bufbuild/protoplugin/ecmascript"; +import { + getFieldTyping, + literalString, + localName, + makeJsDoc, +} from "@bufbuild/protoplugin/ecmascript"; +import { matchWkt } from "./match-wkt.js"; + +export const declaration = { + target: "dts", + extension: "_pb.d.ts", + generateEnum, + generateMessage, +} as const; + +// prettier-ignore +function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) { + f.print(makeJsDoc(enumeration)); + f.print("export declare enum ", enumeration, " {"); + for (const value of enumeration.values) { + if (enumeration.values.indexOf(value) > 0) { + f.print(); + } + f.print(makeJsDoc(value, " ")); + f.print(" ", localName(value), " = ", value.number, ","); + } + f.print("}"); + f.print(); +} + +// prettier-ignore +function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage) { + const protoN = schema.runtime[message.file.syntax]; + const { + PartialMessage, + FieldList, + Message, + PlainMessage, + BinaryReadOptions, + JsonReadOptions, + JsonValue + } = schema.runtime; + f.print(makeJsDoc(message)); + f.print("export declare class ", message, " extends ", Message, "<", message, "> {"); + for (const member of message.members) { + switch (member.kind) { + case "oneof": + generateOneof(schema, f, member); + break; + default: + generateField(schema, f, member); + break; + } + f.print(); + } + f.print(" constructor(data?: ", PartialMessage, "<", message, ">);"); + f.print(); + generateWktMethods(schema, f, message); + f.print(" static readonly runtime: typeof ", protoN, ";"); + f.print(' static readonly typeName = ', literalString(message.typeName), ';'); + f.print(" static readonly fields: ", FieldList, ";"); + // In case we start supporting options, we have to surface them here + //f.print(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};") + f.print(); + generateWktStaticMethods(schema, f, message); + f.print(" static fromBinary(bytes: Uint8Array, options?: Partial<", BinaryReadOptions, ">): ", message, ";") + f.print() + f.print(" static fromJson(jsonValue: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): ", message, ";") + f.print() + f.print(" static fromJsonString(jsonString: string, options?: Partial<", JsonReadOptions, ">): ", message, ";") + f.print() + f.print(" static equals(a: ", message, " | ", PlainMessage, "<", message, "> | undefined, b: ", message, " | ", PlainMessage, "<", message, "> | undefined): boolean;") + f.print("}") + f.print() + for (const nestedEnum of message.nestedEnums) { + generateEnum(schema, f, nestedEnum); + } + for (const nestedMessage of message.nestedMessages) { + generateMessage(schema, f, nestedMessage); + } + // We do not support extensions at this time +} + +// prettier-ignore +function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) { + f.print(makeJsDoc(oneof, " ")); + f.print(" ", localName(oneof), ": {"); + for (const field of oneof.fields) { + if (oneof.fields.indexOf(field) > 0) { + f.print(` } | {`); + } + f.print(makeJsDoc(field, " ")); + const { typing } = getFieldTyping(field, f); + f.print(` value: `, typing, `;`); + f.print(` case: "`, localName(field), `";`); + } + f.print(` } | { case: undefined; value?: undefined };`); +} + +function generateField(schema: Schema, f: GeneratedFile, field: DescField) { + f.print(makeJsDoc(field, " ")); + const e: Parameters = []; + e.push(" ", localName(field)); + const { typing, optional } = getFieldTyping(field, f); + if (optional) { + e.push("?: ", typing); + } else { + e.push(": ", typing); + } + e.push(";"); + f.print(e); +} + +// prettier-ignore +function generateWktMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + const { + Message, + MessageType, + } = schema.runtime; + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(" packFrom(message: ", Message, "): void;"); + f.print(); + f.print(" unpackTo(target: ", Message, "): boolean;"); + f.print(); + f.print(" is(type: ", MessageType, "): boolean;"); + f.print(); + f.print(" private typeNameToUrl(name: string): string;"); + f.print(); + f.print(" private typeUrlToName(url: string): string;"); + f.print(); + break; + case "google.protobuf.Timestamp": + f.print(" toDate(): Date;"); + f.print(); + break; + case "google.protobuf.Duration": + case "google.protobuf.Struct": + case "google.protobuf.Value": + case "google.protobuf.ListValue": + case "google.protobuf.FieldMask": + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": + break; + } +} + +// prettier-ignore +function generateWktStaticMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(" static pack(message: Message): ", message, ";") + f.print() + break; + case "google.protobuf.Timestamp": + f.print(" static now(): ", message, ";") + f.print() + f.print(" static fromDate(date: Date): ", message, ";") + f.print() + break; + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": { + const {typing} = getFieldTyping(ref.value, f); + f.print(" static readonly fieldWrapper: {") + f.print(" wrapField(value: ", typing, " | ", message, "): ", message, ",") + f.print(" unwrapField(value: ", message, "): ", typing, ",") + f.print(" };") + f.print() + break; + } + case "google.protobuf.Duration": + case "google.protobuf.Struct": + case "google.protobuf.Value": + case "google.protobuf.ListValue": + case "google.protobuf.FieldMask": + break; + } +} diff --git a/packages/protoc-gen-es/src/javascript.ts b/packages/protoc-gen-es/src/javascript.ts new file mode 100644 index 000000000..b58b9ef03 --- /dev/null +++ b/packages/protoc-gen-es/src/javascript.ts @@ -0,0 +1,562 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { DescEnum, DescField, DescMessage } from "@bufbuild/protobuf"; +import { proto2, proto3, ScalarType } from "@bufbuild/protobuf"; +import type { GeneratedFile, Schema } from "@bufbuild/protoplugin/ecmascript"; +import { + getFieldExplicitDefaultValue, + literalString, + localName, + makeJsDoc, +} from "@bufbuild/protoplugin/ecmascript"; +import { matchWkt } from "./match-wkt.js"; + +export const javascript = { + target: "js", + extension: "_pb.js", + generateEnum, + generateMessage, +} as const; + +// prettier-ignore +function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) { + const protoN = schema.runtime[enumeration.file.syntax]; + f.print(makeJsDoc(enumeration)); + f.print("export const ", enumeration, " = ", protoN, ".makeEnum(") + f.print(` "`, enumeration.typeName, `",`) + f.print(` [`) + if (enumeration.sharedPrefix === undefined) { + for (const value of enumeration.values) { + f.print(" {no: ", value.number, ", name: ", literalString(value.name), "},") + } + } else { + for (const value of enumeration.values) { + const localName = value.name.substring(enumeration.sharedPrefix.length); + f.print(" {no: ", value.number, ", name: ", literalString(value.name), ", localName: ", literalString(localName), "},") + } + } + f.print(` ],`) + f.print(");") + f.print() +} + +// prettier-ignore +function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage) { + const protoN = schema.runtime[message.file.syntax]; + f.print(makeJsDoc(message)); + f.print("export const ", message, " = ", protoN, ".makeMessageType(") + f.print(` `, literalString(message.typeName), `,`) + if (message.fields.length == 0) { + f.print(" [],") + } else { + f.print(" () => [") + for (const field of message.fields) { + generateFieldInfo(schema, f, field); + } + f.print(" ],") + } + const needsLocalName = localName(message) !== + (message.file.syntax == "proto3" ? proto2 : proto3) + .makeMessageType(message.typeName, []).name; + if (needsLocalName) { + // local name is not inferrable from the type name, we need to provide it + f.print(` {localName: `, literalString(localName(message)), `},`) + } + f.print(");") + f.print() + generateWktMethods(schema, f, message) + generateWktStaticMethods(schema, f, message) + for (const nestedEnum of message.nestedEnums) { + generateEnum(schema, f, nestedEnum); + } + for (const nestedMessage of message.nestedMessages) { + generateMessage(schema, f, nestedMessage); + } + // We do not support extensions at this time +} + +// prettier-ignore +export function generateFieldInfo(schema: Schema, f: GeneratedFile, field: DescField) { + const protoN = schema.runtime[field.parent.file.syntax]; + const e: Parameters = []; + e.push(" { no: ", field.number, `, name: "`, field.name, `", `); + if (field.jsonName !== undefined) { + e.push(`jsonName: "`, field.jsonName, `", `); + } + switch (field.kind) { + case "scalar_field": + e.push(`kind: "scalar", T: `, field.scalar, ` /* ScalarType.`, ScalarType[field.scalar], ` */, `); + break; + case "map_field": + e.push(`kind: "map", K: `, field.mapKey, ` /* ScalarType.`, ScalarType[field.mapKey], ` */, `); + switch (field.mapValue.kind) { + case "scalar": + e.push(`V: {kind: "scalar", T: `, field.mapValue.scalar, ` /* ScalarType.`, ScalarType[field.mapValue.scalar], ` */}, `); + break; + case "message": + e.push(`V: {kind: "message", T: `, field.mapValue.message, `}, `); + break; + case "enum": + e.push(`V: {kind: "enum", T: `, protoN, `.getEnumType(`, field.mapValue.enum, `)}, `); + break; + } + break; + case "message_field": + e.push(`kind: "message", T: `, field.message, `, `); + break; + case "enum_field": + e.push(`kind: "enum", T: `, protoN, `.getEnumType(`, field.enum, `), `); + break; + } + if (field.repeated) { + e.push(`repeated: true, `); + if (field.packed !== field.packedByDefault) { + e.push(`packed: `, field.packed, `, `); + } + } + if (field.optional) { + e.push(`opt: true, `); + } + const defaultValue = getFieldExplicitDefaultValue(field, schema.runtime.protoInt64); + if (defaultValue !== undefined) { + e.push(`default: `, defaultValue, `, `); + } + if (field.oneof) { + e.push(`oneof: "`, field.oneof.name, `", `); + } + const lastE = e[e.length - 1]; + if (typeof lastE == "string" && lastE.endsWith(", ")) { + e[e.length - 1] = lastE.substring(0, lastE.length - 2); + } + e.push(" },"); + f.print(...e); +} + +// prettier-ignore +function generateWktMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + const { + ScalarType: rtScalarType, + protoInt64, + } = schema.runtime; + const protoN = schema.runtime[message.file.syntax]; + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(` if (this.`, localName(ref.typeUrl), ` === "") {`); + f.print(" return {};"); + f.print(" }"); + f.print(" const typeName = this.typeUrlToName(this.", localName(ref.typeUrl), ");"); + f.print(" const messageType = options?.typeRegistry?.findMessage(typeName);"); + f.print(" if (!messageType) {"); + f.print(" throw new Error(`cannot encode message ", message.typeName, ' to JSON: "${this.', localName(ref.typeUrl), '}" is not in the type registry`);'); + f.print(" }"); + f.print(" const message = messageType.fromBinary(this.", localName(ref.value), ");"); + f.print(" let json = message.toJson(options);"); + f.print(` if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) {`); + f.print(" json = {value: json};"); + f.print(" }"); + f.print(` json["@type"] = this.`, localName(ref.typeUrl), `;`); + f.print(" return json;"); + f.print("};"); + f.print(); + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (json === null || Array.isArray(json) || typeof json != "object") {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: expected object but got ${json === null ? "null" : Array.isArray(json) ? "array" : typeof json}`);'); + f.print(" }"); + f.print(` const typeUrl = json["@type"];`); + f.print(` if (typeof typeUrl != "string" || typeUrl == "") {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: "@type" is empty`);'); + f.print(" }"); + f.print(" const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName);"); + f.print(" if (!messageType) {"); + f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: ${typeUrl} is not in the type registry`);"); + f.print(" }"); + f.print(" let message;"); + f.print(` if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) {`); + f.print(` message = messageType.fromJson(json["value"], options);`); + f.print(" } else {"); + f.print(" const copy = Object.assign({}, json);"); + f.print(` delete copy["@type"];`); + f.print(" message = messageType.fromJson(copy, options);"); + f.print(" }"); + f.print(" this.packFrom(message);"); + f.print(" return this;"); + f.print("};"); + f.print(); + f.print(message, ".prototype.packFrom = function packFrom(message) {") + f.print(" this.", localName(ref.value), " = message.toBinary();"); + f.print(" this.", localName(ref.typeUrl), " = this.typeNameToUrl(message.getType().typeName);"); + f.print("};"); + f.print(); + f.print(message, ".prototype.unpackTo = function unpackTo(target) {") + f.print(" if (!this.is(target.getType())) {"); + f.print(" return false;"); + f.print(" }"); + f.print(" target.fromBinary(this.", localName(ref.value), ");"); + f.print(" return true;"); + f.print("};"); + f.print(); + f.print(message, ".prototype.is = function is(type) {") + f.print(" return this.", localName(ref.typeUrl), " === this.typeNameToUrl(type.typeName);"); + f.print("};"); + f.print(); + f.print(message, ".prototype.typeNameToUrl = function typeNameToUrl(name) {") + f.print(" return `type.googleapis.com/${name}`;"); + f.print("};"); + f.print(); + f.print(message, ".prototype.typeUrlToName = function typeUrlToName(url) {") + f.print(" if (!url.length) {"); + f.print(" throw new Error(`invalid type url: ${url}`);"); + f.print(" }"); + f.print(` const slash = url.lastIndexOf("/");`); + f.print(" const name = slash > 0 ? url.substring(slash + 1) : url;"); + f.print(" if (!name.length) {"); + f.print(" throw new Error(`invalid type url: ${url}`);"); + f.print(" }"); + f.print(" return name;"); + f.print("};"); + f.print(); + break; + case "google.protobuf.Timestamp": + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (typeof json !== "string") {`); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);"); + f.print(" }"); + f.print(` const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);`); + f.print(" if (!matches) {"); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);"); + f.print(" }"); + f.print(` const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));`); + f.print(" if (Number.isNaN(ms)) {"); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);"); + f.print(" }"); + f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);"); + f.print(" }"); + f.print(" this.", localName(ref.seconds), " = ", protoInt64, ".parse(ms / 1000);"); + f.print(" this.", localName(ref.nanos), " = 0;"); + f.print(" if (matches[7]) {"); + f.print(` this.`, localName(ref.nanos), ` = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000);` ); + f.print(" }"); + f.print(" return this;"); + f.print("};"); + f.print(); + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(" const ms = Number(this.", localName(ref.seconds), ") * 1000;"); + f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`); + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);"); + f.print(" }"); + f.print(" if (this.", localName(ref.nanos), " < 0) {"); + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: nanos must not be negative`);"); + f.print(" }"); + f.print(` let z = "Z";`); + f.print(" if (this.", localName(ref.nanos), " > 0) {"); + f.print(" const nanosStr = (this.", localName(ref.nanos), " + 1000000000).toString().substring(1);"); + f.print(` if (nanosStr.substring(3) === "000000") {`); + f.print(` z = "." + nanosStr.substring(0, 3) + "Z";`); + f.print(` } else if (nanosStr.substring(6) === "000") {`); + f.print(` z = "." + nanosStr.substring(0, 6) + "Z";`); + f.print(" } else {"); + f.print(` z = "." + nanosStr + "Z";`); + f.print(" }"); + f.print(" }"); + f.print(` return new Date(ms).toISOString().replace(".000Z", z);`); + f.print("};"); + f.print(); + f.print(message, ".prototype.toDate = function toDate() {") + f.print(" return new Date(Number(this.", localName(ref.seconds), ") * 1000 + Math.ceil(this.", localName(ref.nanos), " / 1000000));"); + f.print("};"); + f.print(); + break; + case "google.protobuf.Duration": + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (typeof json !== "string") {`) + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${proto3.json.debug(json)}`);") + f.print(" }") + f.print(` const match = json.match(/^(-?[0-9]+)(?:\\.([0-9]+))?s/);`) + f.print(" if (match === null) {") + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);") + f.print(" }") + f.print(" const longSeconds = Number(match[1]);") + f.print(" if (longSeconds > 315576000000 || longSeconds < -315576000000) {") + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);") + f.print(" }") + f.print(" this.", localName(ref.seconds), " = ", protoInt64, ".parse(longSeconds);") + f.print(` if (typeof match[2] == "string") {`) + f.print(` const nanosStr = match[2] + "0".repeat(9 - match[2].length);`) + f.print(" this.", localName(ref.nanos), " = parseInt(nanosStr);") + f.print(" if (longSeconds < ", protoInt64, ".zero) {") + f.print(" this.", localName(ref.nanos), " = -this.", localName(ref.nanos), ";") + f.print(" }") + f.print(" }") + f.print(" return this;") + f.print("};"); + f.print() + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(" if (Number(this.", localName(ref.seconds), ") > 315576000000 || Number(this.", localName(ref.seconds), ") < -315576000000) {") + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: value out of range`);") + f.print(" }") + f.print(" let text = this.", localName(ref.seconds), ".toString();") + f.print(" if (this.", localName(ref.nanos), " !== 0) {") + f.print(" let nanosStr = Math.abs(this.", localName(ref.nanos), ").toString();") + f.print(` nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;`) + f.print(` if (nanosStr.substring(3) === "000000") {`) + f.print(" nanosStr = nanosStr.substring(0, 3);") + f.print(` } else if (nanosStr.substring(6) === "000") {`) + f.print(" nanosStr = nanosStr.substring(0, 6);") + f.print(` }`) + f.print(` text += "." + nanosStr;`) + f.print(" }") + f.print(` return text + "s";`) + f.print("};"); + f.print() + break; + case "google.protobuf.Struct": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(" const json = {}") + f.print(" for (const [k, v] of Object.entries(this.", localName(ref.fields), ")) {") + f.print(" json[k] = v.toJson(options);") + f.print(" }") + f.print(" return json;") + f.print("};") + f.print() + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (typeof json != "object" || json == null || Array.isArray(json)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(" }") + f.print(" for (const [k, v] of Object.entries(json)) {") + f.print(" this.", localName(ref.fields), "[k] = ", ref.fields.mapValue.message ?? "", ".fromJson(v);") + f.print(" }") + f.print(" return this;") + f.print("};"); + f.print() + break; + case "google.protobuf.Value": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(" switch (this.", localName(ref.kind), ".case) {") + f.print(` case "`, localName(ref.nullValue), `":`) + f.print(" return null;") + f.print(` case "`, localName(ref.boolValue), `":`) + f.print(` case "`, localName(ref.numberValue), `":`) + f.print(` case "`, localName(ref.stringValue), `":`) + f.print(" return this.", localName(ref.kind), ".value;") + f.print(` case "`, localName(ref.structValue), `":`) + f.print(` case "`, localName(ref.listValue), `":`) + f.print(` return this.`, localName(ref.kind), `.value.toJson({...options, emitDefaultValues: true});`) + f.print(" }") + f.print(` throw new Error("`, message.typeName, ` must have a value");`) + f.print("};"); + f.print() + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(" switch (typeof json) {") + f.print(` case "number":`) + f.print(` this.kind = { case: "`, localName(ref.numberValue), `", value: json };`) + f.print(" break;") + f.print(` case "string":`) + f.print(` this.kind = { case: "`, localName(ref.stringValue), `", value: json };`) + f.print(" break;") + f.print(` case "boolean":`) + f.print(` this.kind = { case: "`, localName(ref.boolValue), `", value: json };`) + f.print(" break;") + f.print(` case "object":`) + f.print(" if (json === null) {") + f.print(` this.kind = { case: "`, localName(ref.nullValue), `", value: `, ref.nullValue.enum, `.`, localName(ref.nullValue.enum.values[0]), ` };`) + f.print(" } else if (Array.isArray(json)) {") + f.print(` this.kind = { case: "`, localName(ref.listValue), `", value: `, ref.listValue.message, `.fromJson(json) };`) + f.print(" } else {") + f.print(` this.kind = { case: "`, localName(ref.structValue), `", value: `, ref.structValue.message, `.fromJson(json) };`) + f.print(" }") + f.print(" break;") + f.print(" default:") + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(" }") + f.print(" return this;") + f.print("};"); + f.print() + break; + case "google.protobuf.ListValue": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(` return this.`, localName(ref.values), `.map(v => v.toJson());`) + f.print(`}`) + f.print() + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (!Array.isArray(json)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(` }`) + f.print(` for (let e of json) {`) + f.print(` this.`, localName(ref.values), `.push(`, ref.values.message, `.fromJson(e));`) + f.print(` }`) + f.print(` return this;`) + f.print("};"); + f.print() + break; + case "google.protobuf.FieldMask": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(` // Converts snake_case to protoCamelCase according to the convention`) + f.print(` // used by protoc to convert a field name to a JSON name.`) + f.print(` function protoCamelCase(snakeCase) {`) + f.print(` let capNext = false;`) + f.print(` const b = [];`) + f.print(` for (let i = 0; i < snakeCase.length; i++) {`) + f.print(` let c = snakeCase.charAt(i);`) + f.print(` switch (c) {`) + f.print(` case '_':`) + f.print(` capNext = true;`) + f.print(` break;`) + f.print(` case '0':`) + f.print(` case '1':`) + f.print(` case '2':`) + f.print(` case '3':`) + f.print(` case '4':`) + f.print(` case '5':`) + f.print(` case '6':`) + f.print(` case '7':`) + f.print(` case '8':`) + f.print(` case '9':`) + f.print(` b.push(c);`) + f.print(` capNext = false;`) + f.print(` break;`) + f.print(` default:`) + f.print(` if (capNext) {`) + f.print(` capNext = false;`) + f.print(` c = c.toUpperCase();`) + f.print(` }`) + f.print(` b.push(c);`) + f.print(` break;`) + f.print(` }`) + f.print(` }`) + f.print(` return b.join('');`) + f.print(` }`) + f.print(` return this.`, localName(ref.paths), `.map(p => {`) + f.print(` if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: lowerCamelCase of path name \\"" + p + "\\" is irreversible");`) + f.print(` }`) + f.print(` return protoCamelCase(p);`) + f.print(` }).join(",");`) + f.print("};"); + f.print() + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(` if (typeof json !== "string") {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: " + proto3.json.debug(json));`) + f.print(` }`) + f.print(` if (json === "") {`) + f.print(` return this;`) + f.print(` }`) + f.print(` function camelToSnake (str) {`) + f.print(` if (str.includes("_")) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: path names must be lowerCamelCase");`) + f.print(` }`) + f.print(` const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase());`) + f.print(` return (sc[0] === "_") ? sc.substring(1) : sc;`) + f.print(` }`) + f.print(` this.`, localName(ref.paths), ` = json.split(",").map(camelToSnake);`) + f.print(` return this;`) + f.print("};"); + f.print() + break; + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": + f.print(message, ".prototype.toJson = function toJson(options) {") + f.print(" return proto3.json.writeScalar(", rtScalarType, ".", ScalarType[ref.value.scalar], ", this.value, true);") + f.print("}") + f.print() + f.print(message, ".prototype.fromJson = function fromJson(json, options) {") + f.print(" try {") + f.print(" this.value = ", protoN, ".json.readScalar(", rtScalarType, ".", ScalarType[ref.value.scalar], ", json);") + f.print(" } catch (e) {") + f.print(" let m = `cannot decode message ", message.typeName, " from JSON\"`;") + f.print(" if (e instanceof Error && e.message.length > 0) {") + f.print(" m += `: ${e.message}`") + f.print(" }") + f.print(" throw new Error(m);") + f.print(" }") + f.print(" return this;") + f.print("};"); + f.print() + break; + } +} + +// prettier-ignore +function generateWktStaticMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + const { + protoInt64, + } = schema.runtime; + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(message, ".pack = function pack(message) {") + f.print(" const any = new ", message, "();") + f.print(" any.packFrom(message);") + f.print(" return any;") + f.print("};") + f.print() + break; + case "google.protobuf.Timestamp": + f.print(message, ".now = function now() {") + f.print(" return ", message, ".fromDate(new Date())") + f.print("};") + f.print() + f.print(message, ".fromDate = function fromDate(date) {") + f.print(" const ms = date.getTime();") + f.print(" return new ", message, "({") + f.print(" ", localName(ref.seconds), ": ", protoInt64, ".parse(Math.floor(ms / 1000)),") + f.print(" ", localName(ref.nanos), ": (ms % 1000) * 1000000,") + f.print(" });") + f.print("};") + f.print() + break; + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": { + f.print(message, ".fieldWrapper = {") + f.print(" wrapField(value) {") + f.print(" return value instanceof ", message, " ? value : new ", message, "({value});") + f.print(" },") + f.print(" unwrapField(value) {") + f.print(" return value.", localName(ref.value), ";") + f.print(" }") + f.print("};") + f.print() + break; + } + case "google.protobuf.Duration": + case "google.protobuf.Struct": + case "google.protobuf.Value": + case "google.protobuf.ListValue": + case "google.protobuf.FieldMask": + break; + } +} diff --git a/packages/protoc-gen-es/src/match-wkt.ts b/packages/protoc-gen-es/src/match-wkt.ts new file mode 100644 index 000000000..95d57481f --- /dev/null +++ b/packages/protoc-gen-es/src/match-wkt.ts @@ -0,0 +1,285 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { + DescField, + DescMessage, + DescOneof, + ScalarType, +} from "@bufbuild/protobuf"; + +type DescWkt = + | { + typeName: "google.protobuf.Any"; + typeUrl: DescField; + value: DescField; + } + | { + typeName: "google.protobuf.Timestamp"; + seconds: DescField; + nanos: DescField; + } + | { + typeName: "google.protobuf.Duration"; + seconds: DescField; + nanos: DescField; + } + | { + typeName: "google.protobuf.Struct"; + fields: DescField & { kind: "map_field" }; + } + | { + typeName: "google.protobuf.Value"; + kind: DescOneof; + nullValue: DescField & { kind: "enum_field" }; + numberValue: DescField; + stringValue: DescField; + boolValue: DescField; + structValue: DescField & { kind: "message_field" }; + listValue: DescField & { kind: "message_field" }; + } + | { + typeName: "google.protobuf.ListValue"; + values: DescField & { kind: "message_field" }; + } + | { + typeName: "google.protobuf.FieldMask"; + paths: DescField; + } + | { + typeName: "google.protobuf.DoubleValue"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.FloatValue"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.Int64Value"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.UInt64Value"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.Int32Value"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.UInt32Value"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.BoolValue"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.StringValue"; + value: DescField & { kind: "scalar_field" }; + } + | { + typeName: "google.protobuf.BytesValue"; + value: DescField & { kind: "scalar_field" }; + }; + +export function matchWkt(message: DescMessage): DescWkt | undefined { + switch (message.typeName) { + case "google.protobuf.Any": { + const typeUrl = message.fields.find( + (f) => + f.number == 1 && + f.kind == "scalar_field" && + f.scalar === ScalarType.STRING + ); + const value = message.fields.find( + (f) => + f.number == 2 && + f.kind == "scalar_field" && + f.scalar === ScalarType.BYTES + ); + if (typeUrl && value) { + return { + typeName: message.typeName, + typeUrl, + value, + }; + } + break; + } + case "google.protobuf.Timestamp": { + const seconds = message.fields.find( + (f) => + f.number == 1 && + f.kind == "scalar_field" && + f.scalar === ScalarType.INT64 + ); + const nanos = message.fields.find( + (f) => + f.number == 2 && + f.kind == "scalar_field" && + f.scalar === ScalarType.INT32 + ); + if (seconds && nanos) { + return { + typeName: message.typeName, + seconds, + nanos, + }; + } + break; + } + case "google.protobuf.Duration": { + const seconds = message.fields.find( + (f) => + f.number == 1 && + f.kind == "scalar_field" && + f.scalar === ScalarType.INT64 + ); + const nanos = message.fields.find( + (f) => + f.number == 2 && + f.kind == "scalar_field" && + f.scalar === ScalarType.INT32 + ); + if (seconds && nanos) { + return { + typeName: message.typeName, + seconds, + nanos, + }; + } + break; + } + case "google.protobuf.Struct": { + const fields = message.fields.find((f) => f.number == 1 && !f.repeated); + if ( + fields?.kind !== "map_field" || + fields.mapValue.kind !== "message" || + fields.mapValue.message.typeName !== "google.protobuf.Value" + ) { + break; + } + return { typeName: message.typeName, fields }; + } + case "google.protobuf.Value": { + const kind = message.oneofs.find((o) => o.name === "kind"); + const nullValue = message.fields.find( + (f) => f.number == 1 && f.oneof === kind + ); + if ( + nullValue?.kind !== "enum_field" || + nullValue.enum.typeName !== "google.protobuf.NullValue" + ) { + return undefined; + } + const numberValue = message.fields.find( + (f) => + f.number == 2 && + f.kind == "scalar_field" && + f.scalar === ScalarType.DOUBLE && + f.oneof === kind + ); + const stringValue = message.fields.find( + (f) => + f.number == 3 && + f.kind == "scalar_field" && + f.scalar === ScalarType.STRING && + f.oneof === kind + ); + const boolValue = message.fields.find( + (f) => + f.number == 4 && + f.kind == "scalar_field" && + f.scalar === ScalarType.BOOL && + f.oneof === kind + ); + const structValue = message.fields.find( + (f) => f.number == 5 && f.oneof === kind + ); + if ( + structValue?.kind !== "message_field" || + structValue.message.typeName !== "google.protobuf.Struct" + ) { + return undefined; + } + const listValue = message.fields.find( + (f) => f.number == 6 && f.oneof === kind + ); + if ( + listValue?.kind !== "message_field" || + listValue.message.typeName !== "google.protobuf.ListValue" + ) { + return undefined; + } + if (kind && numberValue && stringValue && boolValue) { + return { + typeName: message.typeName, + kind, + nullValue, + numberValue, + stringValue, + boolValue, + structValue, + listValue, + }; + } + break; + } + case "google.protobuf.ListValue": { + const values = message.fields.find((f) => f.number == 1 && f.repeated); + if ( + values?.kind != "message_field" || + values.message.typeName !== "google.protobuf.Value" + ) { + break; + } + return { typeName: message.typeName, values }; + } + case "google.protobuf.FieldMask": { + const paths = message.fields.find( + (f) => + f.number == 1 && + f.kind == "scalar_field" && + f.scalar === ScalarType.STRING && + f.repeated + ); + if (paths) { + return { typeName: message.typeName, paths }; + } + break; + } + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": { + const value = message.fields.find( + (f) => f.number == 1 && f.name == "value" + ); + if (!value) { + break; + } + if (value.kind !== "scalar_field") { + break; + } + return { typeName: message.typeName, value }; + } + } + return undefined; +} diff --git a/packages/protoc-gen-es/src/protoc-gen-es-plugin.ts b/packages/protoc-gen-es/src/protoc-gen-es-plugin.ts new file mode 100644 index 000000000..369def1be --- /dev/null +++ b/packages/protoc-gen-es/src/protoc-gen-es-plugin.ts @@ -0,0 +1,43 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { createEcmaScriptPlugin } from "@bufbuild/protoplugin"; +import { typescript } from "./typescript.js"; +import { javascript } from "./javascript.js"; +import { declaration } from "./declaration"; + +export const protocGenEs = createEcmaScriptPlugin( + { + name: "protoc-gen-es", + version: "v0.0.8", + }, + (schema) => { + const targets = [typescript, javascript, declaration].filter((gen) => + schema.targets.includes(gen.target) + ); + for (const target of targets) { + for (const file of schema.files) { + const f = schema.generateFile(file.name + target.extension); + f.preamble(file); + for (const enumeration of file.enums) { + target.generateEnum(schema, f, enumeration); + } + for (const message of file.messages) { + target.generateMessage(schema, f, message); + } + // We do not generate anything for services, and we do not support extensions at this time + } + } + } +); diff --git a/packages/protoc-gen-es/src/typescript.ts b/packages/protoc-gen-es/src/typescript.ts new file mode 100644 index 000000000..09e0d84e9 --- /dev/null +++ b/packages/protoc-gen-es/src/typescript.ts @@ -0,0 +1,587 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { + DescEnum, + DescField, + DescMessage, + DescOneof, +} from "@bufbuild/protobuf"; +import { ScalarType } from "@bufbuild/protobuf"; +import type { GeneratedFile, Schema } from "@bufbuild/protoplugin/ecmascript"; +import { + localName, + getFieldIntrinsicDefaultValue, + getFieldTyping, + makeJsDoc, +} from "@bufbuild/protoplugin/ecmascript"; +import { matchWkt } from "./match-wkt.js"; +import { generateFieldInfo } from "./javascript.js"; +import { literalString } from "@bufbuild/protoplugin/ecmascript"; + +export const typescript = { + target: "ts", + extension: "_pb.ts", + generateEnum, + generateMessage, +} as const; + +// prettier-ignore +function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) { + const protoN = schema.runtime[enumeration.file.syntax]; + f.print(makeJsDoc(enumeration)); + f.print("export enum ", enumeration, " {"); + for (const value of enumeration.values) { + if (enumeration.values.indexOf(value) > 0) { + f.print(); + } + f.print(makeJsDoc(value, " ")); + f.print(" ", localName(value), " = ", value.number, ","); + } + f.print("}"); + f.print("// Retrieve enum metadata with: ", enumeration.file.syntax, ".getEnumType(", enumeration, ")"); + f.print(protoN, `.util.setEnumType(`, enumeration, `, "`, enumeration.typeName, `", [`); + for (const value of enumeration.values) { + f.print(" { no: ", value.number, ', name: "', value.name, '" },'); + } + f.print("]);"); + f.print(); +} + +// prettier-ignore +function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage) { + const protoN = schema.runtime[message.file.syntax]; + const { + PartialMessage, + FieldList, + Message, + PlainMessage, + BinaryReadOptions, + JsonReadOptions, + JsonValue + } = schema.runtime; + f.print(makeJsDoc(message)); + f.print("export class ", message, " extends ", Message, "<", message, "> {"); + for (const member of message.members) { + switch (member.kind) { + case "oneof": + generateOneof(schema, f, member); + break; + default: + generateField(schema, f, member); + break; + } + f.print(); + } + f.print(" constructor(data?: ", PartialMessage, "<", message, ">) {"); + f.print(" super();"); + f.print(" ", protoN, ".util.initPartial(data, this);"); + f.print(" }"); + f.print(); + generateWktMethods(schema, f, message); + f.print(" static readonly runtime = ", protoN, ";"); + f.print(' static readonly typeName = ', literalString(message.typeName), ';'); + f.print(" static readonly fields: ", FieldList, " = ", protoN, ".util.newFieldList(() => ["); + for (const field of message.fields) { + generateFieldInfo(schema, f, field); + } + f.print(" ]);") + // In case we start supporting options, we have to surface them here + //f.print(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};") + f.print(); + generateWktStaticMethods(schema, f, message); + f.print(" static fromBinary(bytes: Uint8Array, options?: Partial<", BinaryReadOptions, ">): ", message, " {") + f.print(" return new ", message, "().fromBinary(bytes, options);") + f.print(" }") + f.print() + f.print(" static fromJson(jsonValue: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): ", message, " {") + f.print(" return new ", message, "().fromJson(jsonValue, options);") + f.print(" }") + f.print() + f.print(" static fromJsonString(jsonString: string, options?: Partial<", JsonReadOptions, ">): ", message, " {") + f.print(" return new ", message, "().fromJsonString(jsonString, options);") + f.print(" }") + f.print() + f.print(" static equals(a: ", message, " | ", PlainMessage, "<", message, "> | undefined, b: ", message, " | ", PlainMessage, "<", message, "> | undefined): boolean {") + f.print(" return ", protoN, ".util.equals(", message, ", a, b);") + f.print(" }") + f.print("}") + f.print() + for (const nestedEnum of message.nestedEnums) { + generateEnum(schema, f, nestedEnum); + } + for (const nestedMessage of message.nestedMessages) { + generateMessage(schema, f, nestedMessage); + } + // We do not support extensions at this time +} + +// prettier-ignore +function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) { + f.print(makeJsDoc(oneof, " ")); + f.print(" ", localName(oneof), ": {"); + for (const field of oneof.fields) { + if (oneof.fields.indexOf(field) > 0) { + f.print(` } | {`); + } + f.print(makeJsDoc(field, " ")); + const { typing } = getFieldTyping(field, f); + f.print(` value: `, typing, `;`); + f.print(` case: "`, localName(field), `";`); + } + f.print(` } | { case: undefined; value?: undefined } = { case: undefined };`); +} + +function generateField(schema: Schema, f: GeneratedFile, field: DescField) { + f.print(makeJsDoc(field, " ")); + const e: Parameters = []; + e.push(" ", localName(field)); + const { defaultValue, typingInferrable } = + getFieldIntrinsicDefaultValue(field); + const { typing, optional } = getFieldTyping(field, f); + if (optional || defaultValue === undefined) { + e.push("?: ", typing); + } else if (!typingInferrable) { + e.push(": ", typing); + } + if (defaultValue !== undefined) { + e.push(" = ", defaultValue); + } + e.push(";"); + f.print(e); +} + +// prettier-ignore +function generateWktMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + const { + Message, + JsonValue, + JsonReadOptions, + JsonWriteOptions, + JsonObject, + MessageType, + ScalarType: rtScalarType, + protoInt64, + } = schema.runtime; + const protoN = schema.runtime[message.file.syntax]; + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {"); + f.print(` if (this.`, localName(ref.typeUrl), ` === "") {`); + f.print(" return {};"); + f.print(" }"); + f.print(" const typeName = this.typeUrlToName(this.", localName(ref.typeUrl), ");"); + f.print(" const messageType = options?.typeRegistry?.findMessage(typeName);"); + f.print(" if (!messageType) {"); + f.print(" throw new Error(`cannot encode message ", message.typeName, ' to JSON: "${this.', localName(ref.typeUrl), '}" is not in the type registry`);'); + f.print(" }"); + f.print(" const message = messageType.fromBinary(this.", localName(ref.value), ");"); + f.print(" let json = message.toJson(options);"); + f.print(` if (typeName.startsWith("google.protobuf.") || (json === null || Array.isArray(json) || typeof json !== "object")) {`); + f.print(" json = {value: json};"); + f.print(" }"); + f.print(` json["@type"] = this.`, localName(ref.typeUrl), `;`); + f.print(" return json;"); + f.print(" }"); + f.print(); + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {"); + f.print(` if (json === null || Array.isArray(json) || typeof json != "object") {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: expected object but got ${json === null ? "null" : Array.isArray(json) ? "array" : typeof json}`);'); + f.print(" }"); + f.print(` const typeUrl = json["@type"];`); + f.print(` if (typeof typeUrl != "string" || typeUrl == "") {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, ' from JSON: "@type" is empty`);'); + f.print(" }"); + f.print(" const typeName = this.typeUrlToName(typeUrl), messageType = options?.typeRegistry?.findMessage(typeName);"); + f.print(" if (!messageType) {"); + f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: ${typeUrl} is not in the type registry`);"); + f.print(" }"); + f.print(" let message;"); + f.print(` if (typeName.startsWith("google.protobuf.") && Object.prototype.hasOwnProperty.call(json, "value")) {`); + f.print(` message = messageType.fromJson(json["value"], options);`); + f.print(" } else {"); + f.print(" const copy = Object.assign({}, json);"); + f.print(` delete copy["@type"];`); + f.print(" message = messageType.fromJson(copy, options);"); + f.print(" }"); + f.print(" this.packFrom(message);"); + f.print(" return this;"); + f.print(" }"); + f.print(); + f.print(" packFrom(message: ", Message, "): void {"); + f.print(" this.", localName(ref.value), " = message.toBinary();"); + f.print(" this.", localName(ref.typeUrl), " = this.typeNameToUrl(message.getType().typeName);"); + f.print(" }"); + f.print(); + f.print(" unpackTo(target: ", Message, "): boolean {"); + f.print(" if (!this.is(target.getType())) {"); + f.print(" return false;"); + f.print(" }"); + f.print(" target.fromBinary(this.", localName(ref.value), ");"); + f.print(" return true;"); + f.print(" }"); + f.print(); + f.print(" is(type: ", MessageType, "): boolean {"); + f.print(" return this.", localName(ref.typeUrl), " === this.typeNameToUrl(type.typeName);"); + f.print(" }"); + f.print(); + f.print(" private typeNameToUrl(name: string): string {"); + f.print(" return `type.googleapis.com/${name}`;"); + f.print(" }"); + f.print(); + f.print(" private typeUrlToName(url: string): string {"); + f.print(" if (!url.length) {"); + f.print(" throw new Error(`invalid type url: ${url}`);"); + f.print(" }"); + f.print(` const slash = url.lastIndexOf("/");`); + f.print(" const name = slash > 0 ? url.substring(slash + 1) : url;"); + f.print(" if (!name.length) {"); + f.print(" throw new Error(`invalid type url: ${url}`);"); + f.print(" }"); + f.print(" return name;"); + f.print(" }"); + f.print(); + break; + case "google.protobuf.Timestamp": + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {"); + f.print(` if (typeof json !== "string") {`); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);"); + f.print(" }"); + f.print(` const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);`); + f.print(" if (!matches) {"); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);"); + f.print(" }"); + f.print(` const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));`); + f.print(" if (Number.isNaN(ms)) {"); + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: invalid RFC 3339 string`);"); + f.print(" }"); + f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`); + f.print(" throw new Error(`cannot decode message ", message.typeName, " from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);"); + f.print(" }"); + f.print(" this.", localName(ref.seconds), " = ", protoInt64, ".parse(ms / 1000);"); + f.print(" this.", localName(ref.nanos), " = 0;"); + f.print(" if (matches[7]) {"); + f.print(` this.`, localName(ref.nanos), ` = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000);` ); + f.print(" }"); + f.print(" return this;"); + f.print(" }"); + f.print(); + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): JsonValue {"); + f.print(" const ms = Number(this.", localName(ref.seconds), ") * 1000;"); + f.print(` if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {`); + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive`);"); + f.print(" }"); + f.print(" if (this.", localName(ref.nanos), " < 0) {"); + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: nanos must not be negative`);"); + f.print(" }"); + f.print(` let z = "Z";`); + f.print(" if (this.", localName(ref.nanos), " > 0) {"); + f.print(" const nanosStr = (this.", localName(ref.nanos), " + 1000000000).toString().substring(1);"); + f.print(` if (nanosStr.substring(3) === "000000") {`); + f.print(` z = "." + nanosStr.substring(0, 3) + "Z";`); + f.print(` } else if (nanosStr.substring(6) === "000") {`); + f.print(` z = "." + nanosStr.substring(0, 6) + "Z";`); + f.print(" } else {"); + f.print(` z = "." + nanosStr + "Z";`); + f.print(" }"); + f.print(" }"); + f.print(` return new Date(ms).toISOString().replace(".000Z", z);`); + f.print(" }"); + f.print(); + f.print(" toDate(): Date {"); + f.print(" return new Date(Number(this.", localName(ref.seconds), ") * 1000 + Math.ceil(this.", localName(ref.nanos), " / 1000000));"); + f.print(" }"); + f.print(); + break; + case "google.protobuf.Duration": + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {") + f.print(` if (typeof json !== "string") {`) + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${proto3.json.debug(json)}`);") + f.print(" }") + f.print(` const match = json.match(/^(-?[0-9]+)(?:\\.([0-9]+))?s/);`) + f.print(" if (match === null) {") + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);") + f.print(" }") + f.print(" const longSeconds = Number(match[1]);") + f.print(" if (longSeconds > 315576000000 || longSeconds < -315576000000) {") + f.print(" throw new Error(`cannot decode ", message.typeName, " from JSON: ${", protoN, ".json.debug(json)}`);") + f.print(" }") + f.print(" this.", localName(ref.seconds), " = ", protoInt64, ".parse(longSeconds);") + f.print(` if (typeof match[2] == "string") {`) + f.print(` const nanosStr = match[2] + "0".repeat(9 - match[2].length);`) + f.print(" this.", localName(ref.nanos), " = parseInt(nanosStr);") + f.print(" if (longSeconds < ", protoInt64, ".zero) {") + f.print(" this.", localName(ref.nanos), " = -this.", localName(ref.nanos), ";") + f.print(" }") + f.print(" }") + f.print(" return this;") + f.print(" }") + f.print() + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): JsonValue {") + f.print(" if (Number(this.", localName(ref.seconds), ") > 315576000000 || Number(this.", localName(ref.seconds), ") < -315576000000) {") + f.print(" throw new Error(`cannot encode ", message.typeName, " to JSON: value out of range`);") + f.print(" }") + f.print(" let text = this.", localName(ref.seconds), ".toString();") + f.print(" if (this.", localName(ref.nanos), " !== 0) {") + f.print(" let nanosStr = Math.abs(this.", localName(ref.nanos), ").toString();") + f.print(` nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;`) + f.print(` if (nanosStr.substring(3) === "000000") {`) + f.print(" nanosStr = nanosStr.substring(0, 3);") + f.print(` } else if (nanosStr.substring(6) === "000") {`) + f.print(" nanosStr = nanosStr.substring(0, 6);") + f.print(` }`) + f.print(` text += "." + nanosStr;`) + f.print(" }") + f.print(` return text + "s";`) + f.print(" }") + f.print() + break; + case "google.protobuf.Struct": + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {") + f.print(" const json: ", JsonObject, " = {}") + f.print(" for (const [k, v] of Object.entries(this.", localName(ref.fields), ")) {") + f.print(" json[k] = v.toJson(options);") + f.print(" }") + f.print(" return json;") + f.print(" }") + f.print() + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {") + f.print(` if (typeof json != "object" || json == null || Array.isArray(json)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(" }") + f.print(" for (const [k, v] of Object.entries(json)) {") + f.print(" this.", localName(ref.fields), "[k] = ", ref.fields.mapValue.message ?? "", ".fromJson(v);") + f.print(" }") + f.print(" return this;") + f.print(" }") + f.print() + break; + case "google.protobuf.Value": + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {") + f.print(" switch (this.", localName(ref.kind), ".case) {") + f.print(` case "`, localName(ref.nullValue), `":`) + f.print(" return null;") + f.print(` case "`, localName(ref.boolValue), `":`) + f.print(` case "`, localName(ref.numberValue), `":`) + f.print(` case "`, localName(ref.stringValue), `":`) + f.print(" return this.", localName(ref.kind), ".value;") + f.print(` case "`, localName(ref.structValue), `":`) + f.print(` case "`, localName(ref.listValue), `":`) + f.print(` return this.`, localName(ref.kind), `.value.toJson({...options, emitDefaultValues: true});`) + f.print(" }") + f.print(` throw new Error("`, message.typeName, ` must have a value");`) + f.print(" }") + f.print() + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {") + f.print(" switch (typeof json) {") + f.print(` case "number":`) + f.print(` this.kind = { case: "`, localName(ref.numberValue), `", value: json };`) + f.print(" break;") + f.print(` case "string":`) + f.print(` this.kind = { case: "`, localName(ref.stringValue), `", value: json };`) + f.print(" break;") + f.print(` case "boolean":`) + f.print(` this.kind = { case: "`, localName(ref.boolValue), `", value: json };`) + f.print(" break;") + f.print(` case "object":`) + f.print(" if (json === null) {") + f.print(` this.kind = { case: "`, localName(ref.nullValue), `", value: `, ref.nullValue.enum, `.`, localName(ref.nullValue.enum.values[0]), ` };`) + f.print(" } else if (Array.isArray(json)) {") + f.print(` this.kind = { case: "`, localName(ref.listValue), `", value: `, ref.listValue.message, `.fromJson(json) };`) + f.print(" } else {") + f.print(` this.kind = { case: "`, localName(ref.structValue), `", value: `, ref.structValue.message, `.fromJson(json) };`) + f.print(" }") + f.print(" break;") + f.print(" default:") + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(" }") + f.print(" return this;") + f.print(" }") + f.print() + break; + case "google.protobuf.ListValue": + f.print(` override toJson(options?: Partial<`, JsonWriteOptions, `>): `, JsonValue, ` {`) + f.print(` return this.`, localName(ref.values), `.map(v => v.toJson());`) + f.print(` }`) + f.print() + f.print(` override fromJson(json: `, JsonValue, `, options?: Partial<`, JsonReadOptions, `>): this {`) + f.print(` if (!Array.isArray(json)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON " + `, protoN, `.json.debug(json));`) + f.print(` }`) + f.print(` for (let e of json) {`) + f.print(` this.`, localName(ref.values), `.push(`, ref.values.message, `.fromJson(e));`) + f.print(` }`) + f.print(` return this;`) + f.print(` }`) + f.print() + break; + case "google.protobuf.FieldMask": + f.print(` override toJson(options?: Partial<`, JsonWriteOptions, `>): `, JsonValue, ` {`) + f.print(` // Converts snake_case to protoCamelCase according to the convention`) + f.print(` // used by protoc to convert a field name to a JSON name.`) + f.print(` function protoCamelCase(snakeCase: string): string {`) + f.print(` let capNext = false;`) + f.print(` const b = [];`) + f.print(` for (let i = 0; i < snakeCase.length; i++) {`) + f.print(` let c = snakeCase.charAt(i);`) + f.print(` switch (c) {`) + f.print(` case '_':`) + f.print(` capNext = true;`) + f.print(` break;`) + f.print(` case '0':`) + f.print(` case '1':`) + f.print(` case '2':`) + f.print(` case '3':`) + f.print(` case '4':`) + f.print(` case '5':`) + f.print(` case '6':`) + f.print(` case '7':`) + f.print(` case '8':`) + f.print(` case '9':`) + f.print(` b.push(c);`) + f.print(` capNext = false;`) + f.print(` break;`) + f.print(` default:`) + f.print(` if (capNext) {`) + f.print(` capNext = false;`) + f.print(` c = c.toUpperCase();`) + f.print(` }`) + f.print(` b.push(c);`) + f.print(` break;`) + f.print(` }`) + f.print(` }`) + f.print(` return b.join('');`) + f.print(` }`) + f.print(` return this.`, localName(ref.paths), `.map(p => {`) + f.print(` if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g)) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: lowerCamelCase of path name \\"" + p + "\\" is irreversible");`) + f.print(` }`) + f.print(` return protoCamelCase(p);`) + f.print(` }).join(",");`) + f.print(` }`) + f.print() + f.print(` override fromJson(json: `, JsonValue, `, options?: Partial<`, JsonReadOptions, `>): this {`) + f.print(` if (typeof json !== "string") {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: " + proto3.json.debug(json));`) + f.print(` }`) + f.print(` if (json === "") {`) + f.print(` return this;`) + f.print(` }`) + f.print(` function camelToSnake (str: string) {`) + f.print(` if (str.includes("_")) {`) + f.print(` throw new Error("cannot decode `, message.typeName, ` from JSON: path names must be lowerCamelCase");`) + f.print(` }`) + f.print(` const sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase());`) + f.print(` return (sc[0] === "_") ? sc.substring(1) : sc;`) + f.print(` }`) + f.print(` this.`, localName(ref.paths), ` = json.split(",").map(camelToSnake);`) + f.print(` return this;`) + f.print(` }`) + f.print() + break; + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": + f.print(" override toJson(options?: Partial<", JsonWriteOptions, ">): ", JsonValue, " {") + f.print(" return proto3.json.writeScalar(", rtScalarType, ".", ScalarType[ref.value.scalar], ", this.value, true)!;") + f.print(" }") + f.print() + f.print(" override fromJson(json: ", JsonValue, ", options?: Partial<", JsonReadOptions, ">): this {") + f.print(" try {") + f.print(" this.value = ", protoN, ".json.readScalar(", rtScalarType, ".", ScalarType[ref.value.scalar], ", json);") + f.print(" } catch (e) {") + f.print(" let m = `cannot decode message ", message.typeName, " from JSON\"`;") + f.print(" if (e instanceof Error && e.message.length > 0) {") + f.print(" m += `: ${e.message}`") + f.print(" }") + f.print(" throw new Error(m);") + f.print(" }") + f.print(" return this;") + f.print(" }") + f.print() + break; + } +} + +// prettier-ignore +function generateWktStaticMethods(schema: Schema, f: GeneratedFile, message: DescMessage) { + const ref = matchWkt(message); + if (ref === undefined) { + return; + } + const { + protoInt64, + } = schema.runtime; + switch (ref.typeName) { + case "google.protobuf.Any": + f.print(" static pack(message: Message): ", message, " {") + f.print(" const any = new ", message, "();") + f.print(" any.packFrom(message);") + f.print(" return any;") + f.print(" }") + f.print() + break; + case "google.protobuf.Timestamp": + f.print(" static now(): ", message, " {") + f.print(" return ", message, ".fromDate(new Date())") + f.print(" }") + f.print() + f.print(" static fromDate(date: Date): ", message, " {") + f.print(" const ms = date.getTime();") + f.print(" return new ", message, "({") + f.print(" ", localName(ref.seconds), ": ", protoInt64, ".parse(Math.floor(ms / 1000)),") + f.print(" ", localName(ref.nanos), ": (ms % 1000) * 1000000,") + f.print(" });") + f.print(" }") + f.print() + break; + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": { + const {typing} = getFieldTyping(ref.value, f); + f.print(" static readonly fieldWrapper = {") + f.print(" wrapField(value: ", typing, " | ", message, "): ", message, " {") + f.print(" return value instanceof ", message, " ? value : new ", message, "({value});") + f.print(" },") + f.print(" unwrapField(value: ", message, "): ", typing, " {") + f.print(" return value.", localName(ref.value), ";") + f.print(" }") + f.print(" };") + f.print() + break; + } + case "google.protobuf.Duration": + case "google.protobuf.Struct": + case "google.protobuf.Value": + case "google.protobuf.ListValue": + case "google.protobuf.FieldMask": + break; + } +} diff --git a/packages/protoc-gen-es/tsconfig.json b/packages/protoc-gen-es/tsconfig.json new file mode 100644 index 000000000..8cd428f82 --- /dev/null +++ b/packages/protoc-gen-es/tsconfig.json @@ -0,0 +1,4 @@ +{ + "files": ["src/protoc-gen-es-plugin.ts"], + "extends": "../../tsconfig.base.json" +} diff --git a/packages/protoplugin/README.md b/packages/protoplugin/README.md new file mode 100644 index 000000000..341cb61aa --- /dev/null +++ b/packages/protoplugin/README.md @@ -0,0 +1,38 @@ +# @bufbuild/protoplugin + +This package helps to create your own code generator plugin. + +## Protocol Buffers for ECMAScript + +A complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) +in TypeScript, suitable for web browsers and Node.js. +Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). + + +It is a complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) +in TypeScript, suitable for web browsers and Node.js. + +For example, the following definition: + +```protobuf +message Person { + string name = 1; + int32 id = 2; // Unique ID number for this person. + string email = 3; +} +``` + +Is compiled to an ECMAScript class that can be used like this: + +```typescript +let pete = new Person({ + name: "pete", + id: 123 +}); + +let bytes = pete.toBinary(); +pete = Person.fromBinary(bytes); +pete = Person.fromJsonString('{"name": "pete", "id": 123}'); +``` + +Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es). diff --git a/packages/protoplugin/package.json b/packages/protoplugin/package.json new file mode 100644 index 000000000..f4edbf34e --- /dev/null +++ b/packages/protoplugin/package.json @@ -0,0 +1,48 @@ +{ + "name": "@bufbuild/protoplugin", + "version": "0.0.8", + "license": "(Apache-2.0 AND BSD-3-Clause)", + "description": "Helps to create your own Protocol Buffers code generators.", + "repository": { + "type": "git", + "url": "https://github.com/bufbuild/protobuf-es.git", + "directory": "packages/protoplugin" + }, + "sideEffects": false, + "scripts": { + "clean": "rm -rf ./dist/cjs/* ./dist/esm/* ./dist/types/*", + "build": "npm run build:cjs && npm run build:esm+types", + "build:cjs": "npx tsc --project tsconfig.json --module commonjs --outDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'", + "build:esm+types": "npx tsc --project tsconfig.json --module ES2015 --outDir ./dist/esm --declaration --declarationDir ./dist/types" + }, + "type": "module", + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "default": "./dist/esm/index.js" + }, + "./ecmascript": { + "import": "./dist/esm/ecmascript/index.js", + "require": "./dist/cjs/ecmascript/index.js", + "default": "./dist/esm/ecmascript/index.js" + } + }, + "types": "./dist/types/index.d.ts", + "typesVersions": { + "*": { + "ecmascript": [ + "./dist/types/ecmascript/index.d.ts" + ] + } + }, + "dependencies": { + "@bufbuild/protobuf": "^0.0.8" + }, + "devDependencies": { + "typescript": "^4.7.4" + }, + "files": [ + "dist/**/" + ] +} diff --git a/packages/protoplugin/src/create-es-plugin.ts b/packages/protoplugin/src/create-es-plugin.ts new file mode 100644 index 000000000..3a8d2a79c --- /dev/null +++ b/packages/protoplugin/src/create-es-plugin.ts @@ -0,0 +1,153 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { Schema } from "./ecmascript"; +import { createSchema } from "./ecmascript/schema.js"; +import { CodeGeneratorResponse } from "@bufbuild/protobuf"; +import type { Plugin } from "./plugin.js"; +import { PluginOptionError } from "./error.js"; +import type { Target } from "./ecmascript"; + +interface PluginInit { + /** + * Name of this code generator plugin. + */ + name: string; + + /** + * Version of this code generator plugin. + */ + version: string; + + parseOption?: PluginOptionParseFn; +} + +type PluginOptionParseFn = (key: string, value: string | undefined) => void; + +/** + * Create a new code generator plugin for ECMAScript. + * The plugin can generate JavaScript, TypeScript, or TypeScript declaration + * files. + */ +export function createEcmaScriptPlugin( + init: PluginInit, + generateFn: (schema: Schema) => void +): Plugin { + return { + name: init.name, + version: init.version, + run(req) { + const { targets, tsNocheck, bootstrapWkt } = parseParameter( + req.parameter, + init.parseOption + ); + const { schema, toResponse } = createSchema( + req, + targets, + init.name, + init.version, + tsNocheck, + bootstrapWkt + ); + generateFn(schema); + const res = new CodeGeneratorResponse(); + toResponse(res); + return res; + }, + }; +} + +function parseParameter( + parameter: string | undefined, + parseOption: PluginOptionParseFn | undefined +) { + let targets: Target[] = ["js", "dts"]; + let tsNocheck = true; + let bootstrapWkt = false; + for (const { key, value } of splitParameter(parameter)) { + switch (key) { + case "target": + targets = []; + for (const rawTarget of value.split("+")) { + switch (rawTarget) { + case "js": + case "ts": + case "dts": + if (targets.indexOf(rawTarget) < 0) { + targets.push(rawTarget); + } + break; + default: + throw new PluginOptionError(`${key}=${value}`); + } + } + value.split("+"); + break; + case "ts_nocheck": + switch (value) { + case "true": + case "1": + tsNocheck = true; + break; + case "false": + case "0": + tsNocheck = false; + break; + default: + throw new PluginOptionError(`${key}=${value}`); + } + break; + case "bootstrap_wkt": + switch (value) { + case "true": + case "1": + bootstrapWkt = true; + break; + case "false": + case "0": + bootstrapWkt = false; + break; + default: + throw new PluginOptionError(`${key}=${value}`); + } + break; + default: + if (parseOption === undefined) { + throw new PluginOptionError(`${key}=${value}`); + } + try { + parseOption(key, value); + } catch (e) { + throw new PluginOptionError(`${key}=${value}`, e); + } + break; + } + } + return { targets, tsNocheck, bootstrapWkt }; +} + +function splitParameter( + parameter: string | undefined +): { key: string; value: string }[] { + if (parameter == undefined) { + return []; + } + return parameter.split(",").map((pair) => { + const i = pair.indexOf("="); + return { + key: i === -1 ? pair : pair.substring(0, i), + value: i === -1 ? "" : pair.substring(i + 1), + }; + }); +} diff --git a/packages/protoplugin/src/ecmascript/gencommon.ts b/packages/protoplugin/src/ecmascript/gencommon.ts new file mode 100644 index 000000000..7768b1b9e --- /dev/null +++ b/packages/protoplugin/src/ecmascript/gencommon.ts @@ -0,0 +1,381 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { DescComments } from "@bufbuild/protobuf"; +import { + codegenInfo, + DescEnum, + DescEnumValue, + DescField, + DescFile, + DescMessage, + DescMethod, + DescOneof, + DescService, + ScalarType, +} from "@bufbuild/protobuf"; +import type { GeneratedFile } from "./generated-file.js"; +import type { ImportSymbol } from "./import-symbol.js"; + +const { localName, getUnwrappedFieldType, scalarDefaultValue } = codegenInfo; + +type Printable = Parameters[number]; + +export function makeFilePreamble( + file: DescFile, + pluginName: string, + pluginVersion: string, + parameter: string | undefined, + tsNoCheck: boolean +): string { + const builder: string[] = []; + const trimSuffix = (str: string, suffix: string): string => + str.endsWith(suffix) ? str.substring(0, str.length - suffix.length) : str; + const writeLeadingComments = (comments: DescComments) => { + for (let comment of comments.leadingDetached) { + comment = trimSuffix(comment, "\n"); + for (const line of comment.split("\n")) { + builder.push(`//${line}\n`); + } + builder.push("\n"); + } + if (comments.leading !== undefined) { + const comment = trimSuffix(comments.leading, "\n"); + for (const line of comment.split("\n")) { + builder.push(`//${line}\n`); + } + builder.push("\n"); + } + }; + writeLeadingComments(file.getSyntaxComments()); + builder.push(`// @generated by ${pluginName} ${pluginVersion}`); + if (parameter !== undefined) { + builder.push(` with parameter "${parameter}"`); + } + builder.push("\n"); + builder.push(`// @generated from file ${file.name}.proto (`); + if (file.proto.package !== undefined) { + builder.push(`package ${file.proto.package}, `); + } + builder.push(`syntax ${file.syntax})\n`); + builder.push("/* eslint-disable */\n"); + if (tsNoCheck) { + builder.push("/* @ts-nocheck */\n"); + } + builder.push("\n"); + writeLeadingComments(file.getPackageComments()); + return trimSuffix(builder.join(""), "\n"); +} + +export function createJsDocBlock(text: string, indentation = ""): Printable { + if (text.trim().length == 0) { + return []; + } + let lines = text.split("\n"); + if (lines.length === 0) { + return []; + } + lines = lines.map((l) => l.split("*/").join("*\\/")); + lines = lines.map((l) => (l.length > 0 ? " " + l : l)); + // prettier-ignore + return [ + `${indentation}/**\n`, + ...lines.map((l) => `${indentation} *${l}\n`), + `${indentation} */` + ]; +} + +export function makeJsDoc( + desc: + | DescEnum + | DescEnumValue + | DescMessage + | DescOneof + | DescField + | DescService + | DescMethod, + indentation = "" +): Printable { + const comments = desc.getComments(); + let text = ""; + if (comments.leading !== undefined) { + text += comments.leading; + if (text.endsWith("\n")) { + text = text.substring(0, text.length - 1); + } + } + if (comments.trailing !== undefined) { + if (text.length > 0) { + text += "\n\n"; + } + text += comments.trailing; + if (text.endsWith("\n")) { + text = text.substring(0, text.length - 1); + } + } + if (text.length > 0) { + text += "\n\n"; + } + text = text + .split("\n") + .map((line) => (line.startsWith(" ") ? line.substring(1) : line)) + .join("\n"); + + switch (desc.kind) { + case "enum_value": + text += `@generated from enum value: ${desc.declarationString()};`; + break; + case "scalar_field": + case "enum_field": + case "message_field": + case "map_field": + text += `@generated from field: ${desc.declarationString()};`; + break; + default: + text += `@generated from ${desc.toString()}`; + break; + } + let deprecated = desc.deprecated; + switch (desc.kind) { + case "enum": + case "message": + case "service": + deprecated = deprecated || (desc.file.proto.options?.deprecated ?? false); + break; + default: + break; + } + if (deprecated) { + text += "\n@deprecated"; + } + if (text.length > 0) { + return createJsDocBlock(text, indentation); + } + return []; +} + +/** + * Returns an expression for the TypeScript typing of a field, + * and whether the property should be optional. + */ +export function getFieldTyping( + field: DescField, + file: GeneratedFile +): { typing: Printable; optional: boolean } { + const typing: Printable = []; + let optional = false; + switch (field.kind) { + case "scalar_field": + typing.push(scalarTypeScriptType(field.scalar)); + optional = field.optional; + break; + case "message_field": { + const baseType = getUnwrappedFieldType(field); + if (baseType !== undefined) { + typing.push(scalarTypeScriptType(baseType)); + } else { + typing.push(file.import(field.message).toTypeOnly()); + } + optional = true; + break; + } + case "enum_field": + typing.push(file.import(field.enum).toTypeOnly()); + optional = field.optional; + break; + case "map_field": { + let keyType: string; + switch (field.mapKey) { + case ScalarType.INT32: + case ScalarType.FIXED32: + case ScalarType.UINT32: + case ScalarType.SFIXED32: + case ScalarType.SINT32: + keyType = "number"; + break; + default: + keyType = "string"; + break; + } + let valueType; + switch (field.mapValue.kind) { + case "scalar": + valueType = scalarTypeScriptType(field.mapValue.scalar); + break; + case "message": + valueType = file.import(field.mapValue.message).toTypeOnly(); + break; + case "enum": + valueType = file.import(field.mapValue.enum).toTypeOnly(); + break; + } + typing.push("{ [key: ", keyType, "]: ", valueType, " }"); + optional = false; + break; + } + } + if (field.repeated) { + typing.push("[]"); + optional = false; + } + return { typing, optional }; +} + +export function scalarTypeScriptType(type: ScalarType): Printable { + switch (type) { + case ScalarType.STRING: + return "string"; + case ScalarType.BOOL: + return "boolean"; + case ScalarType.UINT64: + case ScalarType.SFIXED64: + case ScalarType.FIXED64: + case ScalarType.SINT64: + case ScalarType.INT64: + return "bigint"; + case ScalarType.BYTES: + return "Uint8Array"; + default: + return "number"; + } +} + +export function literalString(value: string): string { + return ( + '"' + + value + .split("\\") + .join("\\\\") + .split('"') + .join('\\"') + .split("\r") + .join("\\r") + .split("\n") + .join("\\n") + + '"' + ); +} + +export function getFieldExplicitDefaultValue( + field: DescField, + protoInt64Symbol: ImportSymbol +): Printable | undefined { + switch (field.kind) { + case "enum_field": { + const value = field.enum.values.find( + (v) => v.number === field.getDefaultValue() + ); + if (value !== undefined) { + return [value.parent, ".", localName(value)]; + } + break; + } + case "scalar_field": { + const defaultValue = field.getDefaultValue(); + if (defaultValue === undefined) { + break; + } + switch (field.scalar) { + case ScalarType.FLOAT: + case ScalarType.DOUBLE: { + return defaultValue; + } + case ScalarType.INT64: + case ScalarType.SINT64: + case ScalarType.SFIXED64: + return [protoInt64Symbol, `.parse("${defaultValue.toString()}")`]; + case ScalarType.UINT64: + case ScalarType.FIXED64: + return [protoInt64Symbol, `.uParse("${defaultValue.toString()}")`]; + case ScalarType.INT32: + case ScalarType.FIXED32: + case ScalarType.UINT32: + case ScalarType.SFIXED32: + case ScalarType.SINT32: + return defaultValue; + case ScalarType.BOOL: { + return defaultValue; + } + case ScalarType.STRING: { + if (typeof defaultValue == "string") { + return literalString(defaultValue); + } + break; + } + case ScalarType.BYTES: { + if (defaultValue instanceof Uint8Array) { + return defaultValue; + } + break; + } + } + break; + } + default: + break; + } + return undefined; +} + +export function getFieldIntrinsicDefaultValue(field: DescField): { + defaultValue: Printable | undefined; + typingInferrable: boolean; +} { + if (field.repeated) { + return { + defaultValue: "[]", + typingInferrable: false, + }; + } + if (field.kind == "map_field") { + return { + defaultValue: "{}", + typingInferrable: false, + }; + } + let defaultValue: Printable | undefined = undefined; + let typingInferrable = false; + if (field.parent.file.syntax == "proto3") { + switch (field.kind) { + case "enum_field": { + if (!field.optional) { + const zeroValue = field.enum.values.find((v) => v.number === 0); + if (zeroValue === undefined) { + throw new Error("invalid proto3 enum: missing 0 value"); + } + defaultValue = [field.enum, ".", localName(zeroValue)]; + typingInferrable = true; + } + break; + } + case "scalar_field": + if (!field.optional) { + typingInferrable = true; + if (field.scalar === ScalarType.STRING) { + defaultValue = literalString(""); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment + defaultValue = scalarDefaultValue(field.scalar); + } + } + break; + default: + break; + } + } + return { + defaultValue, + typingInferrable, + }; +} diff --git a/packages/protoplugin/src/ecmascript/generated-file.ts b/packages/protoplugin/src/ecmascript/generated-file.ts new file mode 100644 index 000000000..a1b730b53 --- /dev/null +++ b/packages/protoplugin/src/ecmascript/generated-file.ts @@ -0,0 +1,433 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { DescEnum, DescFile, DescMessage } from "@bufbuild/protobuf"; +import { + CodeGeneratorResponse, + CodeGeneratorResponse_File, +} from "@bufbuild/protobuf"; +import type { ImportSymbol } from "./import-symbol.js"; +import { createImportSymbol } from "./import-symbol.js"; +import { literalString, makeFilePreamble } from "./gencommon.js"; +import type { RuntimeImports } from "./runtime-imports"; + +/** + * All types that can be passed to GeneratedFile.print() + */ +type Printable = + | string + | number + | boolean + | bigint + | Uint8Array + | ImportSymbol + | DescMessage + | DescEnum + | Printable[]; + +/** + * Represents a JavaScript, TypeScript, or TypeScript declaration file. + */ +export interface GeneratedFile { + /** + * Create a standard preamble the includes comments at the top of the + * protobuf source file (like a license header), as well as information + * about the code generator and its version. + * + * The preamble is always placed at the very top of the generated file, + * above import statements. + */ + preamble(file: DescFile): void; + + /** + * Add a line of code to the file. + * + * - string: Prints the string verbatim. + * - number or boolean: Prints a literal. + * - bigint: Prints an expression using protoInt64.parse(). + * - Uint8Array: Prints an expression that re-created the array. + * - ImportSymbol: Adds an import statement and prints the name of the symbol. + * - DescMessage or DescEnum: Imports the type if necessary, and prints the name. + */ + print(...any: Printable[]): void; + + /** + * Reserves an identifier in this file. + */ + export(name: string): ImportSymbol; + + /** + * Import a message or enumeration generated by protoc-gen-es. + */ + import(type: DescMessage | DescEnum): ImportSymbol; + + /** + * Import any symbol from a file or package. + * + * The import path can point to a package, for example `@foo/bar/baz.js`, or + * to a file, for example `./bar/baz.js`. + * + * Note that while paths to a file begin with a `./`, they must be + * relative to the project root. The import path is automatically made + * relative to the current file. + */ + import(name: string, from: string): ImportSymbol; +} + +export interface GenerateFileToResponse { + toResponse(res: CodeGeneratorResponse): void; +} + +type CreateTypeImportFn = (desc: DescMessage | DescEnum) => ImportSymbol; + +export function createGeneratedFile( + name: string, + createTypeImport: CreateTypeImportFn, + runtimeImports: RuntimeImports, + preambleSettings: { + pluginName: string; + pluginVersion: string; + parameter: string | undefined; + tsNocheck: boolean; + } +): GeneratedFile & GenerateFileToResponse { + const importPath = deriveImportPath(name); + let preamble: string | undefined; + const el: El[] = []; + return { + preamble(file) { + preamble = makeFilePreamble( + file, + preambleSettings.pluginName, + preambleSettings.pluginVersion, + preambleSettings.parameter, + preambleSettings.tsNocheck + ); + }, + print(...any) { + printableToEl(any, el, createTypeImport, runtimeImports); + el.push("\n"); + }, + export(name) { + return createImportSymbol(name, importPath); + }, + import(typeOrName: DescMessage | DescEnum | string, from?: string) { + if (typeof typeOrName == "string") { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return createImportSymbol(name, from!); + } + return createTypeImport(typeOrName); + }, + toResponse(res) { + let content = elToContent(el, importPath); + if (content.length === 0) { + return; + } + if (preamble !== undefined) { + content = preamble + "\n" + content; + } + res.file.push( + new CodeGeneratorResponse_File({ + name: name, + content, + }) + ); + }, + }; +} + +type El = ImportSymbol | string; + +const importPathExtension = ".js"; +const knownExtensionsRE = /\.(js|ts|d.ts)$/; +const relativePathRE = /^\.{1,2}\//; + +function deriveImportPath(filename: string): string { + let importPath = filename.replace(knownExtensionsRE, importPathExtension); + if (!relativePathRE.test(importPath)) { + importPath = "./" + importPath; + } + return importPath; +} + +function elToContent(el: El[], importerPath: string): string { + const c: string[] = []; + const symbolToIdentifier = processImports( + el, + importerPath, + (typeOnly, from, names) => { + const p = names.map(({ name, alias }) => + alias == undefined ? name : `${name} as ${alias}` + ); + const what = `{${p.join(", ")}}`; + if (typeOnly) { + c.push(`import type ${what} from ${literalString(from)};\n`); + } else { + c.push(`import ${what} from ${literalString(from)};\n`); + } + } + ); + if (c.length > 0) { + c.push("\n"); + } + for (const e of el) { + if (typeof e == "string") { + c.push(e); + continue; + } + const ident = symbolToIdentifier.get(e.id); + if (ident != undefined) { + c.push(ident); + } + } + return c.join(""); +} + +function printableToEl( + printables: Printable[], + el: El[], + createTypeImport: CreateTypeImportFn, + runtimeImports: RuntimeImports +): void { + for (const p of printables) { + if (Array.isArray(p)) { + printableToEl(p, el, createTypeImport, runtimeImports); + } else { + switch (typeof p) { + case "string": + el.push(p); + break; + case "number": + el.push(literalNumber(p)); + break; + case "boolean": + el.push(p.toString()); + break; + case "bigint": + el.push(...literalBigint(p, runtimeImports)); + break; + case "object": + if (p instanceof Uint8Array) { + el.push(literalUint8Array(p)); + break; + } + switch (p.kind) { + case "es_symbol": + el.push(p); + break; + case "message": + case "enum": + el.push(createTypeImport(p)); + break; + } + break; + default: + throw `cannot print ${typeof p}`; + } + } + } +} + +type MakeImportStatementFn = ( + typeOnly: boolean, + from: string, + names: { name: string; alias?: string }[] +) => void; + +function processImports( + el: El[], + importerPath: string, + makeImportStatement: MakeImportStatementFn +) { + // identifiers to use in the output + const symbolToIdentifier = new Map(); + // symbols that need a value import (as opposed to a type-only import) + const symbolToIsValue = new Map(); + // taken in this file + const identifiersTaken = new Set(); + // foreign symbols need an import + const foreignSymbols: ImportSymbol[] = []; + + // Walk through all symbols used and populate the collections above. + for (const s of el) { + if (typeof s == "string") { + continue; + } + symbolToIdentifier.set(s.id, s.name); + if (!s.typeOnly) { + // a symbol is only type-imported as long as all uses are type-only + symbolToIsValue.set(s.id, true); + } + if (s.from === importerPath) { + identifiersTaken.add(s.name); + } else { + foreignSymbols.push(s); + } + } + + // Walk through all foreign symbols and make their identifiers unique. + const handledSymbols = new Set(); + for (const s of foreignSymbols) { + if (handledSymbols.has(s.id)) { + continue; + } + handledSymbols.add(s.id); + if (!identifiersTaken.has(s.name)) { + identifiersTaken.add(s.name); + continue; + } + let i = 1; + let alias: string; + for (;;) { + // We choose '$' because it is invalid in proto identifiers. + alias = `${s.name}$${i}`; + if (!identifiersTaken.has(alias)) { + break; + } + i++; + } + identifiersTaken.add(alias); + symbolToIdentifier.set(s.id, alias); + } + + // Group foreign symbols (imports) by their source (from). + type Imp = { + types: Map; // type-only imports, name to (optional) alias + values: Map; // value imports, name to (optional) alias + }; + const sourceToImport = new Map(); + for (const s of foreignSymbols) { + let i = sourceToImport.get(s.from); + if (i == undefined) { + i = { + types: new Map(), + values: new Map(), + }; + sourceToImport.set(s.from, i); + } + let alias = symbolToIdentifier.get(s.id); + if (alias == s.name) { + alias = undefined; + } + if (symbolToIsValue.get(s.id)) { + i.values.set(s.name, alias); + } else { + i.types.set(s.name, alias); + } + } + + // Make import statements. + const handledSource = new Set(); + const buildNames = (map: Map) => { + const names: { name: string; alias?: string }[] = []; + map.forEach((value, key) => names.push({ name: key, alias: value })); + names.sort((a, b) => a.name.localeCompare(b.name)); + return names; + }; + for (const s of foreignSymbols) { + if (handledSource.has(s.from)) { + continue; + } + handledSource.add(s.from); + const i = sourceToImport.get(s.from); + if (i == undefined) { + // should never happen + continue; + } + const from = makeImportPathRelative(importerPath, s.from); + if (i.types.size > 0) { + makeImportStatement(true, from, buildNames(i.types)); + } + if (i.values.size > 0) { + makeImportStatement(false, from, buildNames(i.values)); + } + } + + return symbolToIdentifier; +} + +// makeImportPathRelative makes an import path relative to the file importing +// it. For example, consider the following files: +// - foo/foo.js +// - baz.js +// If foo.js wants to import baz.js, we return ../baz.js +function makeImportPathRelative(importer: string, importPath: string): string { + if (!relativePathRE.test(importPath)) { + // We don't touch absolute imports, like @bufbuild/protobuf + return importPath; + } + let a = importer + .replace(/^\.\//, "") + .split("/") + .filter((p) => p.length > 0) + .slice(0, -1); + let b = importPath + .replace(/^\.\//, "") + .split("/") + .filter((p) => p.length > 0); + let matchingPartCount = 0; + for ( + let l = Math.min(a.length, b.length); + matchingPartCount < l; + matchingPartCount++ + ) { + if (a[matchingPartCount] !== b[matchingPartCount]) { + break; + } + } + a = a.slice(matchingPartCount); + b = b.slice(matchingPartCount); + const c = a + .map(() => "..") + .concat(b) + .join("/"); + return relativePathRE.test(c) ? c : "./" + c; +} + +function literalNumber(value: number): string { + if (Number.isNaN(value)) { + return "globalThis.Number.NaN"; + } + if (value === Number.POSITIVE_INFINITY) { + return "globalThis.Number.POSITIVE_INFINITY"; + } + if (value === Number.NEGATIVE_INFINITY) { + return "globalThis.Number.NEGATIVE_INFINITY"; + } + return value.toString(10); +} + +function literalBigint(value: bigint, runtimeImports: RuntimeImports): El[] { + // Loose comparison will match between 0n and 0. + if (value == (0 as unknown as bigint)) { + return [runtimeImports.protoInt64, ".zero"]; + } + return [ + runtimeImports.protoInt64, + ".parse(", + literalString(value.toString()), + ")", + ]; +} + +function literalUint8Array(value: Uint8Array): string { + if (value.length === 0) { + return "new Uint8Array(0)"; + } + const strings: string[] = []; + for (const n of value) { + strings.push("0x" + n.toString(16).toUpperCase().padStart(2, "0")); + } + return `new Uint8Array([${strings.join(", ")}])`; +} diff --git a/packages/protoplugin/src/ecmascript/import-symbol.ts b/packages/protoplugin/src/ecmascript/import-symbol.ts new file mode 100644 index 000000000..c461ec0e0 --- /dev/null +++ b/packages/protoplugin/src/ecmascript/import-symbol.ts @@ -0,0 +1,79 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +/** + * An import symbol represents an ECMAScript import. + */ +export type ImportSymbol = { + readonly kind: "es_symbol"; + + /** + * The name to import. + */ + readonly name: string; + + /** + * The import path. + * + * The path can point to a package, for example `@foo/bar/baz.js`, or + * to a file, for example `./bar/baz.js`. + * + * Note that while paths to a file begin with a `./`, they must be + * relative to the project root. + */ + readonly from: string; + + /** + * Whether this is a type-only import - an import that only exists in + * TypeScript. + */ + readonly typeOnly: boolean; + + /** + * Create a copy of this import, and make it type-only for TypeScript. + */ + toTypeOnly(): ImportSymbol; + + /** + * The unique ID based on name and from, disregarding typeOnly. + */ + readonly id: EsSymbolId; +}; + +/** + * Create a new import symbol. + */ +export function createImportSymbol( + name: string, + from: string, + typeOnly?: boolean +): ImportSymbol { + const id = `import("${from}").${name}`; + const s: ImportSymbol = { + kind: "es_symbol", + name, + from, + typeOnly: false, + id, + toTypeOnly() { + return { + ...this, + typeOnly: true, + }; + }, + }; + return typeOnly === true ? s.toTypeOnly() : s; +} + +type EsSymbolId = string; diff --git a/packages/protoplugin/src/ecmascript/index.ts b/packages/protoplugin/src/ecmascript/index.ts new file mode 100644 index 000000000..df92a17b3 --- /dev/null +++ b/packages/protoplugin/src/ecmascript/index.ts @@ -0,0 +1,32 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import { codegenInfo } from "@bufbuild/protobuf"; + +export { Target } from "./target.js"; +export { Schema } from "./schema.js"; +export { RuntimeImports } from "./runtime-imports.js"; +export { GeneratedFile } from "./generated-file.js"; +export { ImportSymbol } from "./import-symbol.js"; + +export const { localName } = codegenInfo; + +export { + createJsDocBlock, + getFieldExplicitDefaultValue, + getFieldIntrinsicDefaultValue, + getFieldTyping, + makeJsDoc, + literalString, +} from "./gencommon.js"; diff --git a/packages/protoplugin/src/ecmascript/runtime-imports.ts b/packages/protoplugin/src/ecmascript/runtime-imports.ts new file mode 100644 index 000000000..87c1149a7 --- /dev/null +++ b/packages/protoplugin/src/ecmascript/runtime-imports.ts @@ -0,0 +1,72 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { ImportSymbol } from "./import-symbol.js"; +import { createImportSymbol } from "./import-symbol.js"; +import { codegenInfo } from "@bufbuild/protobuf"; + +export interface RuntimeImports { + proto2: ImportSymbol; + proto3: ImportSymbol; + Message: ImportSymbol; + PartialMessage: ImportSymbol; + PlainMessage: ImportSymbol; + FieldList: ImportSymbol; + MessageType: ImportSymbol; + BinaryReadOptions: ImportSymbol; + BinaryWriteOptions: ImportSymbol; + JsonReadOptions: ImportSymbol; + JsonWriteOptions: ImportSymbol; + JsonValue: ImportSymbol; + JsonObject: ImportSymbol; + protoInt64: ImportSymbol; + ScalarType: ImportSymbol; + MethodKind: ImportSymbol; + MethodIdempotency: ImportSymbol; +} + +export function createRuntimeImports(bootstrapWkt: boolean): RuntimeImports { + // prettier-ignore + return { + proto2: infoToSymbol("proto2", bootstrapWkt), + proto3: infoToSymbol("proto3", bootstrapWkt), + Message: infoToSymbol("Message", bootstrapWkt), + PartialMessage: infoToSymbol("PartialMessage", bootstrapWkt), + PlainMessage: infoToSymbol("PlainMessage", bootstrapWkt), + FieldList: infoToSymbol("FieldList", bootstrapWkt), + MessageType: infoToSymbol("MessageType", bootstrapWkt), + BinaryReadOptions: infoToSymbol("BinaryReadOptions", bootstrapWkt), + BinaryWriteOptions: infoToSymbol("BinaryWriteOptions",bootstrapWkt), + JsonReadOptions: infoToSymbol("JsonReadOptions", bootstrapWkt), + JsonWriteOptions: infoToSymbol("JsonWriteOptions", bootstrapWkt), + JsonValue: infoToSymbol("JsonValue", bootstrapWkt), + JsonObject: infoToSymbol("JsonObject", bootstrapWkt), + protoInt64: infoToSymbol("protoInt64", bootstrapWkt), + ScalarType: infoToSymbol("ScalarType", bootstrapWkt), + MethodKind: infoToSymbol("MethodKind", bootstrapWkt), + MethodIdempotency: infoToSymbol("MethodIdempotency", bootstrapWkt), + }; +} + +function infoToSymbol( + name: keyof typeof codegenInfo.symbols, + bootstrapWkt: boolean +): ImportSymbol { + const info = codegenInfo.symbols[name]; + const symbol = createImportSymbol( + name, + bootstrapWkt ? info.privateImportPath : info.publicImportPath + ); + return info.typeOnly ? symbol.toTypeOnly() : symbol; +} diff --git a/packages/protoplugin/src/ecmascript/schema.ts b/packages/protoplugin/src/ecmascript/schema.ts new file mode 100644 index 000000000..7e093cf40 --- /dev/null +++ b/packages/protoplugin/src/ecmascript/schema.ts @@ -0,0 +1,165 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { + CodeGeneratorRequest, + DescEnum, + DescFile, + DescMessage, + DescriptorSet, +} from "@bufbuild/protobuf"; +import { + codegenInfo, + CodeGeneratorResponse, + CodeGeneratorResponse_Feature, + createDescriptorSet, + protoInt64, +} from "@bufbuild/protobuf"; +import type { + GeneratedFile, + GenerateFileToResponse, +} from "./generated-file.js"; +import { createGeneratedFile } from "./generated-file.js"; +import { createRuntimeImports, RuntimeImports } from "./runtime-imports.js"; +import { createImportSymbol, ImportSymbol } from "./import-symbol.js"; +import type { Target } from "./target"; + +/** + * Schema describes the files and types that the plugin is requested to + * generate. + */ +export interface Schema { + /** + * The files we are asked to generate. + */ + readonly files: readonly DescFile[]; + + /** + * All files contained in the code generator request. + */ + readonly allFiles: readonly DescFile[]; + + /** + * The plugin option `target`. A code generator should support all targets. + */ + readonly targets: readonly Target[]; + + /** + * Provides some symbols from the runtime library @bufbuild/protobuf. + */ + readonly runtime: RuntimeImports; + + /** + * Generate a new file with the given name. + */ + generateFile(name: string): GeneratedFile; + + /** + * The original google.protobuf.compiler.CodeGeneratorRequest. + */ + readonly proto: CodeGeneratorRequest; +} + +interface SchemaController { + schema: Schema; + toResponse: (res: CodeGeneratorResponse) => void; +} + +export function createSchema( + request: CodeGeneratorRequest, + targets: Target[], + pluginName: string, + pluginVersion: string, + tsNocheck: boolean, + bootstrapWkt: boolean +): SchemaController { + const descriptorSet = createDescriptorSet(request.protoFile); + const filesToGenerate = findFilesToGenerate(descriptorSet, request); + const runtime = createRuntimeImports(bootstrapWkt); + const createTypeImport = (desc: DescMessage | DescEnum): ImportSymbol => { + const name = codegenInfo.localName(desc); + const from = makeImportPath(desc.file, bootstrapWkt, filesToGenerate); + return createImportSymbol(name, from); + }; + const generatedFiles: GenerateFileToResponse[] = []; + const schema: Schema = { + targets, + runtime, + proto: request, + files: filesToGenerate, + allFiles: descriptorSet.files, + generateFile(name) { + const genFile = createGeneratedFile(name, createTypeImport, runtime, { + pluginName, + pluginVersion, + parameter: request.parameter, + tsNocheck, + }); + generatedFiles.push(genFile); + return genFile; + }, + }; + return { + schema, + toResponse(res) { + res.supportedFeatures = protoInt64.parse( + CodeGeneratorResponse_Feature.PROTO3_OPTIONAL + ); + for (const genFile of generatedFiles) { + genFile.toResponse(res); + } + }, + }; +} + +function findFilesToGenerate( + descriptorSet: DescriptorSet, + request: CodeGeneratorRequest +) { + const missing = request.fileToGenerate.filter((fileToGenerate) => + descriptorSet.files.every((file) => fileToGenerate !== file.name + ".proto") + ); + if (missing.length) { + throw `files_to_generate missing in the request: ${missing.join(", ")}`; + } + return descriptorSet.files.filter((file) => + request.fileToGenerate.includes(file.name + ".proto") + ); +} + +/** + * Returns the import path for files generated by the base type generator + * protoc-gen-es. + */ +function makeImportPath( + file: DescFile, + bootstrapWkt: boolean, + filesToGenerate: DescFile[] +): string { + // Well-known types are published with the runtime package. We usually want + // the generated code to import them from the runtime package, with the + // following exceptions: + // 1. We are bootstrapping the runtime package via the plugin option + // "bootstrap_wkt". In that case, we cannot refer to the runtime package + // itself. + // 2. We were explicitly asked to generate the well-known type. + if ( + !bootstrapWkt && + !filesToGenerate.includes(file) && + codegenInfo.wktSourceFiles.includes(file.name + ".proto") + ) { + return codegenInfo.packageName; + } + return "./" + file.name + "_pb.js"; +} diff --git a/private/protoplugin/fuzz_test.go b/packages/protoplugin/src/ecmascript/target.ts similarity index 62% rename from private/protoplugin/fuzz_test.go rename to packages/protoplugin/src/ecmascript/target.ts index 263c2f603..82b253cf5 100644 --- a/private/protoplugin/fuzz_test.go +++ b/packages/protoplugin/src/ecmascript/target.ts @@ -12,24 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build go1.18 -// +build go1.18 - -package protoplugin - -import ( - "testing" -) - -func FuzzProtoCamelCase(f *testing.F) { - f.Add("foo_bar") - f.Add("__proto__") - f.Add(`FacilityFactoryFacadeMutator66Generator_`) - for k := range reservedIdentifiers { - f.Add(k) - } - for k := range reservedObjectProperties { - f.Add(k) - } - f.Fuzz(assertProtoCamelCaseEqualsProtocJSONName) -} +/** + * Represents possible values of the plugin option `target`. + */ +export type Target = "js" | "ts" | "dts"; diff --git a/packages/protoplugin/src/error.ts b/packages/protoplugin/src/error.ts new file mode 100644 index 000000000..953032ca6 --- /dev/null +++ b/packages/protoplugin/src/error.ts @@ -0,0 +1,33 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +export class PluginOptionError extends Error { + constructor(option: string, reason?: unknown) { + super( + reason === undefined + ? `invalid option "${option}` + : `invalid option "${option}: ${reasonToString(reason)}` + ); + } +} + +export function reasonToString(reason: unknown): string { + if (reason instanceof Error) { + return reason.message; + } + if (typeof reason === "string") { + return reason; + } + return String(reason); +} diff --git a/packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.js b/packages/protoplugin/src/index.ts similarity index 58% rename from packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.js rename to packages/protoplugin/src/index.ts index 47fe7bbd7..156ce29ee 100644 --- a/packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.js +++ b/packages/protoplugin/src/index.ts @@ -12,20 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" -// @generated from file extra/enum-annotated.proto (package spec, syntax proto3) -/* eslint-disable */ - -import {proto3} from "@bufbuild/protobuf"; - -/** - * @generated from enum spec.AnnotatedEnum - */ -export const AnnotatedEnum = proto3.makeEnum( - "spec.AnnotatedEnum", - [ - {no: 0, name: "UNSPECIFIED"}, - {no: 1, name: "FOO"}, - ], -); - +export { Plugin } from "./plugin.js"; +export { Schema } from "./ecmascript/schema.js"; +export { runNodeJs } from "./run-node.js"; +export { createEcmaScriptPlugin } from "./create-es-plugin.js"; diff --git a/packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.d.ts b/packages/protoplugin/src/plugin.ts similarity index 61% rename from packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.d.ts rename to packages/protoplugin/src/plugin.ts index 43fe113d0..2cf33543a 100644 --- a/packages/protobuf-test/src/gen/js/extra/enum-annotated_pb.d.ts +++ b/packages/protoplugin/src/plugin.ts @@ -12,22 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -// @generated by protoc-gen-es v0.0.8 with parameter "ts_nocheck=false,target=js+dts" -// @generated from file extra/enum-annotated.proto (package spec, syntax proto3) -/* eslint-disable */ +import type { + CodeGeneratorRequest, + CodeGeneratorResponse, +} from "@bufbuild/protobuf"; /** - * @generated from enum spec.AnnotatedEnum + * Represents any code generator plugin. */ -export declare enum AnnotatedEnum { +export interface Plugin { /** - * @generated from enum value: UNSPECIFIED = 0; + * Name of this code generator plugin. */ - UNSPECIFIED = 0, + name: string; /** - * @generated from enum value: FOO = 1; + * Version of this code generator plugin. */ - FOO = 1, -} + version: string; + /** + * Run this plugin for the given request. + */ + run(request: CodeGeneratorRequest): CodeGeneratorResponse; +} diff --git a/packages/protoplugin/src/run-node.ts b/packages/protoplugin/src/run-node.ts new file mode 100644 index 000000000..8399fdae1 --- /dev/null +++ b/packages/protoplugin/src/run-node.ts @@ -0,0 +1,92 @@ +// Copyright 2021-2022 Buf Technologies, Inc. +// +// 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. + +import type { Plugin } from "./plugin.js"; +import type { ReadStream } from "tty"; +import { CodeGeneratorRequest } from "@bufbuild/protobuf"; +import { PluginOptionError, reasonToString } from "./error.js"; + +/** + * Run a plugin with Node.js. + * + * ``` + * #!/usr/bin/env node + * const {runNodeJs} = require("@bufbuild/protoplugin"); + * const {myPlugin} = require("./protoc-gen-x-plugin.js"); + * runNodeJs(myPlugin); + * ``` + */ +export function runNodeJs(plugin: Plugin): void { + setBlockingStdout(); + const args = process.argv.slice(2); + if ((args.length === 1 && args[0] === "-v") || args[0] === "--version") { + process.stdout.write(`${plugin.name} ${plugin.version}\n`); + process.exit(0); + return; + } + if (args.length !== 0) { + process.stderr.write( + `${plugin.name} accepts a google.protobuf.compiler.CodeGeneratorRequest on stdin and writes a CodeGeneratorResponse to stdout\n` + ); + process.exit(1); + return; + } + readBytes(process.stdin) + .then((data) => { + const req = CodeGeneratorRequest.fromBinary(data); + const res = plugin.run(req); + process.stdout.write(res.toBinary()); + process.exit(0); + }) + .catch((reason) => { + const message = + reason instanceof PluginOptionError + ? reason.message + : reasonToString(reason); + process.stderr.write(`${plugin.name}: ${message}\n`); + process.exit(1); + return; + }); +} + +/** + * Read a stream to the end. + */ +function readBytes(stream: ReadStream): Promise { + return new Promise((resolve, reject) => { + const chunks: Uint8Array[] = []; + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => { + resolve(Buffer.concat(chunks)); + }); + stream.on("error", (err) => { + reject(err); + }); + }); +} + +/** + * Node.js buffers stdout, and process.exit() will truncate output. + * As a workaround, we set the stream to blocking via a private API. + * See https://github.com/timostamm/protobuf-ts/issues/134 + * See https://github.com/nodejs/node/issues/6456 + */ +function setBlockingStdout(): void { + const stdout = process.stdout as unknown as { + _handle?: { + setBlocking?(value: boolean): void; + }; + }; + stdout._handle?.setBlocking?.(true); +} diff --git a/packages/protoplugin/tsconfig.json b/packages/protoplugin/tsconfig.json new file mode 100644 index 000000000..f5f48d7ad --- /dev/null +++ b/packages/protoplugin/tsconfig.json @@ -0,0 +1,4 @@ +{ + "files": ["src/index.ts", "src/ecmascript/index.ts"], + "extends": "../../tsconfig.base.json" +} diff --git a/private/protoplugin/comments.go b/private/protoplugin/comments.go deleted file mode 100644 index 9503b3e6a..000000000 --- a/private/protoplugin/comments.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "fmt" - "strings" - - "google.golang.org/protobuf/types/descriptorpb" -) - -// The following field numbers are used to find comments in -// google.protobuf.SourceCodeInfo. -const ( - fieldNumber_FileDescriptorProto_Package = 2 - fieldNumber_FileDescriptorProto_MessageType = 4 - fieldNumber_FileDescriptorProto_EnumType = 5 - fieldNumber_FileDescriptorProto_Service = 6 - fieldNumber_FileDescriptorProto_Extension = 7 - fieldNumber_FileDescriptorProto_Syntax = 12 - fieldNumber_DescriptorProto_Field = 2 - fieldNumber_DescriptorProto_NestedType = 3 - fieldNumber_DescriptorProto_EnumType = 4 - fieldNumber_DescriptorProto_OneofDecl = 8 - fieldNumber_EnumDescriptorProto_Value = 2 - fieldNumber_ServiceDescriptorProto_Method = 2 -) - -type jsDocBlock struct { - lines []string -} - -func newJsDocBlock() *jsDocBlock { - return &jsDocBlock{} -} - -func (j *jsDocBlock) add(text string) { - text = strings.TrimSuffix(text, "\n") - text = strings.ReplaceAll(text, "*/", "*\\/") - lines := strings.Split(text, "\n") - j.lines = append(j.lines, lines...) -} - -func (j *jsDocBlock) empty() bool { - return len(j.lines) == 0 -} - -func (j *jsDocBlock) indentedString(indent string) string { - var buf strings.Builder - if len(j.lines) > 0 { - _, _ = fmt.Fprintf(&buf, "%s/**\n", indent) - for _, line := range j.lines { - _, _ = fmt.Fprintf(&buf, "%s *%s\n", indent, line) - } - _, _ = fmt.Fprintf(&buf, "%s */", indent) - } - return buf.String() -} - -// CommentSet is a set of comments associated with a protobuf element like -// a message, field, or enum value. -// Those comments are passed to the plugin as part of the SourceCodeInfo -// message in a CodeGeneratorRequest. While SourceCodeInfo contains all -// information for a file, a CommentSet is already filtered for a given -// protobuf element. -type CommentSet struct { - LeadingDetached []string - Leading string - Trailing string -} - -func newCommentSet(sourceCodeInfo *descriptorpb.SourceCodeInfo, sourcePath []int32) CommentSet { - set := CommentSet{} - for _, location := range sourceCodeInfo.GetLocation() { - if len(location.Path) != len(sourcePath) { - continue - } - pathMatches := true - for index, want := range location.Path { - if sourcePath[index] != want { - pathMatches = false - break - } - } - if !pathMatches { - continue - } - set.Leading = location.GetLeadingComments() - set.Trailing = location.GetTrailingComments() - set.LeadingDetached = location.GetLeadingDetachedComments() - } - return set -} - -func makeFilePreamble(gen *Generator, fileName string, packageName string, syntax ProtoSyntax, syntaxComments CommentSet, packageComments CommentSet) string { - var builder strings.Builder - writeLeadingComments(&builder, syntaxComments) - writeGenerationInfo(&builder, gen, fileName, packageName, syntax) - _, _ = builder.WriteString("/* eslint-disable */\n") - if gen.tsNoCheck { - _, _ = builder.WriteString("/* @ts-nocheck */\n") - } - _, _ = builder.WriteString("\n") - writeLeadingComments(&builder, packageComments) - return strings.TrimSuffix(builder.String(), "\n") -} - -func writeGenerationInfo(builder *strings.Builder, gen *Generator, fileName string, packageName string, syntax ProtoSyntax) { - _, _ = fmt.Fprintf(builder, "// @generated by %s %s", gen.Options.Name, gen.Options.Version) - if gen.Request.GetParameter() != "" { - _, _ = fmt.Fprintf(builder, ` with parameter "%s"`, gen.Request.GetParameter()) - } - _, _ = builder.WriteString("\n") - _, _ = fmt.Fprintf(builder, "// @generated from file %s (", fileName) - if packageName != "" { - _, _ = fmt.Fprintf(builder, "package %s, ", packageName) - } - _, _ = fmt.Fprintf(builder, "syntax %s)\n", syntax) -} - -func writeLeadingComments(builder *strings.Builder, comments CommentSet) { - for _, comment := range comments.LeadingDetached { - comment = strings.TrimSuffix(comment, "\n") - for _, line := range strings.Split(comment, "\n") { - _, _ = builder.WriteString("//" + line + "\n") - } - _, _ = builder.WriteString("\n") - } - if comment := comments.Leading; comment != "" { - comment = strings.TrimSuffix(comment, "\n") - for _, line := range strings.Split(comment, "\n") { - _, _ = builder.WriteString("//" + line + "\n") - } - _, _ = builder.WriteString("\n") - } -} diff --git a/private/protoplugin/generated_file.go b/private/protoplugin/generated_file.go deleted file mode 100644 index 84f193485..000000000 --- a/private/protoplugin/generated_file.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "bytes" - "fmt" - "sort" - "strings" -) - -// GeneratedFile represents a file generated by a plugin. -type GeneratedFile struct { - Name string // path to the file as generated - ImportPath string // path used to import this file - SkipIfEmpty bool // unless explicitly set to false, the file is excluded from the output if it has an empty body - symbolPool *symbolPool - header bytes.Buffer - elements []interface{} - ownSymbolsByName map[string]*Symbol -} - -func newGeneratedFile(symbolPool *symbolPool, name string, importPath string) *GeneratedFile { - f := &GeneratedFile{ - Name: name, - ImportPath: importPath, - SkipIfEmpty: true, - symbolPool: symbolPool, - ownSymbolsByName: make(map[string]*Symbol), - } - return f -} - -// H prints a line to the header of the file. All values are converted to -// string using their default format in Go. The header appears before any -// lines added with P. Imports are inserted right after it. -func (f *GeneratedFile) H(v ...interface{}) { - for _, x := range v { - f.header.WriteString(fmt.Sprint(x)) - } - f.header.WriteByte('\n') -} - -// P prints a line to the file. Symbols imported from other files will -// be aliased automatically if necessary. Symbols owned by this file retain -// their name. All other values are converted to string using their default -// format in Go. -func (f *GeneratedFile) P(v ...interface{}) { - var buf bytes.Buffer - f.p(&buf, v...) - buf.WriteByte('\n') - f.elements = append(f.elements, buf.String()) -} - -func (f *GeneratedFile) p(buf *bytes.Buffer, v ...interface{}) { - for _, x := range v { - switch x := x.(type) { - case []interface{}: - f.p(buf, x...) - case *Symbol: - if buf.Len() > 0 { - f.elements = append(f.elements, buf.String()) - buf.Reset() - } - f.elements = append(f.elements, x) - default: - buf.WriteString(fmt.Sprint(x)) - } - } -} - -// Symbol reserves an identifier in this file. Repeated calls with the same -// name will return the same instance. If the Symbol is printed in another -// file, it is automatically imported. -func (f *GeneratedFile) Symbol(name string) *Symbol { - s, ok := f.ownSymbolsByName[name] - if !ok { - s = f.symbolPool.new(name, f.Name) - f.ownSymbolsByName[name] = s - } - return s -} - -// Import takes a name to import from a source, and reserves an identifier in -// this file. -func (f *GeneratedFile) Import(name string, from string) *Symbol { - return f.symbolPool.new(name, from) -} - -// GetName returns the name of this file which includes its path. -func (f *GeneratedFile) GetName() string { - return f.Name -} - -// IsEmpty returns true if this file contains nothing but whitespace. -// Headers - added with H() - are ignored. -func (f *GeneratedFile) IsEmpty() bool { - for _, x := range f.elements { - switch e := x.(type) { - case string: - e = strings.TrimSpace(e) - e = strings.TrimSuffix(e, "\n") - if len(e) > 0 { - return false - } - } - } - return true -} - -// GetContent returns the complete content of the file. -func (f *GeneratedFile) GetContent() string { - var buf bytes.Buffer - buf.Write(f.header.Bytes()) - var imports bytes.Buffer - symbolToIdentifier := f.processSymbols(func(typeOnly bool, from string, names map[string]string) { - x := make([]string, 0, len(names)) - for name, alias := range names { - if len(alias) > 0 { - x = append(x, name+" as "+alias) - } else { - x = append(x, name) - } - } - sort.Strings(x) - y := strings.Join(x, ", ") - if typeOnly { - _, _ = fmt.Fprintf(&imports, "import type {%s} from %q;\n", y, from) - } else { - _, _ = fmt.Fprintf(&imports, "import {%s} from %q;\n", y, from) - } - }) - buf.Write(imports.Bytes()) - if imports.Len() > 0 { - buf.WriteByte('\n') - } - for _, x := range f.elements { - switch e := x.(type) { - case string: - buf.WriteString(e) - case *Symbol: - buf.WriteString(symbolToIdentifier[e.id]) - } - } - return buf.String() -} - -func (f *GeneratedFile) processSymbols(makeImportStatement func(typeOnly bool, from string, nameToAlias map[string]string)) map[symbolID]string { - var symbolToIdentifier = make(map[symbolID]string) // identifiers to use in the output - var symbolToIsValue = make(map[symbolID]bool) // symbols that need a value import (as opposed to a type-only import) - var identifiersTaken = make(map[string]bool) // taken in this file - var foreignSymbols []*Symbol // foreign symbols need an import - - // Walk through all symbols used and populate the collections above. - for _, e := range f.elements { - if s, ok := e.(*Symbol); ok { - symbolToIdentifier[s.id] = s.Name - if !s.typeOnly { - // a symbol is only type-imported as long as all uses are type-only - symbolToIsValue[s.id] = true - } - switch s.From { - case f.ImportPath: - // always reserve the names of symbols defined in this file - identifiersTaken[s.Name] = true - default: - foreignSymbols = append(foreignSymbols, s) - } - } - } - - // Walk through all foreign symbols and make their identifiers unique. - handledSymbols := make(map[symbolID]bool) - for _, s := range foreignSymbols { - if handledSymbols[s.id] { - continue - } - handledSymbols[s.id] = true - if !identifiersTaken[s.Name] { - identifiersTaken[s.Name] = true - continue - } - var i = 1 - var alias string - for { - alias = fmt.Sprintf("%s$%d", s.Name, i) - if !identifiersTaken[alias] { - break - } - i++ - } - identifiersTaken[alias] = true - symbolToIdentifier[s.id] = alias - } - - // Group foreign symbols by their source. - type imp struct { - types map[string]string // type-only imports, name to (optional) alias - values map[string]string // value imports, name to (optional) alias - } - sourceToImport := make(map[string]*imp) - for _, s := range foreignSymbols { - i, ok := sourceToImport[s.From] - if !ok { - i = &imp{ - types: make(map[string]string), - values: make(map[string]string), - } - sourceToImport[s.From] = i - } - alias := symbolToIdentifier[s.id] - if alias == s.Name { - alias = "" - } - if symbolToIsValue[s.id] { - i.values[s.Name] = alias - } else { - i.types[s.Name] = alias - } - } - - // Make import statements. - imported := make(map[string]bool) - for _, s := range foreignSymbols { - if imported[s.From] { - continue - } - imported[s.From] = true - i := sourceToImport[s.From] - from := makeImportPathRelative(f.ImportPath, s.From) - if len(i.types) > 0 { - makeImportStatement(true, from, i.types) - } - if len(i.values) > 0 { - makeImportStatement(false, from, i.values) - } - } - - return symbolToIdentifier -} - -type symbolID uint64 - -// Symbol is an importable name, such as `MyMessage` in a file `my_message_pb.ts`. -// If the symbol is passed to the method P() of a GeneratedFile, an import -// statement is automatically added. -type Symbol struct { - Name string - From string - typeOnly bool - id symbolID -} - -// ToTypeOnly returns a variant of a Symbol that indicates that the identifier -// is only used as a type, not as a value. This is relevant in TypeScript, -// where it is preferable to use `import type {MyMessage}` for such imports, -// so that it is easier for 3rd party transpilation tooling to skip type -// imports. -func (s *Symbol) ToTypeOnly() *Symbol { - if s.typeOnly { - return s - } - return &Symbol{ - Name: s.Name, - From: s.From, - typeOnly: true, - id: s.id, - } -} - -type symbolPool struct { - c uint64 - m map[string]map[string]symbolID -} - -func (p *symbolPool) new(name string, from string) *Symbol { - if p.m == nil { - p.m = make(map[string]map[string]symbolID) - } - if _, ok := p.m[from]; !ok { - p.m[from] = make(map[string]symbolID) - } - id, ok := p.m[from][name] - if !ok { - p.c++ - id = symbolID(p.c) - p.m[from][name] = id - } - return &Symbol{ - Name: name, - From: from, - typeOnly: false, - id: id, - } -} diff --git a/private/protoplugin/generated_file_test.go b/private/protoplugin/generated_file_test.go deleted file mode 100644 index e4048162b..000000000 --- a/private/protoplugin/generated_file_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "reflect" - "testing" -) - -func TestSymbol(t *testing.T) { - symbol := &symbolPool{} - t.Run("is re-used", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - a := f.Symbol("A") - a2 := f.Symbol("A") - if a != a2 { - t.Error("expected same symbol") - } - }) - t.Run("keeps its name", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - f.P(f.Symbol("A")) - const wantContent = "A\n" - gotContent := f.GetContent() - if gotContent != wantContent { - t.Errorf("want %q, got %q", wantContent, gotContent) - } - }) -} - -func TestImport(t *testing.T) { - symbol := &symbolPool{} - t.Run("import clashes with own identifier", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - f.P( - symbol.new("A", "t2.js"), - symbol.new("A", "t.js"), - ) - assertGeneratedFileImports(t, f, generatedFileImports{ - typeOnly: false, - from: "t2.js", - names: map[string]string{"A": "A$1"}, - }) - }) - t.Run("import many names", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - f.P( - symbol.new("A", "t2.js"), - symbol.new("B", "t2.js"), - symbol.new("C", "t2.js"), - symbol.new("D", "t2.js"), - ) - assertGeneratedFileImports(t, f, generatedFileImports{ - typeOnly: false, - from: "t2.js", - names: map[string]string{"A": "", "B": "", "C": "", "D": ""}, - }) - }) - t.Run("imports clash", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - f.P( - symbol.new("A", "t2.js"), - symbol.new("A", "t3.js"), - ) - assertGeneratedFileImports(t, f, generatedFileImports{ - typeOnly: false, - from: "t2.js", - names: map[string]string{"A": ""}, - }, generatedFileImports{ - typeOnly: false, - from: "t3.js", - names: map[string]string{"A": "A$1"}, - }) - }) - t.Run("import clashes with own identifier", func(t *testing.T) { - f := newGeneratedFile(symbol, "t.js", "t.js") - f.P( - symbol.new("A", "t2.js"), - symbol.new("A", "t.js"), - ) - assertGeneratedFileImports(t, f, generatedFileImports{ - typeOnly: false, - from: "t2.js", - names: map[string]string{"A": "A$1"}, - }) - }) -} - -type generatedFileImports struct { - typeOnly bool - from string - names map[string]string -} - -func assertGeneratedFileImports(t *testing.T, f *GeneratedFile, want ...generatedFileImports) { - got := make([]generatedFileImports, 0) - f.processSymbols(func(typeOnly bool, from string, names map[string]string) { - got = append(got, generatedFileImports{typeOnly, from, names}) - }) - if len(got) != len(want) { - t.Errorf("got %d imports, want %d", len(got), len(want)) - } - for i, g := range got { - w := want[i] - if w.typeOnly != g.typeOnly { - t.Errorf("got import[%d] typeOnly %t, want %t", i, g.typeOnly, w.typeOnly) - } - if w.from != g.from { - t.Errorf("got import[%d] from %q, want %q", i, g.from, w.from) - } - if !reflect.DeepEqual(w.names, g.names) { - t.Errorf("got import[%d] names %q, want %q", i, g.names, w.names) - } - } -} diff --git a/private/protoplugin/names.go b/private/protoplugin/names.go deleted file mode 100644 index 7cd32acc8..000000000 --- a/private/protoplugin/names.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "bytes" - "path/filepath" - "strings" -) - -// escapeChar must be appended to a reserved name. -// We choose '$' because it is invalid in proto identifiers. -const escapeChar = "$" - -var ( - // reservedIdentifiers cannot be used for classes or other types, - // but _can_ be used for object properties. - reservedIdentifiers = map[string]struct{}{ - // ECMAScript 2015 keywords - "break": {}, - "case": {}, - "catch": {}, - "class": {}, - "const": {}, - "continue": {}, - "debugger": {}, - "default": {}, - "delete": {}, - "do": {}, - "else": {}, - "export": {}, - "extends": {}, - "false": {}, - "finally": {}, - "for": {}, - "function": {}, - "if": {}, - "import": {}, - "in": {}, - "instanceof": {}, - "new": {}, - "null": {}, - "return": {}, - "super": {}, - "switch": {}, - "this": {}, - "throw": {}, - "true": {}, - "try": {}, - "typeof": {}, - "var": {}, - "void": {}, - "while": {}, - "with": {}, - "yield": {}, - - // ECMAScript 2015 future reserved keywords - "enum": {}, - "implements": {}, - "interface": {}, - "let": {}, - "package": {}, - "private": {}, - "protected": {}, - "public": {}, - "static": {}, - - // Class name cannot be 'Object' when targeting ES5 with module CommonJS - "Object": {}, - - // TypeScript keywords that cannot be used for types (as opposed to variables) - "bigint": {}, - "number": {}, - "boolean": {}, - "string": {}, - "object": {}, - - // Identifiers reserved for the runtime, so we can generate legible code - "globalThis": {}, - "Uint8Array": {}, - "Partial": {}, - } - - // reservedObjectProperties are names that cannot be used for object - // properties. - reservedObjectProperties = map[string]struct{}{ - // names reserved by JavaScript - "constructor": {}, - "toString": {}, - "toJSON": {}, - "valueOf": {}, - - // names reserved by the runtime - "getType": {}, - "clone": {}, - "equals": {}, - "fromBinary": {}, - "fromJson": {}, - "fromJsonString": {}, - "toBinary": {}, - "toJson": {}, - "toJsonString": {}, - - // names reserved by the runtime for the future - "toObject": {}, - } -) - -var ( - // runtimeImportPath points to the protobuf runtime library. - runtimeImportPath = "@bufbuild/protobuf" - - // wktSourceToImportPath maps from the path of a well-known types proto - // file to the JavaScript import path for the runtime package. - wktSourceToImportPath = map[string]string{ - "google/protobuf/compiler/plugin.proto": "@bufbuild/protobuf", - "google/protobuf/any.proto": "@bufbuild/protobuf", - "google/protobuf/api.proto": "@bufbuild/protobuf", - "google/protobuf/descriptor.proto": "@bufbuild/protobuf", - "google/protobuf/duration.proto": "@bufbuild/protobuf", - "google/protobuf/empty.proto": "@bufbuild/protobuf", - "google/protobuf/field_mask.proto": "@bufbuild/protobuf", - "google/protobuf/source_context.proto": "@bufbuild/protobuf", - "google/protobuf/struct.proto": "@bufbuild/protobuf", - "google/protobuf/timestamp.proto": "@bufbuild/protobuf", - "google/protobuf/type.proto": "@bufbuild/protobuf", - "google/protobuf/wrappers.proto": "@bufbuild/protobuf", - } - - // knownExtensions are file extensions for which we automatically derive an - // import path. - knownExtensions = []string{".d.ts", ".ts", ".ts", ".js", ".mjs", ".cjs"} -) - -// makePBImportPath returns the import path for message and enum types generated -// by the type generator. -func makePBImportPath(file *File, bootstrapWkt bool) string { - // Well-known types are published with the runtime package. We usually want - // the generated code to import them from the runtime package, with the - // following exceptions: - // 1. We are bootstrapping the runtime package via the plugin option - // "bootstrap_wkt". In that case, we cannot refer to the runtime package - // itself. - // 2. We were explicitly asked to generate the well-known type. - if jsWktImportPath, isWkt := wktSourceToImportPath[file.Proto.GetName()]; isWkt && !bootstrapWkt && !file.Generate { - return jsWktImportPath - } - return "./" + file.Name + "_pb.js" -} - -// deriveImportPath returns an import path "./foo/bar_x.js" for file name -// "foo/bar_x.ts". If the file name does not have any of the known -// extensions, it is returned as is. -func deriveImportPath(filename string) string { - for _, ke := range knownExtensions { - if strings.HasSuffix(filename, ke) { - importPath := strings.TrimSuffix(filename, ke) + ".js" - if !strings.HasPrefix(importPath, "./") && !strings.HasPrefix(importPath, "../") { - importPath = "./" + importPath - } - return importPath - } - } - return filename -} - -// makeImportPathRelative makes an import path relative to the file importing -// it. For example, consider the following files: -// - foo/foo.js -// - baz.js -// If foo.js wants to import baz.js, we return ../baz.js -func makeImportPathRelative(importer string, importPath string) string { - if !strings.HasPrefix(importPath, "./") && !strings.HasPrefix(importPath, "../") { - return importPath - } - dir := filepath.Dir(importer) - rel, _ := filepath.Rel(dir, importPath) - if rel != "" { - importPath = filepath.ToSlash(rel) - if !strings.HasPrefix(importPath, "./") && !strings.HasPrefix(importPath, "../") { - importPath = "./" + importPath - } - } - return importPath -} - -func makeMessageName(message *Message) string { - name := message.protoTypeName - name = strings.TrimPrefix(name, ".") - name = strings.TrimPrefix(name, message.File.Proto.GetPackage()+".") - name = strings.ReplaceAll(name, ".", "_") - if _, reserved := reservedIdentifiers[name]; reserved { - return name + escapeChar - } - return name -} - -func makeEnumName(enum *Enum) (string, string) { - screamingSnakeCase := func(upperCamelCase string) string { - var snakeNext = false - var b strings.Builder - for i := 0; i < len(upperCamelCase); i++ { - c := upperCamelCase[i] - switch { - case 'A' <= c && c <= 'Z': - if snakeNext { - b.WriteByte('_') - snakeNext = false - } - case 'a' <= c && c <= 'z': - snakeNext = true - c -= 'a' - 'A' - case c == '_': - snakeNext = false - } - b.WriteByte(c) - } - return b.String() - } - sharedPrefix := screamingSnakeCase(enum.Proto.GetName()) + "_" - for _, v := range enum.Proto.Value { - if !strings.HasPrefix(v.GetName(), sharedPrefix) { - sharedPrefix = "" - break - } - valueName := strings.TrimPrefix(v.GetName(), sharedPrefix) - if valueName == "" { - sharedPrefix = "" - break - } - f := valueName[0] - if '0' <= f && f <= '9' { - // identifiers must not start with numbers - sharedPrefix = "" - break - } - } - name := enum.protoTypeName - name = strings.TrimPrefix(name, ".") - name = strings.TrimPrefix(name, enum.File.Proto.GetPackage()+".") - name = strings.ReplaceAll(name, ".", "_") - if _, reserved := reservedIdentifiers[name]; reserved { - name += escapeChar - } - return name, sharedPrefix -} - -func makeEnumValueName(protoName string, sharedPrefix string) string { - return strings.TrimPrefix(protoName, sharedPrefix) -} - -func makeFieldName(protoName string, inOneof bool) string { - name := protoCamelCase(protoName) - if inOneof { - return name - } - if _, reserved := reservedObjectProperties[name]; reserved { - return name + escapeChar - } - return name -} - -func makeOneofName(protoName string) string { - return makeFieldName(protoName, false) -} - -func makeServiceName(protoName string) string { - if _, reserved := reservedIdentifiers[protoName]; reserved { - return protoName + escapeChar - } - return protoName -} - -func makeMethodName(protoName string) string { - if len(protoName) == 0 { - return protoName - } - b := []byte(protoName) - return string(append(bytes.ToLower(b[:1]), b[1:]...)) -} - -// protoCamelCase converts snake_case to protoCamelCase according to the -// convention used by protoc to convert a field name to a JSON name. -func protoCamelCase(snakeCase string) string { - var capNext = false - var b strings.Builder - b.Grow(len(snakeCase)) - for i := 0; i < len(snakeCase); i++ { - c := snakeCase[i] - switch c { - case '_': - capNext = true - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - b.WriteByte(c) - capNext = false - default: - if capNext { - capNext = false - // convert lowercase to uppercase - if 'a' <= c && c <= 'z' { - c -= 'a' - 'A' - } - } - b.WriteByte(c) - } - } - return b.String() -} diff --git a/private/protoplugin/names_test.go b/private/protoplugin/names_test.go deleted file mode 100644 index 691539d3b..000000000 --- a/private/protoplugin/names_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "bytes" - "errors" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/descriptorpb" -) - -func TestMakeMethodName(t *testing.T) { - const want = "getImage" - got := makeMethodName("GetImage") - if got != want { - t.Errorf("expected %q but got %q", want, got) - } -} - -func TestDeriveImportPath(t *testing.T) { - const want = "./extra/name-clash_connectweb.js" - got := deriveImportPath("extra/name-clash_connectweb.ts") - if got != want { - t.Errorf("expected %q but got %q", want, got) - } -} - -func TestMakeImportPathRelative(t *testing.T) { - assertMakeRelativeImportPathReturns(t, "./extra/name-clash_connectweb.js", "./extra/name-clash_pb.js", "./name-clash_pb.js") -} - -func assertMakeRelativeImportPathReturns(t *testing.T, importer string, importPath string, want string) { - got := makeImportPathRelative(importer, importPath) - if got != want { - t.Errorf("expected %q but got %q with importer %q and importPath %q", want, got, importer, importPath) - } -} - -func TestProtoCamelCaseEqualsProtocJsonName(t *testing.T) { - assertProtoCamelCaseEqualsProtocJSONName(t, "FooBar") - assertProtoCamelCaseEqualsProtocJSONName(t, "foo_bar") - assertProtoCamelCaseEqualsProtocJSONName(t, "__proto__") - assertProtoCamelCaseEqualsProtocJSONName(t, "fieldname1") - assertProtoCamelCaseEqualsProtocJSONName(t, "field_name2") - assertProtoCamelCaseEqualsProtocJSONName(t, "_field_name3") - assertProtoCamelCaseEqualsProtocJSONName(t, "field__name4_") - assertProtoCamelCaseEqualsProtocJSONName(t, "field0name5") - assertProtoCamelCaseEqualsProtocJSONName(t, "field_0_name6") - assertProtoCamelCaseEqualsProtocJSONName(t, "fieldName7") - assertProtoCamelCaseEqualsProtocJSONName(t, "FieldName8") - assertProtoCamelCaseEqualsProtocJSONName(t, "field_Name9") - assertProtoCamelCaseEqualsProtocJSONName(t, "Field_Name10") - assertProtoCamelCaseEqualsProtocJSONName(t, "FIELD_NAME11") - assertProtoCamelCaseEqualsProtocJSONName(t, "FIELD_name12") - assertProtoCamelCaseEqualsProtocJSONName(t, "__field_name13") - assertProtoCamelCaseEqualsProtocJSONName(t, "__Field_name14") - assertProtoCamelCaseEqualsProtocJSONName(t, "field__name15") - assertProtoCamelCaseEqualsProtocJSONName(t, "field__Name16") - assertProtoCamelCaseEqualsProtocJSONName(t, "field_name17__") - assertProtoCamelCaseEqualsProtocJSONName(t, "Field_name18__") -} - -// assertProtoCamelCaseEqualsProtocJSONName takes the given proto field name -// and runs it through protoc to get the JSON name. -// The result is compared to our own implementation of the algorithm. -// It is important that the implementations in JS and Go match the protoc -// implementation. -func assertProtoCamelCaseEqualsProtocJSONName(t *testing.T, name string) { - got := protoCamelCase(name) - want, err := getProtocJSONName(name) - if err != nil { - if errors.Is(err, errInvalidProtoFieldName) { - return - } - t.Error(err.Error()) - return - } - if got != want { - t.Errorf("want protoCamelCase(%q) to be %q, got %q", name, want, got) - } -} - -var errInvalidProtoFieldName = errors.New("proto field name is invalid") - -// getProtocJSONName runs protoc to get the "json name" for a field -func getProtocJSONName(protoName string) (string, error) { - if strings.TrimSpace(protoName) != protoName { - return "", errInvalidProtoFieldName - } - tempDir, err := os.MkdirTemp("", "golang-protoc-workdir-*") - if err != nil { - return "", err - } - inFilename := filepath.Join(tempDir, "i.proto") - outFilename := filepath.Join(tempDir, "o") - var in bytes.Buffer - in.WriteString("syntax = \"proto3\";\n") - in.WriteString("message I {\n") - in.WriteString(fmt.Sprintf(" int32 %s = 1;\n", protoName)) - in.WriteString("}\n") - err = os.WriteFile(inFilename, in.Bytes(), 0600) - if err != nil { - return "", err - } - cmd := exec.Command("protoc", "-I", tempDir, inFilename, "--descriptor_set_out", outFilename) - var b bytes.Buffer - cmd.Stderr = &b - err = cmd.Run() - if err != nil { - stderr := b.String() - if strings.Contains(stderr, "Expected field name.") { - return "", errInvalidProtoFieldName - } - if strings.Contains(stderr, "Expected field number.") { - return "", errInvalidProtoFieldName - } - if strings.Contains(stderr, "Expected \";\".") { - return "", errInvalidProtoFieldName - } - if strings.Contains(stderr, "Missing field number.") { - return "", errInvalidProtoFieldName - } - if strings.Contains(stderr, "Invalid control characters encountered in text.") { - return "", errInvalidProtoFieldName - } - if stderr != "" { - return "", errors.New(stderr) - } - return "", err - } - out, err := os.ReadFile(outFilename) - if err != nil { - return "", err - } - fds := &descriptorpb.FileDescriptorSet{} - if err := proto.Unmarshal(out, fds); err != nil { - return "", err - } - return fds.GetFile()[0].GetMessageType()[0].GetField()[0].GetJsonName(), nil -} diff --git a/private/protoplugin/protoplugin.go b/private/protoplugin/protoplugin.go deleted file mode 100644 index 1221c1571..000000000 --- a/private/protoplugin/protoplugin.go +++ /dev/null @@ -1,1246 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -// Package protoplugin is a small framework for writing your own code -// generator plugins using protobuf-es. -package protoplugin - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "strings" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/descriptorpb" - "google.golang.org/protobuf/types/pluginpb" -) - -// ErrInvalidOption is raised when protoplugin receives an unknown option. -var ErrInvalidOption = errors.New("invalid option") - -// Options are options to a plugin. Name and Version are mandatory, and -// will be included in generated files as part of the preamble. -// ParamFunc can be used to parse arbitrary options the plugin wants to -// provide. -type Options struct { - Name string // name of this code generator - Version string // version of this code generator - ParamFunc func(key string, value string) error -} - -// Pipe reads a CodeGeneratorRequest from stdin, runs it with the provided -// plugin implementation `gen`, and writes a CodeGeneratorResponse -// to stdout. If an error occurs, an error message is written to stderr, and -// the program exits with code 1. -// This method should be called from the main function of a command that -// implements a plugin. -func (o Options) Pipe(gen func(gen *Generator) error) { - if len(os.Args) > 1 { - switch os.Args[1] { - case "-v", "--version": - _, _ = fmt.Fprintf(os.Stderr, "%s %s\n", o.Name, o.Version) - os.Exit(0) - default: - _, _ = fmt.Fprintf( - os.Stderr, - "%s: this command accepts a google.protobuf.compiler.CodeGeneratorRequest on stdin and writes a CodeGeneratorResponse to stdout\n", - o.Name, - ) - os.Exit(1) - } - return - } - if err := o.pipe(gen); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "%s: %v\n", o.Name, err) - os.Exit(1) - } -} - -func (o Options) pipe(gen func(gen *Generator) error) error { - in, err := ioutil.ReadAll(os.Stdin) - if err != nil { - return err - } - reqPb := &pluginpb.CodeGeneratorRequest{} - if err := proto.Unmarshal(in, reqPb); err != nil { - return err - } - resPb, err := o.Run(reqPb, gen) - if err != nil { - errString := err.Error() - resPb = &pluginpb.CodeGeneratorResponse{Error: &errString} - } - out, err := proto.Marshal(resPb) - if err != nil { - return err - } - if _, err := os.Stdout.Write(out); err != nil { - return err - } - return nil -} - -// Run takes a CodeGeneratorRequest, runs it through the provided plugin -// implementation `gen`, and returns a CodeGeneratorResponse - or an error -// in case the request is invalid. -// This method can be used in tests, so that the plugin does not need to -// be run through a compiler. -func (o Options) Run(request *pluginpb.CodeGeneratorRequest, gen func(gen *Generator) error) (*pluginpb.CodeGeneratorResponse, error) { - g, err := newGenerator(o, request) - if err != nil { - return nil, err - } - err = gen(g) - resPb := &pluginpb.CodeGeneratorResponse{ - SupportedFeatures: &g.SupportedFeatures, - } - if err != nil { - errString := err.Error() - resPb.Error = &errString - } - if resPb.Error == nil { - g.toResponse(resPb) - } - return resPb, nil -} - -// Generator provides all information of a CodeGeneratorRequest in a simplified -// form. -type Generator struct { - Options Options - Request *pluginpb.CodeGeneratorRequest - Files []*File - SupportedFeatures uint64 - Targets []Target - symbolPool *symbolPool - filesByPath map[string]*File - enumsByName map[string]*Enum - messagesByName map[string]*Message - servicesByName map[string]*Service - generatedFiles []*GeneratedFile - tsNoCheck bool // internal plugin option `ts_nocheck=false` removes the /* @ts-nocheck */ annotation at the top of each generated TypeScript file - bootstrapWKT bool // internal plugin option `wkt_bootstrap`; when bootstrapping well-known types, we need to generate relative import paths -} - -func newGenerator(options Options, request *pluginpb.CodeGeneratorRequest) (*Generator, error) { - g := &Generator{ - Options: options, - Request: request, - Targets: []Target{TargetJavaScript, TargetTypeDeclaration}, - symbolPool: &symbolPool{}, - filesByPath: make(map[string]*File), - enumsByName: make(map[string]*Enum), - messagesByName: make(map[string]*Message), - servicesByName: make(map[string]*Service), - tsNoCheck: true, - } - err := g.parseParameter(request.GetParameter()) - if err != nil { - return nil, err - } - filenameToGenerate := make(map[string]bool) - for _, filename := range g.Request.FileToGenerate { - filenameToGenerate[filename] = true - } - for _, protoFile := range request.ProtoFile { - f, err := g.newFile(protoFile, filenameToGenerate[protoFile.GetName()]) - if err != nil { - return nil, err - } - g.filesByPath[protoFile.GetName()] = f - g.Files = append(g.Files, f) - } - for _, file := range g.Files { - err := file.resolveReferences(g) - if err != nil { - return nil, err - } - } - for _, filename := range g.Request.FileToGenerate { - _, ok := g.filesByPath[filename] - if !ok { - return nil, fmt.Errorf("invalid request: no descriptor for file to generate: %s", filename) - } - } - return g, nil -} - -// NewGeneratedFile creates a new file to be generated. If content is added to -// the file with P(), the file is automatically included in the -// CodeGeneratorResponse returned to the protobuf compiler. -func (g *Generator) NewGeneratedFile(name string) *GeneratedFile { - f := newGeneratedFile(g.symbolPool, name, deriveImportPath(name)) - g.generatedFiles = append(g.generatedFiles, f) - return f -} - -func (g *Generator) parseParameter(parameter string) error { - if len(parameter) == 0 { - return nil - } - var err error - var key string - for _, key = range strings.Split(parameter, ",") { - var value string - if i := strings.Index(key, "="); i >= 0 { - value = key[i+1:] - key = key[0:i] - } - switch key { - case "target": - g.Targets = make([]Target, 0) - for _, rawTarget := range strings.Split(value, "+") { - switch rawTarget { - case "ts": - g.Targets = append(g.Targets, TargetTypeScript) - case "js": - g.Targets = append(g.Targets, TargetJavaScript) - case "dts": - g.Targets = append(g.Targets, TargetTypeDeclaration) - default: - return ErrInvalidOption - } - } - case "ts_nocheck": - switch value { - case "true", "1": - g.tsNoCheck = true - case "false", "0": - g.tsNoCheck = false - default: - return ErrInvalidOption - } - case "bootstrap_wkt": - switch value { - case "true", "1": - g.bootstrapWKT = true - case "false", "0": - g.bootstrapWKT = false - default: - return ErrInvalidOption - } - default: - if g.Options.ParamFunc != nil { - if err = g.Options.ParamFunc(key, value); err != nil { - break - } - continue - } - err = ErrInvalidOption - } - } - if err != nil { - return fmt.Errorf("%w %q", ErrInvalidOption, key) - } - return nil -} - -func (g *Generator) toResponse(response *pluginpb.CodeGeneratorResponse) { - for _, f := range g.generatedFiles { - name := f.GetName() - if f.SkipIfEmpty && f.IsEmpty() { - continue - } - content := f.GetContent() - fP := &pluginpb.CodeGeneratorResponse_File{ - Name: &name, - InsertionPoint: nil, - Content: &content, - GeneratedCodeInfo: nil, - } - response.File = append(response.File, fP) - } -} - -// Target represents on of the known output types. -type Target int - -const ( - TargetTypeScript Target = iota - TargetJavaScript - TargetTypeDeclaration -) - -func (l Target) String() string { - switch l { - case TargetTypeScript: - return "TypeScript" - case TargetJavaScript: - return "JavaScript" - default: - return "unknown" - } -} - -// ProtoSyntax is one of the supported syntaxes of proto files. -type ProtoSyntax int - -const ( - ProtoSyntaxUnknown ProtoSyntax = iota - ProtoSyntax2 - ProtoSyntax3 -) - -func (p ProtoSyntax) String() string { - switch p { - case ProtoSyntax2: - return "proto2" - case ProtoSyntax3: - return "proto3" - default: - return "unknown" - } -} - -// File is a protobuf source file, with several helpful fields to aid -// generating ECMAScript. -type File struct { - Proto *descriptorpb.FileDescriptorProto - Syntax ProtoSyntax - Name string // name of the file, excluding the .proto suffix - StandardImportPath string // the standard import path for the type generator (suffix _pb.js) - Preamble string // standard preamble, containing syntax comments, code generator information and package comments - RuntimeSymbols *Runtime - Enums []*Enum - Messages []*Message // excluding synthetic messages like map entries - Extensions []*Extension - Services []*Service - Deprecated bool // deprecated with the file level option "deprecated = true" - SyntaxComments CommentSet - PackageComments CommentSet - Generate bool // whether this file was requested to be generated - allMessages []*Message // including synthetic messages like map entries -} - -func (g *Generator) newFile(proto *descriptorpb.FileDescriptorProto, generate bool) (*File, error) { - f := &File{ - Proto: proto, - Name: strings.TrimSuffix(proto.GetName(), ".proto"), - Deprecated: proto.GetOptions().GetDeprecated(), - Generate: generate, - SyntaxComments: newCommentSet(proto.SourceCodeInfo, []int32{fieldNumber_FileDescriptorProto_Syntax}), - PackageComments: newCommentSet(proto.SourceCodeInfo, []int32{fieldNumber_FileDescriptorProto_Package}), - } - proto.SourceCodeInfo.GetLocation() - f.StandardImportPath = makePBImportPath(f, g.bootstrapWKT) - switch proto.GetSyntax() { - case "proto3": - f.Syntax = ProtoSyntax3 - case "": - f.Syntax = ProtoSyntax2 - default: - return nil, fmt.Errorf("unsupported syntax: %s", proto.GetSyntax()) - } - f.Preamble = makeFilePreamble( - g, - proto.GetName(), - proto.GetPackage(), - f.Syntax, - f.SyntaxComments, - f.PackageComments, - ) - f.RuntimeSymbols = newRuntime(g.symbolPool, f.Syntax, g.bootstrapWKT) - for index, x := range proto.GetEnumType() { - f.Enums = append(f.Enums, g.newEnum(x, f, index)) - } - for index, messageProto := range proto.GetMessageType() { - newMessage, err := g.newMessage(messageProto, f, index) - if err != nil { - return nil, err - } - f.allMessages = append(f.allMessages, newMessage) - if !newMessage.Proto.GetOptions().GetMapEntry() { - f.Messages = append(f.Messages, newMessage) - } - } - for index, extensionProto := range proto.GetExtension() { - newExtension, err := g.newExtension(extensionProto, f, nil, index) - if err != nil { - return nil, err - } - f.Extensions = append(f.Extensions, newExtension) - } - for index, serviceProto := range proto.GetService() { - f.Services = append(f.Services, g.newService(serviceProto, f, index)) - } - return f, nil -} - -func (f *File) String() string { - return fmt.Sprintf("file %s", f.Proto.GetName()) -} - -func (f *File) resolveReferences(gen *Generator) error { - for _, message := range f.Messages { - if err := message.resolveReferences(gen); err != nil { - return err - } - } - for _, extension := range f.Extensions { - if err := extension.resolveReferences(gen); err != nil { - return err - } - } - for _, service := range f.Services { - for _, method := range service.Methods { - if err := method.resolveReferences(gen); err != nil { - return err - } - } - } - return nil -} - -// Enum represents an enum definition. -type Enum struct { - File *File - Proto *descriptorpb.EnumDescriptorProto - TypeName string // fully qualified name, for example `foo.MyEnum` - Symbol *Symbol // importable name of this enum in ECMAScript - Values []*EnumValue - Deprecated bool // deprecated with the enum option "deprecated = true", or implicitly with the file level option - SharedPrefix string // MY_ENUM_ for `enum MyEnum {MY_ENUM_A=0; MY_ENUM_B=1;}`, or blank string - Comments CommentSet - protoTypeName string // fully qualified name with a leading dot - sourcePath []int32 -} - -func (g *Generator) newEnum(proto *descriptorpb.EnumDescriptorProto, parentMessageOrFile interface{}, indexOnParent int) *Enum { - e := &Enum{ - Proto: proto, - } - switch p := parentMessageOrFile.(type) { - case *Message: - e.protoTypeName = fmt.Sprintf("%s.%s", p.protoTypeName, proto.GetName()) - e.File = p.File - e.sourcePath = append(p.sourcePath, fieldNumber_DescriptorProto_EnumType, int32(indexOnParent)) - case *File: - if p.Proto.GetPackage() != "" { - e.protoTypeName = fmt.Sprintf(".%s.%s", p.Proto.GetPackage(), proto.GetName()) - } else { - e.protoTypeName = fmt.Sprintf(".%s", proto.GetName()) - } - e.File = p - e.sourcePath = append(e.sourcePath, fieldNumber_FileDescriptorProto_EnumType, int32(indexOnParent)) - } - e.TypeName = strings.TrimPrefix(e.protoTypeName, ".") - e.Deprecated = proto.GetOptions().GetDeprecated() || e.File.Deprecated - e.Comments = newCommentSet(e.File.Proto.SourceCodeInfo, e.sourcePath) - localName, sharedPrefix := makeEnumName(e) - e.SharedPrefix = sharedPrefix - e.Symbol = g.symbolPool.new(localName, e.File.StandardImportPath) - g.enumsByName[e.protoTypeName] = e - for index, valueProto := range proto.Value { - e.Values = append(e.Values, g.newEnumValue(valueProto, e, index)) - } - return e -} - -// FindValueByNumber finds a value by its number as defined in protobuf. -func (e *Enum) FindValueByNumber(number int32) *EnumValue { - for _, v := range e.Values { - if v.Proto.GetNumber() == number { - return v - } - } - return nil -} - -// FindValueByName finds a value by its name as defined in protobuf. -func (e *Enum) FindValueByName(name string) *EnumValue { - for _, v := range e.Values { - if v.Proto.GetName() == name { - return v - } - } - return nil -} - -// JSDoc creates a JSDoc comment block for this enum, including comments -// from the protobuf source, as well as code generator information and -// - if applicable - a deprecation tag. -func (e *Enum) JSDoc(indent string) string { - doc := newJsDocBlock() - if e.Comments.Leading != "" { - doc.add(e.Comments.Leading) - } - if e.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(e.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from %s", e)) - if e.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (e *Enum) String() string { - return fmt.Sprintf("enum %s", e.TypeName) -} - -// EnumValue represents a single value of an enum definition. -type EnumValue struct { - Proto *descriptorpb.EnumValueDescriptorProto - Parent *Enum - LocalName string - Deprecated bool // deprecated with the enum value option "deprecated = true" - Comments CommentSet -} - -func (g *Generator) newEnumValue(proto *descriptorpb.EnumValueDescriptorProto, parent *Enum, indexOnParent int) *EnumValue { - v := &EnumValue{ - Proto: proto, - Parent: parent, - LocalName: makeEnumValueName(proto.GetName(), parent.SharedPrefix), - Deprecated: proto.GetOptions().GetDeprecated(), - Comments: newCommentSet( - parent.File.Proto.SourceCodeInfo, - append(parent.sourcePath, fieldNumber_EnumDescriptorProto_Value, int32(indexOnParent)), - ), - } - return v -} - -// JSDoc creates a JSDoc comment block for this enum value, including -// comments from the protobuf source, as well as code generator information -// and - if applicable - a deprecation tag. -func (v *EnumValue) JSDoc(indent string) string { - doc := newJsDocBlock() - if v.Comments.Leading != "" { - doc.add(v.Comments.Leading) - } - if v.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(v.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from enum value: %s;", v.GetDeclarationString())) - if v.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (v *EnumValue) String() string { - return fmt.Sprintf("enum value %s.%s", v.Parent.TypeName, v.Proto.GetName()) -} - -// GetDeclarationString returns a string that matches the definition of this -// value in protobuf (but does not take custom options into account). -func (v *EnumValue) GetDeclarationString() string { - d := fmt.Sprintf("%s = %d", v.Proto.GetName(), v.Proto.GetNumber()) - if v.Proto.GetOptions().GetDeprecated() { - return d + " [deprecated = true]" - } - return d -} - -// Message represents a message definition. -type Message struct { - File *File - Proto *descriptorpb.DescriptorProto - TypeName string // fully qualified name, for example `foo.MyMessage` - Symbol *Symbol // importable name of this message in ECMAScript - Members []*Member - Fields []*Field - Oneofs []*Oneof // excluding synthetic oneofs for proto3 optional - NestedEnums []*Enum - NestedMessages []*Message // excluding synthetic messages like map entries - NestedExtensions []*Extension - Deprecated bool // deprecated with the message option "deprecated = true", or implicitly with the file level option - Comments CommentSet - allNestedMessages []*Message // including synthetic messages like map entries - allOneofs []*Oneof // including synthetic oneofs for proto3 optional - protoTypeName string // fully qualified name with a leading dot - sourcePath []int32 -} - -func (g *Generator) newMessage(proto *descriptorpb.DescriptorProto, parentMessageOrFile interface{}, indexOnParent int) (*Message, error) { - message := &Message{ - Proto: proto, - } - switch p := parentMessageOrFile.(type) { - case *Message: - message.protoTypeName = fmt.Sprintf("%s.%s", p.protoTypeName, proto.GetName()) - message.File = p.File - message.sourcePath = append(p.sourcePath, fieldNumber_DescriptorProto_NestedType, int32(indexOnParent)) - case *File: - if p.Proto.GetPackage() != "" { - message.protoTypeName = fmt.Sprintf(".%s.%s", p.Proto.GetPackage(), proto.GetName()) - } else { - message.protoTypeName = fmt.Sprintf(".%s", proto.GetName()) - } - message.File = p - message.sourcePath = append(message.sourcePath, fieldNumber_FileDescriptorProto_MessageType, int32(indexOnParent)) - } - message.TypeName = strings.TrimPrefix(message.protoTypeName, ".") - message.Symbol = g.symbolPool.new(makeMessageName(message), message.File.StandardImportPath) - message.Deprecated = proto.GetOptions().GetDeprecated() || message.File.Deprecated - message.Comments = newCommentSet(message.File.Proto.SourceCodeInfo, message.sourcePath) - g.messagesByName[message.protoTypeName] = message - for index, d := range proto.GetEnumType() { - message.NestedEnums = append(message.NestedEnums, g.newEnum(d, message, index)) - } - for index, messageProto := range proto.GetNestedType() { - newMessage, err := g.newMessage(messageProto, message, index) - if err != nil { - return nil, err - } - message.allNestedMessages = append(message.allNestedMessages, newMessage) - if !newMessage.Proto.GetOptions().GetMapEntry() { - message.NestedMessages = append(message.NestedMessages, newMessage) - } - } - for index, oneofProto := range proto.GetOneofDecl() { - message.allOneofs = append(message.allOneofs, g.newOneof(oneofProto, message, index)) - } - for index, fieldProto := range proto.GetField() { - newField, err := g.newField(fieldProto, message, index) - if err != nil { - return nil, err - } - message.Fields = append(message.Fields, newField) - } - for index, extensionProto := range proto.GetExtension() { - newExtension, err := g.newExtension(extensionProto, message.File, message, index) - if err != nil { - return nil, err - } - message.NestedExtensions = append(message.NestedExtensions, newExtension) - } - for _, field := range message.Fields { - if field.Proto.OneofIndex == nil { - continue - } - oneofIndex := field.Proto.GetOneofIndex() - if oneofIndex < 0 || oneofIndex >= int32(len(message.allOneofs)) { - return nil, fmt.Errorf("invalid request: oneof declaration index %d specified by %s not found", oneofIndex, field) - } - oneof := message.allOneofs[oneofIndex] - oneof.Fields = append(oneof.Fields, field) - if !field.Proto.GetProto3Optional() { - // ignore synthetic oneofs - field.Oneof = oneof - } - } - for _, oneof := range message.allOneofs { - if len(oneof.Fields) == 1 && oneof.Fields[0].Proto.GetProto3Optional() { - // ignore synthetic oneofs - continue - } - message.Oneofs = append(message.Oneofs, oneof) - } - return message, nil -} - -// JSDoc creates a JSDoc comment block for this message, including -// comments from the protobuf source, as well as code generator information -// and - if applicable - a deprecation tag. -func (m *Message) JSDoc(indent string) string { - doc := newJsDocBlock() - if m.Comments.Leading != "" { - doc.add(m.Comments.Leading) - } - if m.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(m.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from %s", m)) - if m.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (m *Message) String() string { - return fmt.Sprintf("message %s", strings.TrimPrefix(m.TypeName, ".")) -} - -func (m *Message) resolveReferences(gen *Generator) error { - for _, message := range m.allNestedMessages { - if err := message.resolveReferences(gen); err != nil { - return err - } - } - for _, extension := range m.NestedExtensions { - if err := extension.resolveReferences(gen); err != nil { - return err - } - } - oneofSeen := make(map[*Oneof]bool) - for _, field := range m.Fields { - if err := field.resolveReferences(gen); err != nil { - return err - } - if field.Oneof != nil { - if oneofSeen[field.Oneof] { - continue - } - oneofSeen[field.Oneof] = true - m.Members = append(m.Members, &Member{ - Kind: MemberKindOneof, - Oneof: field.Oneof, - }) - } else { - m.Members = append(m.Members, &Member{ - Kind: MemberKindField, - Field: field, - }) - } - } - return nil -} - -// MemberKind represents the possible types a member of a Message can be. -type MemberKind int - -const ( - MemberKindField MemberKind = iota - MemberKindOneof -) - -// Member is any member of a Message. -type Member struct { - Kind MemberKind - Field *Field - Oneof *Oneof -} - -// FieldKind represents the possibly categories a field belongs into. -type FieldKind int - -const ( - FieldKindScalar FieldKind = iota + 1 - FieldKindEnum - FieldKindMessage - FieldKindMap -) - -// Field represents a field of a message. -type Field struct { - Proto *descriptorpb.FieldDescriptorProto - LocalName string // name of the property on the message in ECMAScript - JSONName string // blank if the user did not specify the option json_name - Parent *Message - Oneof *Oneof // nil if not member of an oneof - Optional bool // whether the field is optional, regardless of syntax - Deprecated bool // deprecated with the field option `[deprecated = true]` - Repeated bool // a true repeated field, i.e. the user specified `repeated ...` - Packed bool // pack this repeated field? true in case of `[packed = true]` and if packed by default because of proto3 semantics - PackedByDefault bool // packed by default because of proto3 semantics? - Kind FieldKind - Scalar descriptorpb.FieldDescriptorProto_Type - Enum *Enum // type for enum fields; nil otherwise - Message *Message // type for message or group fields; nil otherwise - Map *Map // type for map fields; nil otherwise - Comments CommentSet - sourcePath []int32 -} - -func (g *Generator) newField(desc *descriptorpb.FieldDescriptorProto, parent *Message, indexOnParent int) (*Field, error) { - if desc.Extendee != nil { - return nil, fmt.Errorf("invalid request: regular field must not have a extendee") - } - f := &Field{ - Proto: desc, - LocalName: makeFieldName(desc.GetName(), desc.OneofIndex != nil), - Parent: parent, - Deprecated: desc.GetOptions().GetDeprecated(), - sourcePath: append(parent.sourcePath, fieldNumber_DescriptorProto_Field, int32(indexOnParent)), - } - f.Comments = newCommentSet(parent.File.Proto.SourceCodeInfo, f.sourcePath) - if protoCamelCase(f.Proto.GetName()) != desc.GetJsonName() { - f.JSONName = desc.GetJsonName() - } - switch f.Parent.File.Syntax { - case ProtoSyntax3: - f.Optional = f.Proto.GetProto3Optional() - case ProtoSyntax2: - f.Optional = f.Proto.OneofIndex == nil && f.Proto.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL - } - return f, nil -} - -// JSDoc creates a JSDoc comment block for this field, including comments -// from the protobuf source, as well as code generator information and - -// if applicable - a deprecation tag. -func (f *Field) JSDoc(indent string) string { - doc := newJsDocBlock() - if f.Comments.Leading != "" { - doc.add(f.Comments.Leading) - } - if f.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(f.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from field: %s;", f.GetDeclarationString())) - if f.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (f *Field) String() string { - return fmt.Sprintf("field %s.%s", f.Parent.TypeName, f.Proto.GetName()) -} - -// GetDeclarationString returns a string that matches the definition of this -// field in protobuf (but does not take custom options into account). -func (f *Field) GetDeclarationString() string { - scalarDeclarationString := func(scalarType descriptorpb.FieldDescriptorProto_Type) string { - return strings.ToLower(strings.TrimPrefix(scalarType.String(), "TYPE_")) - } - var labels, options []string - if f.Repeated { - labels = append(labels, "repeated") - } - if f.Optional { - labels = append(labels, "optional") - } - if f.Parent.File.Syntax == ProtoSyntax2 && f.Proto.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED { - labels = append(labels, "required") - } - if f.Proto.GetOptions() != nil && f.Proto.GetOptions().Packed != nil { - switch f.Proto.GetOptions().GetPacked() { - case true: - options = append(options, "packed = true") - case false: - options = append(options, "packed = false") - } - } - if f.Proto.DefaultValue != nil { - value := f.Proto.GetDefaultValue() - switch f.Proto.GetType() { - case descriptorpb.FieldDescriptorProto_TYPE_STRING, descriptorpb.FieldDescriptorProto_TYPE_BYTES: - value = `"` + strings.ReplaceAll(value, `"`, `\"`) + `"` - } - options = append(options, fmt.Sprintf("default = %s", value)) - } - if f.JSONName != "" { - options = append(options, fmt.Sprintf("json_name = %q", f.JSONName)) - } - if f.Proto.GetOptions().GetDeprecated() { - options = append(options, "deprecated = true") - } - var t string - switch f.Kind { - case FieldKindScalar: - t = scalarDeclarationString(f.Scalar) - case FieldKindEnum: - t = strings.TrimPrefix(f.Enum.protoTypeName, ".") - case FieldKindMessage: - t = strings.TrimPrefix(f.Message.protoTypeName, ".") - case FieldKindMap: - k := scalarDeclarationString(f.Map.Key) - v := "" - switch f.Map.ValueKind { - case FieldKindEnum: - v = strings.TrimPrefix(f.Map.ValueEnum.protoTypeName, ".") - case FieldKindMessage: - v = strings.TrimPrefix(f.Map.ValueMessage.protoTypeName, ".") - case FieldKindScalar: - v = scalarDeclarationString(f.Map.ValueScalar) - } - t = fmt.Sprintf("map<%s, %s>", k, v) - } - var sb strings.Builder - if len(labels) > 0 { - sb.WriteString(strings.Join(labels, " ")) - sb.WriteRune(' ') - } - sb.WriteString(fmt.Sprintf("%s %s = %d", t, f.Proto.GetName(), f.Proto.GetNumber())) - if len(options) > 0 { - sb.WriteString(" [") - sb.WriteString(strings.Join(options, ", ")) - sb.WriteRune(']') - } - return sb.String() -} - -func (f *Field) resolveReferences(gen *Generator) error { - refName := f.Proto.GetTypeName() - switch f.Proto.GetType() { - case descriptorpb.FieldDescriptorProto_TYPE_ENUM: - ref, ok := gen.enumsByName[refName] - if !ok { - return fmt.Errorf("invalid request: enum %q specified by %s not found", refName, f) - } - f.Enum = ref - f.Kind = FieldKindEnum - case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, descriptorpb.FieldDescriptorProto_TYPE_GROUP: - ref, ok := gen.messagesByName[refName] - if !ok { - return fmt.Errorf("invalid request: message %q specified by %s not found", refName, f) - } - if ref.Proto.GetOptions().GetMapEntry() { - newMap, err := gen.newMap(f) - if err != nil { - return err - } - f.Map = newMap - f.Kind = FieldKindMap - } else { - f.Message = ref - f.Kind = FieldKindMessage - } - default: - f.Kind = FieldKindScalar - f.Scalar = f.Proto.GetType() - } - if f.Proto.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED && f.Kind != FieldKindMap { - f.Repeated = true - if f.Parent.File.Syntax == ProtoSyntax3 { - switch f.Proto.GetType() { - case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE, - descriptorpb.FieldDescriptorProto_TYPE_FLOAT, - descriptorpb.FieldDescriptorProto_TYPE_INT64, - descriptorpb.FieldDescriptorProto_TYPE_UINT64, - descriptorpb.FieldDescriptorProto_TYPE_INT32, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64, - descriptorpb.FieldDescriptorProto_TYPE_FIXED32, - descriptorpb.FieldDescriptorProto_TYPE_UINT32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64, - descriptorpb.FieldDescriptorProto_TYPE_SINT32, - descriptorpb.FieldDescriptorProto_TYPE_SINT64, - descriptorpb.FieldDescriptorProto_TYPE_BOOL, - descriptorpb.FieldDescriptorProto_TYPE_ENUM: - // From the proto3 language guide: - // > In proto3, repeated fields of scalar numeric types are packed by default. - // This information is incomplete - according to the conformance tests, BOOL - // and ENUM are packed by default as well. This means only STRING and BYTES - // are not packed by default, which makes sense because they are length-delimited. - f.Packed = true - f.PackedByDefault = true - } - } - if f.Proto.GetOptions() != nil && f.Proto.GetOptions().Packed != nil { - f.Packed = f.Proto.GetOptions().GetPacked() - } - } - return nil -} - -// Map represents a map field definition. -type Map struct { - Parent *Field - Key descriptorpb.FieldDescriptorProto_Type - ValueKind FieldKind - ValueScalar descriptorpb.FieldDescriptorProto_Type - ValueEnum *Enum - ValueMessage *Message -} - -func (g *Generator) newMap(parent *Field) (*Map, error) { - refName := parent.Proto.GetTypeName() - mapEntry, ok := g.messagesByName[refName] - if !ok { - return nil, fmt.Errorf("invalid request: map entry %q specified by %s not found", refName, parent) - } - if !mapEntry.Proto.GetOptions().GetMapEntry() { - return nil, fmt.Errorf("invalid request: message %q specified by %s is not a map entry", refName, parent) - } - if len(mapEntry.Fields) != 2 { - return nil, fmt.Errorf("invalid request: map entry %q specified by %s has %d fields", refName, parent, len(mapEntry.Fields)) - } - var keyField *Field - var valueField *Field - for _, f := range mapEntry.Fields { - switch f.Proto.GetNumber() { - case 1: - keyField = f - case 2: - valueField = f - } - } - if keyField == nil { - return nil, fmt.Errorf("invalid request: map entry %q specified by %s is missing key field", refName, parent) - } - if keyField.Kind != FieldKindScalar { - return nil, fmt.Errorf("invalid request: map entry %q specified by %s has unexpected key kind %q", refName, parent, keyField.Kind) - } - switch keyField.Proto.GetType() { - case - descriptorpb.FieldDescriptorProto_TYPE_INT64, - descriptorpb.FieldDescriptorProto_TYPE_UINT64, - descriptorpb.FieldDescriptorProto_TYPE_INT32, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64, - descriptorpb.FieldDescriptorProto_TYPE_FIXED32, - descriptorpb.FieldDescriptorProto_TYPE_BOOL, - descriptorpb.FieldDescriptorProto_TYPE_STRING, - descriptorpb.FieldDescriptorProto_TYPE_UINT32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED32, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64, - descriptorpb.FieldDescriptorProto_TYPE_SINT32, - descriptorpb.FieldDescriptorProto_TYPE_SINT64: - default: - return nil, fmt.Errorf("invalid request: map entry %q specified by %s has unexpected key type %q", refName, parent, keyField.Proto.GetType()) - } - if valueField == nil { - return nil, fmt.Errorf("invalid request: map entry %q specified by %s is missing value field", refName, parent) - } - m := &Map{ - Parent: parent, - Key: keyField.Scalar, - ValueKind: valueField.Kind, - ValueScalar: valueField.Scalar, - ValueEnum: valueField.Enum, - ValueMessage: valueField.Message, - } - return m, nil -} - -// Oneof represents a oneof definition. -type Oneof struct { - Proto *descriptorpb.OneofDescriptorProto - LocalName string // name of the property on the message in ECMAScript - Parent *Message // message in which this oneof is declared - Fields []*Field // fields that are part of this oneof - Comments CommentSet - sourcePath []int32 -} - -func (g *Generator) newOneof(desc *descriptorpb.OneofDescriptorProto, parent *Message, indexOnParent int) *Oneof { - o := &Oneof{ - Proto: desc, - Parent: parent, - LocalName: makeOneofName(desc.GetName()), - sourcePath: append(parent.sourcePath, fieldNumber_DescriptorProto_OneofDecl, int32(indexOnParent)), - } - o.Comments = newCommentSet(parent.File.Proto.SourceCodeInfo, o.sourcePath) - return o -} - -// JSDoc creates a JSDoc comment block for this Oneof, including -// comments from the protobuf source, as well as code generator information -// and - if applicable - a deprecation tag. -func (o *Oneof) JSDoc(indent string) string { - doc := newJsDocBlock() - if o.Comments.Leading != "" { - doc.add(o.Comments.Leading) - } - if o.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(o.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from %s", o)) - return doc.indentedString(indent) -} - -func (o *Oneof) String() string { - return fmt.Sprintf("oneof %s.%s", o.Parent.TypeName, o.Proto.GetName()) -} - -// Extension represents an extension. -type Extension struct { - Proto *descriptorpb.FieldDescriptorProto - File *File - Parent *Message // nil if top-level extension - Extendee *Message - Enum *Enum // type for enum fields; nil otherwise - Message *Message // type for message or group fields; nil otherwise - Deprecated bool // deprecated with the field option "deprecated = true", or implicitly with the file level option - Comments CommentSet - sourcePath []int32 -} - -func (g *Generator) newExtension(desc *descriptorpb.FieldDescriptorProto, file *File, parentMessageOrNil *Message, indexOnParent int) (*Extension, error) { - if desc.Extendee == nil { - return nil, fmt.Errorf("invalid request: extension is missing extendee") - } - f := &Extension{ - Proto: desc, - Parent: parentMessageOrNil, - Deprecated: desc.GetOptions().GetDeprecated() || file.Deprecated, - } - if parentMessageOrNil == nil { - f.sourcePath = append(f.sourcePath, fieldNumber_FileDescriptorProto_Extension, int32(indexOnParent)) - } else { - f.sourcePath = append(parentMessageOrNil.sourcePath, fieldNumber_DescriptorProto_Field, int32(indexOnParent)) - } - return f, nil -} - -func (e *Extension) String() string { - return fmt.Sprintf("extension %s.%s", - strings.TrimPrefix(e.Proto.GetExtendee(), "."), - e.Proto.GetName(), - ) -} - -func (e *Extension) resolveReferences(gen *Generator) error { - if e.Proto.Extendee != nil { - typeName := e.Proto.GetExtendee() - ref, ok := gen.messagesByName[typeName] - if !ok { - return fmt.Errorf("invalid request: message %q specified by %s not found", typeName, e) - } - e.Extendee = ref - } - return nil -} - -// Service represents a service definition. -type Service struct { - File *File - Proto *descriptorpb.ServiceDescriptorProto - TypeName string // fully qualified name, for example `foo.MyService` - LocalName string // name of the service in ECMAScript, for example `MyService` - Methods []*Method - Deprecated bool // deprecated with the service option "deprecated = true", or implicitly with the file level option - protoTypeName string // fully qualified name with a leading dot - Comments CommentSet - sourcePath []int32 -} - -func (g *Generator) newService(proto *descriptorpb.ServiceDescriptorProto, parent *File, indexOnParent int) *Service { - s := &Service{ - File: parent, - Proto: proto, - protoTypeName: fmt.Sprintf("%s.%s", parent.Proto.GetPackage(), proto.GetName()), - } - s.sourcePath = append(s.sourcePath, fieldNumber_FileDescriptorProto_Service, int32(indexOnParent)) - s.Comments = newCommentSet(parent.Proto.SourceCodeInfo, s.sourcePath) - s.TypeName = strings.TrimPrefix(s.protoTypeName, ".") - s.Deprecated = proto.GetOptions().GetDeprecated() || s.File.Deprecated - s.LocalName = makeServiceName(proto.GetName()) - for index, methodProto := range proto.GetMethod() { - s.Methods = append(s.Methods, g.newMethod(methodProto, s, index)) - } - return s -} - -// JSDoc creates a JSDoc comment block for this Service, including -// comments from the protobuf source, as well as code generator information -// and - if applicable - a deprecation tag. -func (s *Service) JSDoc(indent string) string { - doc := newJsDocBlock() - if s.Comments.Leading != "" { - doc.add(s.Comments.Leading) - } - if s.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(s.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from %s", s)) - if s.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (s *Service) String() string { - return fmt.Sprintf("service %s", s.TypeName) -} - -// Method represents a method definition. -type Method struct { - Proto *descriptorpb.MethodDescriptorProto - LocalName string // name of the method in ECMAScript - Deprecated bool // deprecated with the method option "deprecated = true", or implicitly with the file level option - Parent *Service - Input *Message - Output *Message - Comments CommentSet -} - -func (g *Generator) newMethod(proto *descriptorpb.MethodDescriptorProto, parent *Service, indexOnParent int) *Method { - m := &Method{ - Proto: proto, - Parent: parent, - LocalName: makeMethodName(proto.GetName()), - Deprecated: proto.GetOptions().GetDeprecated() || parent.File.Deprecated, - Comments: newCommentSet( - parent.File.Proto.SourceCodeInfo, - append(parent.sourcePath, fieldNumber_ServiceDescriptorProto_Method, int32(indexOnParent)), - ), - } - return m -} - -func (m *Method) resolveReferences(gen *Generator) error { - name := m.Proto.GetInputType() - ref, ok := gen.messagesByName[name] - if !ok { - return fmt.Errorf("invalid request: input type %q specified by %s not found", name, m) - } - m.Input = ref - name = m.Proto.GetOutputType() - ref, ok = gen.messagesByName[name] - if !ok { - return fmt.Errorf("invalid request: output type %q specified by %s not found", name, m) - } - m.Output = ref - return nil -} - -// JSDoc creates a JSDoc comment block for this Method, including -// comments from the protobuf source, as well as code generator information -// and - if applicable - a deprecation tag. -func (m *Method) JSDoc(indent string) string { - doc := newJsDocBlock() - if m.Comments.Leading != "" { - doc.add(m.Comments.Leading) - } - if m.Comments.Trailing != "" { - if !doc.empty() { - doc.add("") - } - doc.add(m.Comments.Trailing) - } - if !doc.empty() { - doc.add("") - } - doc.add(fmt.Sprintf(" @generated from %s", m)) - if m.Deprecated { - doc.add(" @deprecated") - } - return doc.indentedString(indent) -} - -func (m *Method) String() string { - return fmt.Sprintf("rpc %s.%s", m.Parent.TypeName, m.Proto.GetName()) -} diff --git a/private/protoplugin/run_test.go b/private/protoplugin/run_test.go deleted file mode 100644 index e4f5e187d..000000000 --- a/private/protoplugin/run_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import ( - "errors" - "os" - "testing" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/descriptorpb" - "google.golang.org/protobuf/types/pluginpb" -) - -func TestRun(t *testing.T) { - t.Run("basic run", func(t *testing.T) { - req := makeCodeGeneratorRequest(t, "../../packages/protobuf-test/descriptorset.bin", "") - res, err := Options{ - Version: "0.0.1", - ParamFunc: nil, - }.Run(req, func(gen *Generator) error { - var got = len(gen.Files) - var want = len(req.ProtoFile) - if got != want { - t.Errorf("want %d files, got %d", want, got) - } - f := gen.NewGeneratedFile("x.js") - f.SkipIfEmpty = false - return nil - }) - if err != nil { - t.Errorf("unexpected err: %v", err) - return - } - if len(res.File) != 1 { - t.Errorf("unexpected files") - } - if res.Error != nil { - t.Errorf("unexpected err: %s", res.GetError()) - } - }) - t.Run("generator error is response error", func(t *testing.T) { - req := &pluginpb.CodeGeneratorRequest{} - res, err := Options{}.Run(req, func(gen *Generator) error { - return errors.New("sad") - }) - if err != nil { - t.Errorf("unexpected err: %v", err) - t.FailNow() - } - if len(res.File) != 0 { - t.Errorf("unexpected files") - } - if res.Error == nil { - t.Errorf("expected err: %s", res.GetError()) - } - if res.GetError() != "sad" { - t.Errorf("missing error. want %q got %q", "sad", res.GetError()) - } - }) - t.Run("invalid request is run error", func(t *testing.T) { - req := &pluginpb.CodeGeneratorRequest{ - FileToGenerate: []string{"a.proto"}, - } - _, err := Options{}.Run(req, func(gen *Generator) error { - return nil - }) - if err == nil { - t.FailNow() - } - const want = "invalid request: no descriptor for file to generate: a.proto" - var got = err.Error() - if got != want { - t.Errorf("want %q got %q", want, got) - } - }) -} - -func makeCodeGeneratorRequest(t *testing.T, imagePath string, parameter string, filesToGenerate ...string) *pluginpb.CodeGeneratorRequest { - imageBytes, err := os.ReadFile(imagePath) - if err != nil { - t.Error(err) - } - image := &descriptorpb.FileDescriptorSet{} - err = proto.Unmarshal(imageBytes, image) - if err != nil { - t.Error(err) - } - if len(filesToGenerate) == 0 { - for _, f := range image.GetFile() { - filesToGenerate = append(filesToGenerate, f.GetName()) - } - } - return &pluginpb.CodeGeneratorRequest{ - FileToGenerate: filesToGenerate, - Parameter: ¶meter, - ProtoFile: image.File, - CompilerVersion: nil, - } -} diff --git a/private/protoplugin/runtime.go b/private/protoplugin/runtime.go deleted file mode 100644 index 6310e48a1..000000000 --- a/private/protoplugin/runtime.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2021-2022 Buf Technologies, Inc. -// -// 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. - -package protoplugin - -import "fmt" - -// Runtime provides convenient access to exports from the runtime library. -type Runtime struct { - ProtoN *Symbol - Message *Symbol - PartialMessage *Symbol - PlainMessage *Symbol - FieldList *Symbol - MessageType *Symbol - BinaryReadOptions *Symbol - BinaryWriteOptions *Symbol - JsonReadOptions *Symbol - JsonWriteOptions *Symbol - JsonValue *Symbol - JsonObject *Symbol - ProtoInt64 *Symbol - ScalarType *Symbol - MethodKind *Symbol - MethodIdempotency *Symbol -} - -func newRuntime(symbolPool *symbolPool, syntax ProtoSyntax, bootstrapWKT bool) *Runtime { - if bootstrapWKT { - return &Runtime{ - ProtoN: symbolPool.new(syntax.String(), fmt.Sprintf("./%s.js", syntax.String())), - Message: symbolPool.new("Message", "./message.js"), - PartialMessage: symbolPool.new("PartialMessage", "./message.js").ToTypeOnly(), - PlainMessage: symbolPool.new("PlainMessage", "./message.js").ToTypeOnly(), - FieldList: symbolPool.new("FieldList", "./field-list.js").ToTypeOnly(), - MessageType: symbolPool.new("MessageType", "./message-type.js").ToTypeOnly(), - BinaryReadOptions: symbolPool.new("BinaryReadOptions", "./binary-format.js").ToTypeOnly(), - BinaryWriteOptions: symbolPool.new("BinaryWriteOptions", "./binary-format.js").ToTypeOnly(), - JsonReadOptions: symbolPool.new("JsonReadOptions", "./json-format.js").ToTypeOnly(), - JsonWriteOptions: symbolPool.new("JsonWriteOptions", "./json-format.js").ToTypeOnly(), - JsonValue: symbolPool.new("JsonValue", "./json-format.js").ToTypeOnly(), - JsonObject: symbolPool.new("JsonObject", "./json-format.js").ToTypeOnly(), - ProtoInt64: symbolPool.new("protoInt64", "./proto-int64.js"), - ScalarType: symbolPool.new("ScalarType", "./field.js"), - MethodKind: symbolPool.new("MethodKind", "./service-type.js"), - MethodIdempotency: symbolPool.new("MethodIdempotency", "./service-type.js"), - } - } - return &Runtime{ - ProtoN: symbolPool.new(syntax.String(), runtimeImportPath), - Message: symbolPool.new("Message", runtimeImportPath), - PartialMessage: symbolPool.new("PartialMessage", runtimeImportPath).ToTypeOnly(), - PlainMessage: symbolPool.new("PlainMessage", runtimeImportPath).ToTypeOnly(), - FieldList: symbolPool.new("FieldList", runtimeImportPath).ToTypeOnly(), - MessageType: symbolPool.new("MessageType", runtimeImportPath).ToTypeOnly(), - BinaryReadOptions: symbolPool.new("BinaryReadOptions", runtimeImportPath).ToTypeOnly(), - BinaryWriteOptions: symbolPool.new("BinaryWriteOptions", runtimeImportPath).ToTypeOnly(), - JsonReadOptions: symbolPool.new("JsonReadOptions", runtimeImportPath).ToTypeOnly(), - JsonWriteOptions: symbolPool.new("JsonWriteOptions", runtimeImportPath).ToTypeOnly(), - JsonValue: symbolPool.new("JsonValue", runtimeImportPath).ToTypeOnly(), - JsonObject: symbolPool.new("JsonObject", runtimeImportPath).ToTypeOnly(), - ProtoInt64: symbolPool.new("protoInt64", runtimeImportPath), - ScalarType: symbolPool.new("ScalarType", runtimeImportPath), - MethodKind: symbolPool.new("MethodKind", runtimeImportPath), - MethodIdempotency: symbolPool.new("MethodIdempotency", runtimeImportPath), - } -} diff --git a/make/scripts/set-workspace-version.js b/scripts/set-workspace-version.js similarity index 100% rename from make/scripts/set-workspace-version.js rename to scripts/set-workspace-version.js