Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[gRPC] @typespec/protobuf #636

Merged
merged 60 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
1bffa05
gRPC: initial commit moving from demo to public repo
witemple-msft Jun 14, 2022
b8af153
Added a README
witemple-msft Jun 14, 2022
df8b76b
remove copied changelogs
witemple-msft Jun 14, 2022
5c3f3dc
added fresh changelog.json
witemple-msft Jun 14, 2022
18b76c0
Some cleanup, removed synthetic models
witemple-msft Jun 23, 2022
88b3a6f
WIP testing system
witemple-msft Jun 23, 2022
59a7c5c
Recorded a test
witemple-msft Jun 23, 2022
70a7415
Fixed bug bypassing effective type calculation.
witemple-msft Jun 23, 2022
186494f
Made 'simple' even simpler.
witemple-msft Jun 23, 2022
f0aa1ba
Added test for inferring message names from context
witemple-msft Jun 23, 2022
afeb49f
Supported output message name inference and refactored unreachable ty…
witemple-msft Jun 23, 2022
b604254
Unleaked discriminated union tags.
witemple-msft Jun 23, 2022
375e447
Updated some documentation.
witemple-msft Jun 23, 2022
4e7d047
Capitalize method names, remove space between method name and input t…
witemple-msft Jun 23, 2022
ba8da03
Tweaked proto header
witemple-msft Jun 23, 2022
792cf87
Extracted writing reservations into own function
witemple-msft Jun 23, 2022
3c0c181
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Jun 23, 2022
f51d3bb
Taught the expectation system to look for diagnostics.
witemple-msft Jun 23, 2022
91943e4
Check for namespace collisions.
witemple-msft Jun 23, 2022
ac1b639
Fixed simple-error test
witemple-msft Jun 23, 2022
24e5729
Re-recorded a simple test.
witemple-msft Oct 3, 2022
661fb90
Updated several facets to work with new cadl updates.
witemple-msft Oct 14, 2022
be92801
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Nov 30, 2022
b287c03
Renamed grpc -> protobuf, improved handling of many protobuf features
witemple-msft Dec 2, 2022
97d6ff6
Implement cross-package references
witemple-msft Dec 2, 2022
0ec1bca
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Dec 2, 2022
55397bb
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Jan 23, 2023
cb041e1
Reworked a bunch of docs issues and diagnostics.
witemple-msft Feb 17, 2023
88e3179
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Feb 17, 2023
fb1083e
Lazy initialize scalars map
witemple-msft Mar 8, 2023
c3c9a66
Some doc updates
witemple-msft Mar 14, 2023
c6919fa
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Mar 14, 2023
f0f6e00
Removed protoc output
witemple-msft Mar 14, 2023
3e73c42
Renamed tests to .tsp
witemple-msft Mar 14, 2023
166cda9
Updated diagnostics and some documentation
witemple-msft Mar 15, 2023
6d696a4
Updated entrypoint from typespecMain to tspMain
witemple-msft Mar 16, 2023
cdf59a6
Updated docs
witemple-msft Mar 16, 2023
8dcd5f0
Lint/spell fixes
witemple-msft Mar 16, 2023
5eb3f08
Updated enum error messages
witemple-msft Mar 16, 2023
b8123cc
Improved namespace handling
witemple-msft Mar 16, 2023
1a51df9
Reject anonymous models in messages
witemple-msft Mar 16, 2023
8fcaa82
Removed TODOs
witemple-msft Mar 16, 2023
a4caf3e
Fixed test harness on windows
witemple-msft Mar 16, 2023
9963298
addressbook scenario
witemple-msft Mar 16, 2023
39b43c1
Several small updates
witemple-msft Mar 27, 2023
9fbde4e
Ignored .protoc-out integration folder
witemple-msft Mar 27, 2023
890489a
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Mar 27, 2023
7ec412a
Updated a few documentation entries
witemple-msft Apr 24, 2023
55bab13
Import from fs rather than import fs
witemple-msft Apr 24, 2023
43dfbfa
Increased resilience to failed scalar resolutions.
witemple-msft Apr 24, 2023
4b9da2d
Support derived scalars by traversing the scalar inheritance links.
witemple-msft Apr 24, 2023
10551b2
Add protobuf as website dependency
witemple-msft Apr 24, 2023
3c0a5e8
Merge remote-tracking branch 'upstream/main' into grpc/draft
witemple-msft Apr 24, 2023
ab00e49
Just don't support unions for now
witemple-msft Apr 24, 2023
34eb9e7
Better handling of intrinsic types
witemple-msft Apr 24, 2023
db0ce3b
Added a note about onValidate
witemple-msft Apr 24, 2023
7803dd5
Added a note about syntax target functions
witemple-msft Apr 24, 2023
fa954f8
Move a symbol
witemple-msft Apr 24, 2023
9320334
Add a readme warning.
witemple-msft Apr 24, 2023
cb556f3
Merge branch 'main' into grpc/draft
witemple-msft Apr 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ words:
- globby
- inmemory
- instanceid
- interner
- intrinsics
- jsyaml
- keyer
- lzutf
- msbuild
- MSRC
Expand All @@ -49,6 +51,7 @@ words:
- rushx
- safeint
- segmentof
- sfixed
- strs
- TRYIT
- TSES
Expand All @@ -64,8 +67,6 @@ words:
- vswhere
- westus
- xplat
- keyer
- interner
ignorePaths:
- "**/node_modules/**"
- "**/dist/**"
Expand Down
233 changes: 233 additions & 0 deletions docs/standard-library/protobuf/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
---
title: Overview
---

# The Protobuf Emitter

TypeSpec provides an emitter (`@typespec/protobuf`) that generates Protocol Buffers specifications from TypeSpec sources as part of its standard library. The resulting Protobuf files may be used as inputs for creating gRPC services or any other tools compatible with Protocol Buffers.

**Note**: The Protobuf emitter uses Protocol Buffers 3 (proto3) syntax. Your workflow (`protoc` version, etc.) must support proto3 to utilize this emitter.

## Install

In the project root, install the emitter using your JavaScript package manager of choice. For example, using NPM:

```bash
npm install @typespec/protobuf
```

## Installing and enabling

The `@typespec/protobuf` package provides an emitter that must be enabled in order to generate Protobuf files. Enable it by adding it to your TypeSpec compiler invocation on the CLI or the project configuration file:

1. Via the CLI

```bash
tsp compile . --emit @typespec/protobuf
```

2. Via the project configuration

Add the Protobuf emitter to the `emitters` entry (or create one if it does not exist) in `tsp-project.yaml`:

```yaml
emitters:
@typespec/protobuf: true
```

With this configuration entry, Protobuf files will be generated every time the project is compiled using `tsp compile .`.

## Core concepts

The Protobuf emitter enables you to write TypeSpec and convert it into equivalent Protocol Buffers for use with Protobuf-enabled systems (such as gRPC). Your TypeSpec models and interfaces must adhere to certain requirements and restrictions in order for the emitter to convert them to Protobuf.

### Packages

A protobuf package is defined by the [`TypeSpec.Protobuf.package` decorator][protobuf-package], which applies to a TypeSpec namespace. A package essentially defines a `.proto` file, and everything within the decorated namespace will be emitted to a single file.

The following TypeSpec namespace results in a Protobuf file named `main.proto` that contains the contents of the `Test` namespace converted into Protobuf.

```typespec
@package
namespace Test {
// ...

}
```

Package names may be provided using the optional `PackageDetails` argument to the `@package` decorator. The following TypeSpec namespace will result in a file `com/example/test.proto` that has the line `package com.example.test;` within it:

```typespec
@package({
name: "com.example.test",
})
namespace Test {
// ...

}
```

TypeSpec objects (models, enums, etc.) are converted to Protobuf declarations within their nearest ancestor that has a package annotation. As a result, unlike in Protobuf, TypeSpec declarations of packages may be nested arbitrarily.p

### Messages

TypeSpec models are converted into Protobuf messages. The following TypeSpec model:

```typespec
model TestMessage {
@field(1) n: int32;
}
```

will be converted into the following Protobuf message:

```proto3
message TestMessage {
int32 n = 1;
}
```

Models are converted into messages and included in the Protobuf file if any of the following conditions are met:

- The model is explicitly annotated with the [`TypeSpec.Protobuf.message` decorator][protobuf-message].
- The model is referenced by any service operation (see [Services](#services) below).
- The model is a direct child of a [package namespace](#packages) and has _every_ field annotated with the [`TypeSpec.Protobuf.field` decorator][protobuf-field].

#### Field indices

Protobuf requires that the offset of each field within a Protobuf message be manually specified. In TypeSpec, the field indices are specified using the [`TypeSpec.Protobuf.field` decorator][protobuf-field]. All fields within a model must have an attached `@field` decorator to be converted into a Protobuf message.

The following TypeSpec model:

```typespec
model TestMessage {
@field(1) n: int32;
}
```

will be converted into the following Protobuf message:

```proto3
message TestMessage {
int32 n = 1;
}
```

### Services

TypeSpec has a concept of a "service" defined by the [`TypeSpec.service` decorator][native-service], but the Protobuf concept of a "service" is different and is indicated by the [`TypeSpec.Protobuf.service` decorator][protobuf-service].

When using the Protobuf emitter, a Protobuf service designation is applied to an _interface_ within a package. For example, the following TypeSpec:

```typespec
@package
namespace Example {
@Protobuf.service
interface Test {
// ...
}
}
```

will yield the following Protobuf file (named `example.proto`):

```proto3
syntax = "proto3";

package example;

service Test {
// ...
}
```

#### Operations

Within a [service interface](#services), TypeSpec operations represent Protobuf service methods. Each operation in the service interface is converted into an equivalent Protobuf method declaration. For example, the following specification:

```typespec
model Input {
@field(1) exampleField: string;
}

model Output {
@field(1) parsed: uint32;
}

@Protobuf.service
interface Example {
testOperation(...Input): Output;
}
```

Results in the following `.proto` file:

```proto3
message Input {
string exampleField = 1;
}

message Output {
uint32 parsed = 1;
}

service Example {
rpc TestOperation(Input) returns (Output);
}
```

#### Streams

The Protobuf emitter supports declaring the streaming mode of an operation using the [`TypeSpec.Protobuf.stream` decorator][protobuf-stream]. The streaming mode is specified using the [`StreamMode`][protobuf-stream-mode] enum. An operation can have one of four streaming modes:

- `None`: this is the default mode and indicates that neither the request nor response are streamed.

Example: `rpc Example(In) returns (Out);`

- `In`: indicates that the request is streamed, but the response is received synchronously.

Example: `rpc Example(stream In) returns (Out);`

- `Out`: indicates that the request is sent synchronously, but the response is streamed.

Example: `rpc Example(In) returns (stream Out);`

- `Duplex`: indicates that both the request and response are streamed.

Example: `rpc Example(stream In) returns (stream Out);`

## Emitter options

Emitter options can be provided to the CLI with

```bash
--option "@typespec/protobuf.<optionName>=<value>"

# For example
--option "@typespec/protobuf.noEmit=true"
```

or configured through the `typespec-project.yaml` project configuration:

```yaml
emitters:
'@typespec/protobuf':
<optionName>: <value>

# For example
emitters:
'@typespec/protobuf':
noEmit: true
```

#### `noEmit`

If set to `true`, this emitter will not write any files. It will still validate the TypeSpec sources to ensure they are compatible with Protobuf, but the files will simply not be written to the output directory.

[native-service]: ../built-in-decorators#service
[protobuf-service]: reference/decorators#@TypeSpec.Protobuf.service
[protobuf-package]: reference/decorators#@TypeSpec.Protobuf.package
[protobuf-field]: reference/decorators#@TypeSpec.Protobuf.field
[protobuf-stream]: reference/decorators#@TypeSpec.Protobuf.stream
[protobuf-stream-mode]: reference/data-types#TypeSpec.Protobuf.StreamMode
[protobuf-message]: reference/decorators#@TypeSpec.Protobuf.message
Loading