ts-proto
.proto
파일을 강력한 관용식 파일로 변환합니다!
TS-Proto의 2.X 릴리스는 저수준 프로토 비프 직렬화를 마이그레이션하여 encode
및 decode
메소드가 유서 깊은 곳에서 사용하지만 @bufbuild/protobuf
로 노화 및 정체 된 protobufjs
패키지로 사용했습니다.
encode
및 decode
메소드 만 사용한 경우 크게 중단되지 않는 변경이어야합니다.
그러나 오래된 protobufjs
Writer
또는 Reader
클래스를 사용한 코드를 사용한 경우 새로운 @bufbuild/protobuf
클래스를 사용하려면 코드를 업데이트해야합니다.
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
@bufbuild/protobuf
로 마이그레이션하는 것이 차단제 인 경우 ts-proto
버전을 1.x
로 고정시킬 수 있습니다.
면책 조항 및 사과 : TS-Proto 2.X를 알파 릴리스로 발표하려고했지만 의미 론적 릴리스 구성을 정확하게 얻지 못하므로 TS-Proto 2.X는 적절한 알파없이 주요 릴리스로 게시되었습니다. /베타 사이클.
릴리스가 여전히 신선한 상태에서 발생하는 문제에 대해 보고서 (또는 더 나은 PR!)를 제출할 수 있다면 큰 감사를드립니다.
마이그레이션에 관한 다른 사람들을위한 팁이나 요령도 감사 할 것입니다!
TS-Proto
목차
개요
QuickStart
부프
ESM
목표
비가가
예제 유형
하이라이트
자동 배치 / N+1 예방
용법
지원되는 옵션
Nestjs 지원
시계 모드
기본 GRPC 구현
스폰서
개발
가정
TODO
하나의 핸들링
기본 값 및 비 설정된 필드
잘 알려진 유형
래퍼 유형
JSON 유형 (구조 유형)
타임 스탬프
숫자 유형
선택적 값의 현재 상태
TS-Proto는 Protobuf Schemas에서 TypeScript 유형을 생성합니다.
즉, person.proto
schema와 같은 주어진 : :
메시지 사람 {문자열 이름 = 1; }
TS-Proto는 다음과 같은 사람의 person.ts
파일을 생성합니다.
인터페이스 사람 { 이름 : String} const person = { Encode (Person) : Writer {...} Decode (Reader) : Person {...} tojson (사람) : 알 수없는 {...} Fromjson (데이터) : Person {...}}
또한 서비스에 대해 알고 있으며 서비스를위한 유형을 생성합니다.
인터페이스 수출 서비스 { 핑 (요청 : Pingrequest) : 약속 <PingResponse>;}
또한 PingService
의 클라이언트 구현을 생성합니다. 현재 TWIRP, GRPC-WEB, GRPC-JS 및 NESTJS가 지원됩니다.
npm install ts-proto
protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./simple.proto
(출력 매개 변수 이름 인 ts_proto_out
는 플러그인 이름의 접미사, 즉 --plugin=./node_modules/.bin/protoc-gen-ts_proto
매개 변수가 _out
Jeefix가됩니다. protoc
의 CLI 컨벤션 당.)
Windows에서 protoc --plugin=protoc-gen-ts_proto=".node_modules.binprotoc-gen-ts_proto.cmd" --ts_proto_out=. ./simple.proto
( #93 참조)
최신 protoc
사용하고 있는지 확인하십시오 (플랫폼의 설치 지침 참조, 즉 protoc
v 3.0.0
_opt
플래그를 지원하지 않습니다.
주어진 *.proto
유형에 대한 *.ts
소스 파일을 생성합니다.
이러한 소스 파일을 NPM 패키지에 패키지하려면 클라이언트에 배포하려면 평소와 같이 tsc
실행하여 .js
/ .d.ts
파일을 생성하고 출력을 일반 NPM 패키지로 배포하십시오.
BUF를 사용하는 경우 PASS strategy: all
buf.gen.yaml
파일 (DOCS)에 있습니다.
버전 : v1plugins : -이름 : tsout : ../gen/tsstrategy : allpath : ../node_modules/ts-proto/protoc-gen-ts_proto
buf push
관련없는 .proto
파일을 읽지 않도록하려면 buf.yaml
그렇게 구성하십시오.
빌드 : 제외 : [node_modules]
BUF 레지스트리에 게시 된 공식 플러그인을 사용할 수도 있습니다.
버전 : v1plugins : -플러그인 : buf.build/community/stephenh-tsprotoout : ../gen/tsopt : - outputservices = ... - useexacttypes = ...
esModuleInterop
또는 ESM 환경에서 실행중인 최신 TS 설정을 사용하는 경우 ts_proto_opt
S를 통과해야합니다.
esModuleInterop=true
tsconfig.json
에서 esModuleInterop
사용하는 경우
ESM 환경에서 생성 된 TS-Proto 코드를 실행하는 경우 importSuffix=.js
ts-proto
생성하는 코드 측면에서 일반적인 목표는 다음과 같습니다.
관용식/ES6 유형
ts-proto
Google/Java-esque JS Code of protoc
또는 "make .d.ts
파일 *.js
댓글"접근 방식의 깨끗한 휴식입니다 protobufjs
(기술적으로 protobufjs/minimal
패키지는 실제로 읽기/쓰기 바이트에 사용됩니다.)
TypeScript 우선 출력
클래스를 통해 인터페이스
가능한 한, 유형은 단지 인터페이스 일 뿐이므로 일반 해시/데이터 구조와 같은 메시지로 작업 할 수 있습니다.
CodeGen *.proto
-to- *.ts
워크 플로, 현재 런타임 반사/동적 .proto
파일의로드 만 지원합니다.
TS-Proto는 기본적인 RPC 프레임 워크가 아닙니다. 대신, 그것은 스위스-무아 나이프 (많은 구성 옵션에서 목격 한 바와 같이)에 더 가깝습니다. 이는 당신이 원하는 RPC 프레임 워크를 정확히 구축 할 수 있습니다 (즉, 회사의 protobuf 생태계와 가장 잘 통합되는 것이 더 좋든 나쁘 든 , Protobuf RPC는 여전히 다소 단편화 된 생태계입니다).
TS-Proto 위에 구축 된 기본 RPC 프레임 워크를 원한다면 몇 가지 예가 있습니다.
yfgpc
starpc
(잠재적 인 기고자의 경우, 다른 프레임 워크/미니 프레임 워크 또는 블로그 게시물/튜토리얼을 개발하는 경우 ts-proto
사용에 대해 기꺼이 링크 할 수 있습니다.)
또한 google.api.http
기반 Google Cloud API의 클라이언트를 지원하지 않습니다. PR을 제출하려면 #948을 참조하십시오.
생성 된 유형은 "단지 데이터"입니다.
인터페이스 내보내기 간단한 { 이름 : 문자열; 나이 : 숫자; 생성된다 : 날짜 | 한정되지 않은; 어린이 : 어린이 | 한정되지 않은; 상태 : Stateenum; 손자 : 자녀 []; 동전 : 숫자 [];}
encode
/ decode
팩토리 방법과 함께 :
내보내기 const simple = { Create (BaseObject? : DeepPartial <simple>) : Simple {...}, Encode (메시지 : Simple, Writer : Writer = Writer.create ()) : Writer {...}, Decode (Reader : Reader, Length? : Number) : Simple {...}, Fromjson (Object : Any) : Simple {...}, frompartial (Object : DeepPartial <simple>) : Simple {...}, tojson (메시지 : simple) : 알 수없는 {...},};
이를 통해 다음과 같은 관용 TS/JS 사용량을 허용합니다.
const bytes = simple.encode ({name : ..., age : ... ..., ...}). finish (); const simple = simple.decode (reader.create (bytes)); const {name, age } = 단순;
클래스를 만들거나 올바른 getters/setter를 호출하지 않고 다른 레이어로/로 변환 할 때 통합이 극적으로 완화 될 수 있습니다.
"선택적인 유형을 돌려주세요"에 대한 가난한 사람의 시도
표준 프로토 비프 래퍼 유형 (예 : google.protobuf.StringValue
)은 선택적 값, 즉 string | undefined
것은 프리미티브의 경우 Protobuf 유형 시스템에 선택적 유형을 가지고 있음을 의미합니다.
( 업데이트 : TS-Proto는 이제 Proto3 optional
키워드도 지원합니다.)
타임 스탬프는 Date
로 매핑됩니다
( useDate
매개 변수로 구성 가능합니다.)
fromJSON
/ toJSON
protobufjs
와 달리 Proto3 Canonical JSON 인코딩 형식 (예 : 타임 스탬프는 ISO 스트링)을 사용합니다.
ObjectIds는 mongodb.ObjectId
로 매핑 될 수 있습니다
( useMongoObjectId
매개 변수로 구성 가능합니다.)
(참고 : 이것은 현재 TWIRP 클라이언트가 지원합니다.)
SQL 애플리케이션의 N+1 문제와 유사한 TS-Proto의 클라이언트를 사용하여 백엔드 마이크로 서비스를 호출하는 경우, 마이크로 서비스 클라이언트가 (개별 요청을 제공 할 때) 여러 개의 별도의 RPC 요청을 실수로 트리거하는 것이 쉽습니다. "Book 1", "Get Book 2", "Get Book 3"은 실제로 "Get Books [1, 2, 3]"(백엔드가 배치 지향적 인 RPC 방법을 지원한다고 가정 함)로 배치되어야합니다.
TS-Proto는이 문제를 도울 수 있으며 본질적으로 개인의 "책 구입"호출을 배치 된 "책"통화로 자동 배치합니다.
TS-Proto를 위해서는 다음의 배치 컨벤션을 통해 서비스의 RPC 방법을 구현해야합니다.
Batch<OperationName>
Batch<OperationName>
입력 유형에는 단일 반복 필드가 있습니다 (즉, repeated string ids = 1
)
Batch<OperationName>
출력 유형은 다음과 같습니다.
출력 순서가 입력 ids
순서와 동일한 경우 단일 반복 필드 (예 : repeated Foo foos = 1
)
출력에 대한 입력 맵 (예 : map<string, Entity> entities = 1;
)
TS-Proto 가이 패턴의 메소드를 인식하면 클라이언트에 대해 <OperationName>
의 "비 배치"버전을 자동으로 생성합니다. IE client.Get<OperationName>
은 단일 ID를 사용하여 단일 결과를 반환합니다.
이것은 클라이언트 코드에 개별 Get<OperationName>
호출을 얻을 수 있다는 환상을 제공하지만 (클라이언트의 비즈니스 로직을 구현할 때 일반적으로 바람직/쉽게) TS-Proto가 제공하는 실제 구현은 Batch<OperationName>
만들게됩니다. 백엔드 서비스에 호출.
또한 모든 클라이언트 메소드를 제공하는 useContext=true
빌드 타임 매개 변수를 활성화해야합니다. 모든 ctx
메소드는 TS-Proto Cache/Resolve Request-Scoped Dataloaders를 제공하는 getDataLoaders
메소드를 사용하여 모든 클라이언트 메소드를 제공합니다. 탐지/플러싱 동작.
예제/자세한 내용은 batching.proto
파일 및 관련 테스트를 참조하십시오.
그러나 순 효과는 TS-Proto가 클라이언트 통화에 SQL- / ORM 스타일 N+1 예방을 제공 할 수 있다는 것입니다. 이는 특히 대용량 / 대량의 프론트 엔드 게이트웨이를 호출하는 백엔드 마이크로 서비스와 같은 대량 / 고정적 구현에서 중요 할 수 있습니다. .
ts-proto
는 protoc
플러그인이므로 (프로젝트에서 직접 또는 Mono-Repo Schema 파이프 라인, 즉 Ibotta와 같은 가능성이 높음) : :
package.json
에 ts-proto
추가하십시오
npm install
실행하여 다운로드하십시오
다음과 같은 plugin
매개 변수로 protoc
호출하십시오.
protoc -plugin = node_modules/tsproto/protoc-gen-ts_proto ./batching.proto -i.
ts-proto
Protobuf-gradle-Plugin을 사용하여 Gradle로 호출 할 수 있습니다.
protobuf { 플러그인 {//`ts`는 미사용 플러그인 이름 (예 :`tsproto'ts { Path = 'Path/to/Plugin'} } //이 섹션은 플러그인 옵션을 제공하는 경우에만 필요합니다. all (). 각 {task-> task.plugins {// 플러그인 ID 선언 된 abovets {{ 옵션 'foo = bar'} } } } }
생성 된 코드는 Gradle 빌드 디렉토리에 배치됩니다.
--ts_proto_opt=globalThisPolyfill=true
사용하면 TS-Proto에는 GlobalThis 용 PolyFill이 포함됩니다.
기본값은 false
으로, 즉 globalThis
사용할 수 있다고 가정합니다.
--ts_proto_opt=context=true
사용하면 서비스에는 이동식 ctx
매개 변수가 있으며, 이는 추적/로깅 등에 유용합니다. 성능 이유로 인해 Node의 async_hooks
API를 사용하지 않는 경우.
--ts_proto_opt=forceLong=long
에서는 64 비트 숫자가 모두 Long
인스턴스 (긴 라이브러리 사용)로 구문 분석됩니다.
--ts_proto_opt=forceLong=string
에서는 64 비트 숫자가 모두 문자열로 출력됩니다.
--ts_proto_opt=forceLong=bigint
사용하면 64 비트 숫자가 모두 BigInt
s로 출력됩니다. 이 옵션은 여전히 long
라이브러리를 사용하여 protobuf.js
내에서 내부적으로 인코딩/디코딩하지만 TS-Proto 생성 코드에서 BigInt
S로 변환합니다.
기본 동작은 forceLong=number
이며, 이는 내부적으로 long
라이브러리를 사용하여 와이어의 값을 인코딩/디코딩하기 위해 여전히 util.Long = Long
line이 표시되지만 long
값을 number
로 변환합니다. 자동으로. 이 변환을 수행하는 동안 64 비트 값이 number
로 올바르게 저장 될 수있는 것보다 큰 경우 런타임 오류가 발생합니다.
--ts_proto_opt=useJsTypeOverride
사용하면 필드에 지정된 FieldOption.jstype으로 64 비트 숫자가 출력됩니다. 이것은 제공된 forceLong
옵션보다 우선합니다.
--ts_proto_opt=esModuleInterop=true
esModuleInterop
준수하기 위해 출력을 변경합니다.
구체적으로 Long
수입은 import Long from 'long'
import * as Long from 'long'
가져 오기로 생성됩니다.
--ts_proto_opt=env=node
또는 browser
또는 both
사용하면 TS-Proto는 출력에 환경 별 가정을 만듭니다. 이것은 both
의 기본값으로 환경 별 가정을 만들지 않습니다.
node
사용하면 일반적으로 Buffer
사용하는 노드 생태계와 쉽게 통합 할 수 있도록 Uint8Array
에서 Buffer
로 bytes
유형을 변경합니다.
현재 browser
" node
아님"이외의 특정 동작이 없습니다. 아마도 곧/어느 시점에있을 것입니다.
--ts_proto_opt=useOptionals=messages
(메시지 필드의 경우) 또는 --ts_proto_opt=useOptionals=all
field: Message | undefined
메시지 및 스칼라 필드의 경우), 필드는 선택적 키로 선언됩니다 field?: Message
field: Message | undefined
.
ts-proto 기본적으로 useOptionals=none
때문에 :
오타 예방의 경우 옵션 필드는 추가 필드가 메시지에 쉽게 빠져 나올 수 있습니다 (정확한 유형을 얻을 때까지).
인터페이스 somemessage { FirstName : 문자열; lastName : String;} // typoconst data = {FirstName : "a", lastTyp : "b"}; // useOptionals = none, 이것은 올바르게 컴파일하지 못합니다. `lastname이 선택 사항이라면, 메시지가 전혀 없습니다 : somemessage = {... data};
일관된 API의 경우 SomeMessage.lastName
이 선택적인 lastName?
, 독자는 두 가지 빈 조건을 확인해야합니다. a) lastName
undefined
입니다 (B/C는 메모리에서 생성되고 왼쪽으로 남아 있음) 또는 b)는 lastName
빈 문자열입니다 (b/c는 와이어에서 SomeMessage
읽습니다. Proto3 사양, lastName
빈 문자열로 초기화)?
적절한 초기화를 보장하기 위해 나중에 SomeMessage.middleInitial
이 추가되지만 옵션 middleInitial?
, 당신은 생산 코드에 많은 통화 사이트가있을 수 있으며, 이제 유효한 SomeMessage
만들기 위해 middleInitial
통과 해야 하지만 그렇지는 않습니다.
따라서 오타 예방, 독자 불일치 및 올바른 초기화 사이에서 TS-Proto는 "가장 안전한"옵션으로 사용 useOptionals=none
사용하는 것이 좋습니다.
이 접근법은 작가/제작자가 모든 필드를 설정해야하므로 ( fromPartial
와 create
이 문제를 해결하기위한 것이지만) 선택 사항을 갖고 싶다면 useOptionals=messages
또는 useOptionals=all
설정할 수 있습니다.
( useOptional
에 대한 토론은이 문제 와이 문제를 참조하십시오.)
메시지를 초기화 할 때 오타를 방지합니다
독자에게 가장 일관된 API를 제공합니다
생산 메시지가 모든 필드로 올바르게 초기화되도록합니다.
--ts_proto_opt=exportCommonSymbols=false
with with with DeepPartial
및 protobufPackage
와 같은 유틸리티 유형 d export
않습니다 d.
이를 통해 생성 된 출력의 배럴 가져 오기, 즉 import * from ./foo
import * from ./bar
사용할 수 있습니다.
여러 *.proto
파일에 사용 된 동일한 메시지 이름이있는 경우에도 여전히 가져 오기 충돌이 발생합니다.
--ts_proto_opt=oneof=unions
에서는 oneof
필드가 ADT로 생성됩니다.
"하나의 핸들링"섹션을 참조하십시오.
--ts_proto_opt=unrecognizedEnumName=<NAME>
Enums는 unrecognizedEnumValue
옵션의 값이 포함 된 키 <NAME>
포함합니다.
UNRECOGNIZED
기본값.
--ts_proto_opt=unrecognizedEnumValue=<NUMBER>
Enums는 <NUMBER>
의 값을 가진 unrecognizedEnumName
옵션 옵션에서 제공하는 키를 포함합니다.
기본값은 -1
입니다.
--ts_proto_opt=unrecognizedEnum=false
enum에는 unrecognizedEnumName
열거 키와 인식 할 수없는 unrecognizedEnumValue
값이 포함되어 있지 않습니다.
--ts_proto_opt=removeEnumPrefix=true
생성 열거는 멤버에서 열거 이름을 제거합니다.
FooBar.FOO_BAR_BAZ = "FOO_BAR_BAZ"
FooBar.BAZ = "FOO_BAR_BAZ"
생성합니다.
--ts_proto_opt=lowerCaseServiceMethods=true
사용하면 서비스 메소드의 메소드 이름이 낮아지고 Camel-Case, 즉 service.findFoo
가 service.FindFoo
.
--ts_proto_opt=snakeToCamel=false
사용하면 메시지 키와 toJSON
/ fromJSON
메소드 모두에서 필드는 뱀 케이스를 유지합니다.
snakeToCamel
또한 _
텔리밍 문자열 목록으로 설정할 수 있습니다 (쉼표는 깃발이 구분 된 깃발로 예약되어 있음), 즉 --ts_proto_opt=snakeToCamel=keys_json
, keys
포함하여 메시지 키를 카멜 케이스로 만들고 json
포함하여 JSON 키를 포함시킬 수 있습니다. 낙타 케이스.
빈 문자열 (예 : snakeToCamel=
)은 모두 메시지 키와 JSON
키를 뱀 케이스로 유지합니다 ( snakeToCamel=false
와 동일).
json_name
속성을 사용하려면 json
사용해야합니다.
기본 동작은 keys_json
입니다. 즉, 둘 다 낙타 케이스가되고, json_name
설정되면 사용됩니다.
--ts_proto_opt=outputEncodeMethods=false
사용하여 Message.encode
및 Message.decode
"유형 만"을 원한다면 유용합니다.
--ts_proto_opt=outputJsonMethods=false
사용하여 JSON- 코딩 된 데이터로 작업하기위한 Message.fromJSON
및 Message.toJSON
메소드는 출력되지 않습니다.
"유형 만"을 원한다면 유용합니다.
--ts_proto_opt=outputJsonMethods=to-only
및 --ts_proto_opt=outputJsonMethods=from-only
the Message.toJSON
과 Message.fromJSON
메소드를 내보낼 수 있습니다.
이것은 TS-Proto를 사용하여 encode
하거나 decode
것이 아니라 두 가지 모두를 위해 유용합니다.
--ts_proto_opt=outputPartialMethods=false
, Message.fromPartial
and Message.create
부분적으로 형성된 객체/객체 리터럴을 수락하는 메소드가 출력되지 않습니다.
--ts_proto_opt=stringEnums=true
사용하면 생성 된 열거 유형은 int 기반 대신 문자열 기반입니다.
"유형 만"을 원하고 열거를 문자열로 직렬화하도록 구성된 GRPC REST 게이트웨이를 사용하는 경우 유용합니다.
( outputEncodeMethods=false
필요합니다.)
--ts_proto_opt=outputClientImpl=false
사용하면 클라이언트 측면을 구현하는 FooServiceClientImpl
구현 (예 : grpc-web
의 다음 옵션 참조) RPC 인터페이스가 출력되지 않습니다.
--ts_proto_opt=outputClientImpl=grpc-web
사용하면 클라이언트 구현 (예 : FooServiceClientImpl
은 런타임에 @improbable-eng/grpc-web 라이브러리를 사용하여 grpc 메시지를 grpc-web 백엔드로 보냅니다.
(이것은 GRPC-WEB 런타임 만 사용하여 생성 된 코드를 사용할 필요가 없습니다. 즉, TS-Proto 출력은 ts-protoc-gen
출력을 대체합니다.)
@improbable-eng/grpc-web
추가하고 프로젝트의 package.json
으로 전송해야합니다. 작업 예제는 integration/grpc-web
디렉토리를 참조하십시오. Grpc-Web-Devtools와 통합하려면 #504도 참조하십시오.
--ts_proto_opt=returnObservable=true
사용하면 Promise<T>
대신 서비스 메소드의 반환 유형을 Observable<T>
할 수 있습니다.
--ts_proto_opt=addGrpcMetadata=true
사용하면 서비스 메소드의 마지막 인수는 GRPC Metadata
유형에 수락되며, 여기에는 통화와 함께 추가 정보가 포함되어 있습니다 (즉, 액세스 토큰 등).
( nestJs=true
필요합니다.)
--ts_proto_opt=addNestjsRestParameter=true
사용하면 서비스 메소드의 마지막 인수는 유형의 REST 매개 변수가됩니다. 이렇게하면 NestJS에서 일반적으로 사용할 수있는 맞춤형 데코레이터를 사용할 수 있습니다.
( nestJs=true
필요합니다.)
--ts_proto_opt=nestJs=true
사용하면 기본값이 Nestjs Protobuf 구현의 클라이언트 측 및 서버 측에서 사용할 수있는 Nestjs Protobuf 친화적 인 유형 및 서비스 인터페이스를 생성하도록 변경됩니다. 자세한 정보 및 구현 예는 Nestjs Readme를 참조하십시오.
구체적으로 outputEncodeMethods
, outputJsonMethods
및 outputClientImpl
모두 false가되며, lowerCaseServiceMethods
참이되고 outputServices
무시됩니다.
addGrpcMetadata
, addNestjsRestParameter
및 returnObservable
은 여전히 거짓입니다.
--ts_proto_opt=useDate=false
사용하여 google.protobuf.Timestamp
유형의 필드는 생성 된 유형의 유형 Date
에 매핑되지 않습니다. 자세한 내용은 타임 스탬프를 참조하십시오.
--ts_proto_opt=useMongoObjectId=true
사용하여, 객체 라드라는 유형의 필드는 메시지가 필드에 구성되도록 구성되어 mongodb.ObjectId
이라는 값이라는 값이 맵핑됩니다. 이를 위해서는 프로젝트가 MongoDB NPM 패키지를 설치해야합니다. 자세한 내용은 ObjectId를 참조하십시오.
--ts_proto_opt=annotateFilesWithVersion=false
사용하면 생성 된 파일에는 파일을 생성하는 데 사용되는 protoc
및 ts-proto
버전이 포함되어 있지 않습니다. 이 옵션은 일반적으로 파일이 사용 된 버전을 나열하도록 true
로 설정됩니다.
--ts_proto_opt=outputSchema=true
사용하면 나중에 다른 코드 생성기에서 사용할 수있는 메타 유형이 생성됩니다.
--ts_proto_opt=outputSchema=no-file-descriptor
사용하면 메타 유형이 생성되지만 생성 된 스키마에 파일 디스크립터를 포함하지 않습니다. 생성 된 스키마의 크기를 최소화하려는 경우 유용합니다.
--ts_proto_opt=outputSchema=const
사용하면 메타 타이핑이 as const
생성되어 모든 속성에 유형-안전 액세스를 허용합니다. ( satisfies
연산자를 사용하기 때문에 TypeScript 4.9 이상에서만 작동합니다). 생성 된 스키마에 파일 디스크립터를 포함시키지 않으려면 no-file-descriptor
옵션 ( outputSchema=const,outputSchema=no-file-descriptor
)과 결합 할 수 있습니다.
--ts_proto_opt=outputTypeAnnotations=true
사용하면 각 메시지에는 완전히 자격이있는 이름이 포함 된 $type
필드가 제공됩니다. interface
선언에서 --ts_proto_opt=outputTypeAnnotations=static-only
사용하여 인터페이스 정의에서 선택적 특성을 만들기 위해 interface
선언 또는 --ts_proto_opt=outputTypeAnnotations=optional
할 수 있습니다. 후자의 옵션은 서버의 응답에서 런타임 유형에 $type
필드를 사용하려는 경우 유용 할 수 있습니다.
--ts_proto_opt=outputTypeRegistry=true
사용하면 완전히 자격이있는 이름으로 메시지 유형을 해결하는 데 사용할 수있는 유형 레지스트리가 생성됩니다. 또한 각 메시지에는 완전히 자격이있는 이름이 포함 된 $type
필드가 제공됩니다.
--ts_proto_opt=outputServices=grpc-js
사용하면 TS-Proto가 GRPC-JS 형식의 서비스 정의 및 서버 / 클라이언트 스터브를 출력합니다.
--ts_proto_opt=outputServices=generic-definitions
통해 TS-Proto는 일반 (프레임 워크-공연) 서비스 정의를 출력합니다. 이러한 정의에는 요청 및 응답 유형에 대한 링크와 응답 유형이있는 각 방법에 대한 설명자가 포함되어있어 런타임에 서버 및 클라이언트 스터브를 생성 할 수 있으며 컴파일 시간에 강력한 유형을 생성 할 수 있습니다. 이 접근법을 사용하는 라이브러리의 예는 grpc입니다.
--ts_proto_opt=outputServices=nice-grpc
사용하면 ts-proto가 witch-grpc의 서버 및 클라이언트 스터브를 출력합니다. 이것은 일반적인 정의와 함께 사용해야합니다. 즉, outputServices=nice-grpc,outputServices=generic-definitions
의 두 가지 옵션을 지정해야합니다.
--ts_proto_opt=metadataType=Foo@./some-file
, ts-proto는 일반적인 서비스 정의에 일반 (프레임 워크-공제) 메타 데이터 필드를 추가합니다.
--ts_proto_opt=outputServices=generic-definitions,outputServices=default
, ts-proto는 일반적인 정의와 인터페이스를 모두 출력합니다. 이것은 인터페이스에 의존하고 싶지만 런타임에 반사 기능이있는 경우에도 유용합니다.
--ts_proto_opt=outputServices=false
또는 =none
으로 ts-proto는 서비스 정의를 출력하지 않습니다.
--ts_proto_opt=rpcBeforeRequest=true
사용하여 TS-Proto는 Signature beforeRequest(service: string, message: string, request: <RequestType>)
와 함께 RPC 인터페이스 정의에 함수 정의를 추가합니다. 또한 outputServices=default
자동으로 설정합니다. 각 서비스의 방법은 요청을 수행하기 전에 beforeRequest
호출합니다.
--ts_proto_opt=rpcAfterResponse=true
사용하면 ts-proto는 다음 afterResponse(service: string, message: string, response: <ResponseType>)
같은 RPC 인터페이스 정의에 함수 정의를 추가합니다. 또한 outputServices=default
자동으로 설정합니다. 서비스의 각 방법은 응답을 반환하기 전에 afterResponse
호출합니다.
--ts_proto_opt=rpcErrorHandler=true
사용하면 TS-Proto는 서명을 사용하여 RPC 인터페이스 정의에 함수 정의를 추가합니다 handleError(service: string, message: string, error: Error)
. 또한 outputServices=default
자동으로 설정합니다.
--ts_proto_opt=useAbortSignal=true
사용하면 생성 된 서비스는 RPC 호출을 취소하기 위해 AbortSignal
수락합니다.
--ts_proto_opt=useAsyncIterable=true
사용하면 생성 된 서비스는 Observable
대신 AsyncIterable
사용을 사용합니다.
--ts_proto_opt=emitImportedFiles=false
사용하여 TS-Proto는이 protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto my_message.proto google/protobuf/duration.proto
같은 protoc
에 파일을 추가하지 않는 한 google/protobuf/*
파일을 방출하지 않습니다. protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto my_message.proto google/protobuf/duration.proto
--ts_proto_opt=fileSuffix=<SUFFIX>
사용하면 TS-Proto가 지정된 접미사를 사용하여 생성 된 파일을 방출합니다. fileSuffix=.pb
있는 helloworld.proto
파일은 helloworld.pb.ts
로 생성됩니다. 이것은 다른 Protoc 플러그인의 일반적인 동작이며 생성 된 모든 파일을 신속하게 지구하는 방법을 제공합니다.
--ts_proto_opt=importSuffix=<SUFFIX>
사용하면 TS-Proto는 지정된 접미사를 사용하여 파일 가져 오기를 방출합니다. fileSuffix=.js
가있는 helloworld.ts
의 가져 오기 import "helloworld.js"
생성합니다. 기본값은 파일 확장자없이 가져 오는 것입니다. TypeScript 4.7.x 이상으로 지원됩니다.
--ts_proto_opt=enumsAsLiterals=true
사용하면 생성 된 열거 유형은 as const
와 함께 열렬한 물체가됩니다.
--ts_proto_opt=useExactTypes=false
사용하면 fromPartial
생성 된 생성 및 create
메소드는 정확한 유형을 사용하지 않습니다.
기본 동작은 useExactTypes=true
이며, 이는 fromPartial
만들고 인수에 대한 정확한 유형을 create
TypeScript가 알 수없는 속성을 거부하도록합니다.
--ts_proto_opt=unknownFields=true
사용하면 모든 알 수없는 필드가 버퍼의 배열로 구문 분석되고 출력됩니다.
--ts_proto_opt=onlyTypes=true
사용하면 유형 만 방출되고 long
protobufjs/minimal
의 수입은 제외됩니다.
이것은 outputJsonMethods=false,outputEncodeMethods=false,outputClientImpl=false,nestJs=false
설정하는 것과 동일합니다
--ts_proto_opt=usePrototypeForDefaults=true
사용하면 생성 된 코드는 Object.create
사용하여 새 개체를 랩핑합니다.
이를 통해 코드는 기본값이 적용된 시점을 감지하기 위해 HAZZER 검사를 수행 할 수 있습니다. 이는 PROTO3의 와이어에 기본값을 넣지 않는 동작으로 인해 일반적으로 PROTO2 메시지와 상호 작용하는 데 유용합니다.
활성화되면 기본값이 프로토 타입에서 상속되므로 코드는 Object.keys () 포함 ( "somefield")를 사용하여 일부 필드가 실제로 디코딩되었는지 여부를 감지 할 수 있습니다.
표시된 바와 같이, 이는 Object.keys에 세트 별 필드가 포함되어 있지 않으므로 메시지 키를 일반적인 방식으로 반복하는 코드가있는 경우 프로토 타입에서 상속 된 키를 반복해야합니다.
--ts_proto_opt=useJsonName=true
사용하면 메시지 필드 이름 대신 Protofiles에 정의 된 json_name
사용됩니다.
--ts_proto_opt=useJsonWireFormat=true
사용하면 생성 된 코드는 protobuf 메시지의 JSON 표현을 반영합니다.
onlyTypes=true
. useDate=string
및 stringEnums=true
의미합니다. 이 옵션은 JSON으로 직렬화 된 Marshalling/Unmarshalling Protobuf 메시지와 직접 사용할 수있는 유형을 생성하는 것입니다. grpc 게이트웨이가 스칼라 값에 대한 기본값을 보내는 데 사용할 필요가 없으므로 useOptionals=all
설정할 수도 있습니다.
--ts_proto_opt=useNumericEnumForJson=true
사용하면 JSON 변환기 ( toJSON
)는 열거 값을 문자열 문자가 아닌 int로 인코딩합니다.
--ts_proto_opt=initializeFieldsAsUndefined=false
사용하면 생성 된 기본 인스턴스에서 모든 옵션 필드 초기화기가 생략됩니다.
--ts_proto_opt=disableProto2Optionals=true
사용하면 Proto2 파일의 모든 선택 필드가 선택 사항으로 설정되지 않습니다. 이 플래그는 주로 TS-Proto의 PROTO2 파일의 유산 처리를 보존하고 변경 사항을 깨지 않도록하기위한 것이므로 결과적으로 앞으로 나아가는 것이 아닙니다.
--ts_proto_opt=disableProto2DefaultValues=true
사용하면 기본값을 지정하는 Proto2 파일의 모든 필드는 실제로 해당 기본값을 사용하지 않습니다. 이 플래그는 주로 TS-Proto의 PROTO2 파일의 유산 처리를 보존하고 변경 사항을 깨지 않도록하기위한 것이므로 결과적으로 앞으로 나아가는 것이 아닙니다.
--ts_proto_opt=Mgoogle/protobuf/empty.proto=./google3/protobuf/empty
, ( 'm'은 protoc-gen-go와 유사한 'importmapping'을 의미 함), ./google/protobuf/empty.ts
에 대한 생성 된 코드 가져 오기 경로 ./google/protobuf/empty.ts
재정의 값을 반영합니다.
Mfoo/bar.proto=@myorg/some-lib
foo/bar.proto
가져 오기를 import ... from '@myorg/some-lib'
가져옵니다.
Mfoo/bar.proto=./some/local/lib
foo/bar.proto
imports를 import ... from './some/local/lib'
맵핑합니다.
Mfoo/bar.proto=some-modules/some-lib
foo/bar.proto
import를 import ... from 'some-module/some-lib'
가져옵니다.
참고 : 용도가 축적되므로 --ts_proto_opt=M... --ts_proto_opt=M...
(매핑 당 하나의 ts_proto_opt
) 형태로 여러 값이 예상됩니다.
참고 : 매핑 된 가져 오기와 일치하는 프로토 파일은 생성되지 않습니다 .
--ts_proto_opt=useMapType=true
사용하면 protobuf map<key_type, value_type>
Map<key_type, value_type>
가됩니다.
기본 동작은 useMapType=false
이며 {[key: key_type]: value_type}
와 같은 key-value 쌍이있는 protobuf map<key_type, value_type
코드를 생성합니다.
--ts_proto_opt=useReadonlyTypes=true
사용하면 생성 된 유형은 TypeScript의 readonly
수정자를 사용하여 불변으로 선언됩니다.
--ts_proto_opt=useSnakeTypeName=false
사용하여 유형에서 뱀 케이싱을 제거합니다.
예제 protobuf
메시지 상자 {메시지 요소 {메시지 이미지 {enum indignment {왼쪽 = 1; 중심 = 2; 오른쪽 = 3; } } } }
기본적으로 이것은 Box_Element_Image_Alignment
의 유형을 생성하는 활성화되어 있습니다. 이 옵션을 비활성화함으로써 생성 된 유형은 BoxElementImageAlignment
입니다.
--ts_proto_opt=outputExtensions=true
with with with with 생성 코드에는 proto2 확장자가 포함됩니다.
확장자 Encode/Decode 메소드는 outputEncodeMethods
옵션을 준수하며, unknownFields=true
인 경우 확장 가능한 메시지에 대해 setExtension
및 getExtension
메소드가 생성되며 outputEncodeMethods
에 대해서도 outextension = encode, getextension = decode)를 준수합니다.
--ts_proto_opt=outputIndex=true
사용하면 프로토 패키지 네임 스페이스를 기반으로 인덱스 파일이 생성됩니다.
이것은 공통 기호의 이름 충돌을 피하기 위해 exportCommonSymbols
비활성화합니다.
--ts_proto_opt=emitDefaultValues=json-methods
사용하면 생성 된 Tojson 메소드는 0
과 ""
스칼라를 JSON 필드로 방출합니다.
--ts_proto_opt=comments=false
사용하면 프로토 파일에서 생성 된 코드로 댓글이 복사되지 않습니다.
--ts_proto_opt=bigIntLiteral=false
사용하면 생성 된 코드는 bigint 리터럴에 0n
대신 BigInt("0")
사용합니다. "대상"컴파일러 옵션이 "ES2020"보다 오래된 것으로 설정된 경우 Bigint Literals는 TypeScript별로 지원되지 않습니다.
--ts_proto_opt=useNullAsOptional=true
사용하면 undefined
값이 null
로 변환되며 .proto
파일에서 optional
레이블을 사용하면 필드에 undefined
유형이 있습니다. 예를 들어:
--ts_proto_opt=typePrefix=MyPrefix
사용하면 생성 된 인터페이스, 열거 및 공장은 이름에 MyPrefix
의 접두사를 갖습니다.
--ts_proto_opt=typeSuffix=MySuffix
사용하면 생성 된 인터페이스, 열거 및 공장의 이름에 MySuffix
의 접미사가 있습니다.
메시지 profileInfo {int32 id = 1; 문자열 bio = 2; 문자열 폰 = 3; } 메시지 부서 {int32 id = 1; 문자열 이름 = 2; } 메시지 사용자 {int32 id = 1; String username = 2;/* profileInfo는 typeScript에서 선택 사항이되며 유형은 profileInfo | 널 | 정의되지 않은 것은 프로필에 값을 제공하고 싶지 않은 경우에 필요합니다. */선택적 프로파일 info profile = 3;/* 부서는 부서 유형 또는 null 만 허용하므로 값을 사용할 수없는 경우 NULL을 전달해야 함을 의미합니다. */부서 부서 = 4; }
생성 된 인터페이스는 다음과 같습니다.
내보내기 인터페이스 profireinfo { ID : 번호; 바이오 : 문자열; 전화 : 문자열;} 내보내기 인터페이스 부서 { ID : 번호; 이름 : String;} 내보내기 인터페이스 사용자 { ID : 번호; 사용자 이름 : 문자열; 프로파일? : 프로파일 인치 | 널 | 한정되지 않은; // 이것을 확인하십시오 부서 : 부서 | 널; // 이거 확인}
--ts_proto_opt=noDefaultsForOptionals=true
사용하면 protobuf 사양에 따라 undefined
원시 값이 기본적으로 기본적으로 표시되지 않습니다. 또한 표준 동작과 달리 필드가 표준 기본값으로 설정되면 와이어 위로 전송되고 정의되지 않은 값과 구별 될 수 있도록 인코딩 됩니다 . 예를 들어 메시지가 부울 값을 설정하지 않으면 일반적으로 정의되지 않은 것과 다른 false
으로 기본적으로 기본적으로 표시됩니다.
이 옵션을 사용하면 라이브러리가 Square/Block에서 유지 관리 및 사용되는 와이어 구현과 호환되는 방식으로 작동 할 수 있습니다. 참고 :이 옵션은이 옵션을 사용하여 Wire 또는 TS-Proto를 사용하여 생성 된 다른 클라이언트/서버 코드와 함께 사용해야합니다.
우리는 Nestjs와 함께 일할 수있는 좋은 방법이 있습니다. ts-proto
컨트롤러, 클라이언트를위한 interfaces
및 decorators
생성합니다. 자세한 내용은 Nestjs Readme를 참조하십시오.
프로토 파일의 모든 변경에서 ts-proto
실행하려면 Chokidar-Cli와 같은 도구를 사용하여 package.json
에서 스크립트로 사용해야합니다.
"proto : generate": "protoc -ts_proto_out = ./<Proto_path>/<Proto_name>.proto -ts_proto_opt = esmoduleInterop = true", "프로토 :": "Chokidar"**/*. proto " - C "NPM 실행 프로토 : 생성" ""
ts-proto
는 RPC 프레임 워크 Agnostic입니다. 데이터 소스를 오가는 방법은 귀하에게 달려 있습니다. 생성 된 클라이언트 구현은 모두 rpc
매개 변수를 기대하며,이 유형은 다음과 같이 정의됩니다.
인터페이스 rpc { 요청 (서비스 : 문자열, 메소드 : 문자열, 데이터 : uint8array) : 약속 <uint8array>;}
GRPC로 작업하는 경우 간단한 구현이 다음과 같습니다.
const conn = 새로운 grpc.client ( "Localhost : 8765", grpc.credentials.createinsecure ()); type rpcimpl = (service : String, method : string, data : uint8array) => 약속 <UINT8ARRAY>; const sendRequest : rpcimpl = (서비스, 메소드, 데이터) => { // 기존 GRPC에서 요청 경로는 모양이 보입니다 // "package.names.servicename/methodname", // 그러한 문자열을 구성합니다 const path =`/$ {service}/$ {method}`; 새로운 약속을 반환합니다 ((Resolve, Reject) => {// MakeUnaryRequest 콜백으로 결과 (및 오류)를 전송합니다. (err) {return Reject (err)} resolve (res);}; 함수 통과 (Argument : onity) {return argument;} // functionsconn.makeUnaryRequest (경로, PassHrough, PassHrough, Data. , resultCallback); });}; const rpc : rpc = {request : sendRequest};
후원자에게 kudos :
NGROK는 TS-Proto의 초기 GRPC-WEB 지원에 자금을 지원했습니다.
회사에 대한 TS-PROTO 사용자 정의 또는 우선 순위 지원이 필요한 경우 이메일을 통해 저를 핑하여 저에게 핑을 할 수 있습니다.
이 섹션에서는 TS-Proto에 직접 기여하는 방법에 대해 설명합니다. 즉, protoc
에서 ts-proto
실행하거나 생성 된 TypeScript를 사용하는 것이 필요하지 않습니다.
요구 사항
도커
yarn
npm install -g yarn
설정
아래 명령은 Docker가 설치되었다고 가정합니다. OS X를 사용하는 경우 Coreutils를 설치하고 brew install coreutils
.
최신 코드는 저장소를 확인하십시오.
yarn install
실행하여 종속성을 설치하십시오.
yarn build:test
.
이것은 다음 명령을 실행합니다.
proto2ts
integration/**/*.proto
파일에서 .ts
파일을 생성하기 위해 ts-proto
실행합니다.
proto2pbjs
- 호환성 테스트를 위해 pbjs
사용하여 참조 구현을 생성합니다.
yarn test
실행하십시오
워크 플로
사용 사례에 대한 통합 테스트를 추가/업데이트하십시오
당신은 또한 yarn watch
계속할 수 있으며, "옳은 일을해야합니다".
필요한 ts_proto_opt
매개 변수와 함께 새로운 integration/your-new-test/parameters.txt
만듭니다
최소 integration/your-new-test/your-new-test.proto
생성. Proto Schema 사용 케이스를 재현하십시오.
사용 사례에 충분히 가까운 기존 integration/*
테스트를 찾으십시오. 예를 들어 ts_proto_opt
parameters.txt
있습니다.
새로운 통합 테스트를 작성하는 경우 :
your-new-test.proto
또는 기존 integration/*.proto
파일을 변경 한 후 yarn proto2bin
실행하십시오.
생성 된 코드가 컴파일하는 것만 큼 사소한 경우에도 integration/your-new-test/some-test.ts
단위 테스트 추가/업데이트
ts-proto
코드 생성 로직 수정 :
또는 yarn proto2ts your-new-test
다시 yarn watch
떠나는 것은 "옳은 일을해야합니다"
가장 중요한 논리는 src/main.ts에서 찾을 수 있습니다.
src/*.ts
파일을 변경 한 후에는 yarn proto2ts
실행하여 모든 통합 테스트를 다시 코드로 연결하십시오.
yarn test
실행하여 변경 사항을 확인하여 모든 기존 테스트를 통과하십시오.
홍보를 저지르고 제출하십시오
때때로 생성 된 코드를 확인하는 것이 눈살을 찌푸 리지만 TS-Proto의 주요 작업이 코드를 생성하는 것이면 PRS의 CodeGen Diff가 도움이됩니다.
yarn format
실행하여 TypeScript 파일을 포맷하십시오.
git git 모든 *.proto
, *.bin
및 *.ts
파일을 integration/your-new-test
에 git add
하십시오.
프로젝트에서 테스트
yarn build
수동으로 실행하는 한 yarn add ts-proto@./path/to/ts-proto
실행하여 자체 프로젝트에서 로컬 TS-Proto 변경 사항을 테스트 할 수 있습니다.
Dockerized protoc
이 저장소에는 Docker-Compose.yml로 구성된 Dockerized 버전의 protoc
버전이 포함되어 있습니다.
알려진 버전의 protoc
로 플러그인을 수동으로 호출하려는 경우 유용 할 수 있습니다.
용법:
# protoc alias를 쉘에 포함시킵니다. aliases.sh# 평소와 같이 protoc을 실행하십시오. TS-Proto 디렉토리는 /ts-proto.protoc -plugin =/ts-proto/protoc-gen-ts_proto에서 사용할 수 있습니다. 플러그인 경로를 지정하는 ts-protoc alias를 사용하십시오 .tsprotoc -ts_proto_out =./output -i =./protos ./protoc/* .proto
모든 경로는 호스트의 현재 작업 디렉토리 내의 상대 경로 여야합니다. ../
허용되지 않습니다
Docker 컨테이너 내에서 프로젝트 루트의 절대 경로는 /ts-proto
입니다.
컨테이너는 현재 작업 디렉토리를 /host
로 장착하고 작업 디렉토리로 설정합니다.
aliases.sh
가 소스되면 모든 폴더에서 protoc
명령을 사용할 수 있습니다.
TS/ES6 모듈 이름은 프로토 패키지입니다
fromJSON
/ toJSON
의 스트링 기반 지속 시간 인코딩 지원
oneof=unions-value
기본 동작을 2.0으로 만드십시오
아마도 2.0에서 forceLong
기본값을 변경하고 기본적으로 forceLong=long
으로 변경해야합니다.
esModuleInterop=true
2.0의 기본값으로 만드십시오
기본적으로 TS-Proto는 메시지에서 oneof
필드를 "평평하게"모델링합니다.
메시지 foo {oneof aled_field {String field_a = 1; 문자열 field_b = 2; } }
FIELD_A Foo
field_a: string | undefined;
및 field_b: string | undefined
.
이 출력을 사용하면 if object.field_a
확인해야합니다. if object.field_b
확인하고 하나를 설정하면 다른 하나를 설정하지 않아야합니다.
대신 oneof=unions-value
옵션을 사용하는 것이 좋습니다.이 옵션은 출력을 대수 데이터 유형으로 변경하여 다음과 같습니다.
인터페이스 YourMessage { 두 필드? : {$ case : "field_a"; 값 : 문자열} | {$ case : "Field_B"; 값 : String};}
이렇게하면 한 번에 단일 값을 가질 수있는 eitherField
필드에 값이 저장되기 때문에 한 번에 field_a
또는 field_b
"Set"중 하나만 자동으로 시행됩니다.
( eitherField
는 Protobuf의 Oneof 옵션 인 B/C oneof
입니다. "최대 한 필드"가 설정되었으며 필드 중 하나가 설정되어야 한다는 의미는 아닙니다.)
TS-Proto의 현재 예정되지 않은 2.x 릴리스에서 oneof=unions-value
기본 동작이됩니다.
oneof=unions
옵션도 있습니다.이 옵션은 각 옵션에 필드 이름이 포함 된 노조를 생성합니다.
인터페이스 YourMessage { 두 필드? : {$ case : "field_a"; Field_a : String} | {$ case : "Field_B"; Field_B : String};}
여러 옵션을 처리하기 위해 코드 및 유형을 작성하기가 어려울 수 있으므로 더 이상 권장되지 않습니다.
다음 도우미 유형은 oneof=unions
에서 생성 된 유형으로 쉽게 작업 할 수 있지만 oneof=unions-value
사용하는 경우 일반적으로 필요하지 않습니다.
/** oneof 필드에서 모든 케이스 이름을 추출합니다. */type OneOfCases <t> = t extends {$ case : ul u extends string}? u : 절대;/** Oneof 필드에서 모든 값 유형의 결합을 추출합니다*/type oneofvalues <t> = t 확장 {$ case : ult u extends string; [키 : 문자열] : 알 수없는}? t [u] : 절대;/** 필드 이름*/type oneofcase <t, k는 oneofcases <t >> = t extends를 확장합니다. $ CASE : K; [키 : 문자열] : 알 수없는;} ? 티 : never;/** oneof 필드에서 특정 유형의 값 유형을 추출합니다*/type oneofvalue <t, k는 OneOfcases <t >> = t actends를 확장합니다. $ CASE : Unfer u Extends k; [키 : 문자열] : 알 수없는;} ? t [u] : 절대;
비교를 위해 oneof=unions-value
의 등가 :
/** oneof 필드에서 모든 케이스 이름을 추출합니다. */type oneofcases <t> = t [ '$ case'];/** Oneof 필드에서 모든 값 유형의 결합을 추출합니다*/type oneofvalues <t> = t [ 'value'];/** Extracts 필드 이름 */type oneofcase <t, k는 oneofcases를 확장합니다 <t >> = t extends { $ CASE : K; [키 : 문자열] : 알 수없는;} ? 티 : never;/** oneof 필드에서 특정 유형의 값 유형을 추출합니다*/type oneofvalue <t, k는 OneOfcases <t >> = t actends를 확장합니다. $ CASE : Unfer u Extends k; 가치 : 알 수없는;} ? t [u] : 절대;
Core Protobuf (및 ts-proto
)에서는 기본값과 동일 하거나 동일한 값이 전선을 통해 전송되지 않습니다.
예를 들어, 메시지의 기본값은 undefined
. 원시 유형은 자연스러운 기본값을 취합니다. 예를 들어 string
은 ''
, number
는 0
등입니다.
Protobuf는 원시 필드가 구식 에이전트가 생략하더라도 항상 값을 갖기 때문에 앞으로의 호환성을 가능하게하기 때문에이 동작을 선택/시행합니다.
이것은 양호하지만 ts-proto
필드에서는 기본 및 미지의 값이 구별 될 수 없다는 것을 의미합니다. 기본적으로 Protobuf의 작동 방식입니다.
SET/UNSET를 감지 할 수있는 원시 필드가 필요한 경우 래퍼 유형을 참조하십시오.
Encode / Decode
ts-proto
Protobuf 규칙을 따르고 디코딩 할 때 Unsets 필드에 대한 기본값을 항상 반환하면서 이진 형식으로 직렬화 될 때 출력에서 생략합니다.
구문 = "proto3"; message foo {문자열 bar = 1; }
protobufbytes; // 이것은 protobuf binary formatfoo.decode (protobufbytes)에서 빈 푸 객체라고 가정합니다. // => {bar : ''}
foo.encode ({bar : ""}); // => {}, 비어있는 foo 객체를 Protobuf 이진 형식으로 씁니다.
Fromjson / Tojson
JSON을 읽으면 기본값도 초기화됩니다. 발신자는 UNSET 필드를 생략하거나 기본값으로 설정할 수 있으므로 fromJSON
사용하여 입력을 정상화하십시오.
foo.fromjson ({}); // => {bar : ''} foo.fromjson ({bar : ""}); // => {bar : ''} foo.fromjson ({bar : "baz"}); // => {bar : 'baz'}
JSON을 작성할 때 ts-proto
UNSET 필드 및 필드를 기본값으로 설정하여 메시지를 정규화합니다.
foo.tojson ({}); // => {} foo.tojson ({bar : undefined}); // => {} foo.tojson ({bar : ""}); // => {} - 참고 : 기본값을 생략합니다. // => {bar : 'baz'}
Protobuf에는 "잘 알려진 유형"이라는 몇 가지 사전 정의 된 메시지 정의가 제공됩니다. 그들의 해석은 protobuf 사양에 의해 정의되며 라이브러리는 이러한 메시지를 대상 언어의 해당 기본 유형으로 변환해야합니다.
ts-proto
현재 이러한 메시지를 해당 기본 유형으로 자동 변환합니다.
google.protobuf.boolvalue ⇆ boolean
google.protobuf.bytesvalue ⇆ Uint8Array
google.protobuf.doublevalue ⇆ number
google.protobuf.fieldmask ⇆ string[]
google.protobuf.floatValue ⇆ number
google.protobuf.int32value ⇆ number
google.protobuf.int64value ⇆ number
google.protobuf.listvalue ⇆ any[]
google.protobuf.uint32value ⇆ number
google.protobuf.uint64value ⇆ number
google.protobuf.stringValue ⇆ string
google.protobuf.value ⇆ any
(예 : number | string | boolean | null | array | object
)
google.protobuf.struct ⇆ { [key: string]: any }
래퍼 유형은 단일 원시 필드가 포함 된 메시지이며 import "google/protobuf/wrappers.proto"
.proto
파일로 가져올 수 있습니다.
이 메시지는 메시지 이므로 기본값이 undefined
래퍼 유형을 사용할 때 미지의 프리미티브를 기본값과 구별 할 수 있습니다. ts-proto
이 필드를 <primitive> | undefined
로 생성합니다 <primitive> | undefined
.
예를 들어:
// protobufsyntax = "proto3"; import "google/protobuf/rappers.proto"; 메시지 examplemessage {google.protobuf.stringValue name = 1; }
// typeScriptInterface exemplemessage { 이름 : 문자열 | 한정되지 않은;}
메시지를 인코딩 할 때 원시 값은 해당 래퍼 유형으로 다시 변환됩니다.
examplemessage.encode ({이름 : "foo"}); // => {이름 : {value : 'foo'}}, 이진에서
Tojson을 호출 할 때 JSON에서 래퍼 유형이 관용적이기 때문에 값은 변환되지 않습니다.
examplemessage.tojson ({이름 : "foo"}); // => {이름 : 'foo'}
JSON은 유형을 미리 알 수없는 값을 포함 할 수 있기 때문에 Protobuf의 언어와 유형은 충분하지 않습니다. 이러한 이유로 Protobuf는 임의의 JSON 값을 나타내는 몇 가지 추가 유형을 제공합니다.
이를 구조물 유형이라고하며 import "google/protobuf/struct.proto"
.proto
파일로 가져올 수 있습니다.
google.protobuf.value any
이것은 가장 일반적인 유형이며 JSON 값을 나타낼 수 있습니다 (예 : number | string | boolean | null | array | object
).
google.protobuf.listvalue ⇆ any[]
JSON 배열을 나타냅니다
google.protobuf.struct ⇆ { [key: string]: any }
JSON 객체를 나타냅니다
ts-proto
이러한 구조물 유형과 해당 JSON 유형 사이에서 앞뒤로 자동 변환합니다.
예:
// protobufsyntax = "proto3"; import "Google/protobuf/struct.proto"; 메시지 examplemessage {google.protobuf.value ally = 1; }
// typeScriptInterface exemplemessage { 무엇이든 : 모든 | 한정되지 않은;}
메시지에 포함 된 JSON 값을 인코딩하면 구조물 유형으로 변환합니다.
emablemessage.encode ({ally : {name : "hello"}});/* protobuf binary 형식으로 인코딩 된 다음 구조를 출력합니다. value = value {stringValue = "hello"}]}}}}}*/examplemessage.encode ({ally : true});/*는 protobuf binary 형식으로 인코딩 된 다음 구조를 출력합니다 : {value {boolvalue = true}} */
google.protobuf.Timestamp
의 표현은 useDate
플래그에서 구성 할 수 있습니다. useJsonTimestamp
플래그는 useDate
경우 false
일 때 정밀도를 제어합니다.
Protobuf 잘 알려진 유형 | Default/ useDate=true | useDate=false | useDate=string | useDate=string-nano |
---|---|---|---|---|
google.protobuf.Timestamp | Date | { seconds: number, nanos: number } | string | string |
useDate=false
및 useJsonTimestamp=raw
타임 스탬프를 사용하는 경우 { seconds: number, nanos: number }
로 표시되지만 나노 초 정밀도가 있습니다.
useDate=string-nano
timestamp를 사용하는 경우 나노초 정밀 1970-01-01T14:27:59.987654321Z
가진 ISO 문자열로 표시되며 전환을 위해 나노 날짜 라이브러리에 의존합니다. 프로젝트에 설치해야합니다.
숫자는 기본적으로 일반 JavaScript number
로 가정됩니다.
int64
number
보다 크거나 작은 값을 가질 수 있기 때문에 int32
및 float
와 같은 프로토 비프 유형에 적합하지만 int64
와 같은 64 비트 유형은 JavaScript의 number
유형으로 표현할 수 없습니다.
TS-Proto의 기본 구성 ( forceLong=number
)은 여전히 64 비트 필드의 number
사용한 다음 값 (런타임에서)이 숫자보다 큰 경우 오류를 던지는 것입니다 Number.MAX_SAFE_INTEGER
.
64 비트 / 하이 MAX_SAFE_INTEGER
값을 사용할 것으로 예상되는 경우 긴 NPM 패키지를 사용하여 64 비트 값의 전체 범위를 지원하는 TS-Proto forceLong
옵션을 사용할 수 있습니다.
Protobuf 번호 유형은 forceLong
Config 옵션을 기반으로 JavaScript 유형에 맵을 표시합니다.
protobuf 수 유형 | 기본/ forceLong=number | forceLong=long | forceLong=string |
---|---|---|---|
더블 | 숫자 | 숫자 | 숫자 |
뜨다 | 숫자 | 숫자 | 숫자 |
int32 | 숫자 | 숫자 | 숫자 |
int64 | 숫자* | 긴 | 끈 |
UINT32 | 숫자 | 숫자 | 숫자 |
UINT64 | 숫자* | 서명되지 않은 길다 | 끈 |
SINT32 | 숫자 | 숫자 | 숫자 |
SINT64 | 숫자* | 긴 | 끈 |
고정 32 | 숫자 | 숫자 | 숫자 |
고정 64 | 숫자* | 서명되지 않은 길다 | 끈 |
sfixed32 | 숫자 | 숫자 | 숫자 |
sfixed64 | 숫자* | 긴 | 끈 |
여기서 (*)는 런타임에 오류를 던질 수 있음을 나타냅니다.
필수 프리미티브 : as-is, 즉 string name = 1
사용하십시오.
옵션 프리미티브 : 래퍼 유형을 사용합니다. 즉, StringValue name = 1
.
필수 메시지 : 사용할 수 없습니다
선택적 메시지 : as-is, 즉 SubMessage message = 1
사용합니다.