|
|
@@ -0,0 +1,144 @@
|
|
|
+# gRPC Swift Public API
|
|
|
+
|
|
|
+gRPC Swift follows [Semantic Versioning 2.0.0][semver] (SemVer) which requires
|
|
|
+that projects declare a public API.
|
|
|
+
|
|
|
+For the purpose of this document we consider the gRPC Swift public API to be
|
|
|
+limited to:
|
|
|
+
|
|
|
+1. the `GRPC` module (i.e., code in in [`Sources/GRPC`](../Sources/GRPC)), and
|
|
|
+1. modules generated by the `protoc-gen-grpc-swift` plugin.
|
|
|
+
|
|
|
+Below we cover what consitutes the public API of each, how to use them in an
|
|
|
+acceptable manner, and compatability between `GRPC` and modules generated by
|
|
|
+`protoc-gen-grpc-swift`.
|
|
|
+
|
|
|
+## `GRPC` and Generated Modules
|
|
|
+
|
|
|
+All exported types and methods from the [`GRPC`](../Sources/GRPC) module and those
|
|
|
+generated by `protoc-gen-grpc-swift` are considered public API except for the
|
|
|
+following:
|
|
|
+
|
|
|
+- types which are prefixed with an an underscore (`_`)
|
|
|
+- all methods on types whose name is prefixed with an underscore (`_`)
|
|
|
+- methods which are prefixed with an underscore (`_`)
|
|
|
+
|
|
|
+**Examples**
|
|
|
+
|
|
|
+- `Server.insecure(group:)` **is** part of the public API.
|
|
|
+- `_GRPCClientChannelHandler.channelRead(context:data:)` **is not** part of the
|
|
|
+ public API, the type `_GRPCClientChannelHandler` starts with an underscore.
|
|
|
+- `EmbeddedChannel._configureForEmbeddedServerTest()` **is not** part of the
|
|
|
+ public API, the method starts with an underscore.
|
|
|
+
|
|
|
+### Acceptable Use of the API
|
|
|
+
|
|
|
+#### Conforming Types to Protocols
|
|
|
+
|
|
|
+In gRPC Swift, and more generally Swift, it is only acceptable to conform a type
|
|
|
+to a protocol if you control either the type, the protocol, or both.
|
|
|
+
|
|
|
+- You must not conform any types from `GRPC` or generated code to protocols
|
|
|
+ which you do not own.
|
|
|
+- You must not add conformance to protocols defined by `GRPC` or generated
|
|
|
+ code for types you do not own.
|
|
|
+
|
|
|
+**Examples**
|
|
|
+
|
|
|
+- `extension MyMessageSerializer: MessageSerializer { ... }` is acceptable
|
|
|
+ assuming `MyMessageSerializer` exists in your own codebase.
|
|
|
+- `extension GRPCPayloadSerializer: DebugStringConvertible { ... }` is **not**
|
|
|
+ acceptable, `GRPCPayloadSerializer` is defined in `GRPC` and
|
|
|
+ `DebugStringConvertible` is a standard library protocol.
|
|
|
+
|
|
|
+#### Extending `GRPC` or Generated Types
|
|
|
+
|
|
|
+Extending `GRPC` or generated types with `private` or `internal` methods and
|
|
|
+properties is always allowed.
|
|
|
+
|
|
|
+In order to avoid the potential for clashing names, extending `GRPC` or
|
|
|
+generated types with `public` methods and properties is acceptable if:
|
|
|
+
|
|
|
+- The extension uses a type you own, either as a return type or as a non-default
|
|
|
+ argument.
|
|
|
+- The extension is prefixed with a name which will avoid avoid ambiguity (such
|
|
|
+ as the name of your module).
|
|
|
+
|
|
|
+**Examples**
|
|
|
+
|
|
|
+The following **is not** acceptable since it is public and does not use a type
|
|
|
+owned by the implementer of the extension.
|
|
|
+
|
|
|
+```swift
|
|
|
+extension Server.Builder {
|
|
|
+ public func withSignalHandler(_ handler: @escaping (Int) -> Void) -> Self {
|
|
|
+ ...
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+The following **is** acceptable, `MySignal` is defined in the same module as the
|
|
|
+extension and is used as a non-default argument.
|
|
|
+
|
|
|
+```swift
|
|
|
+public struct MySignal {
|
|
|
+ public var signal: Int
|
|
|
+}
|
|
|
+
|
|
|
+extension Server.Builder {
|
|
|
+ public func withSignalHandler(_ handler: @escaping (MySignal) -> Void) -> Self {
|
|
|
+ ...
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+The following **is** acceptable because the method is `internal`.
|
|
|
+
|
|
|
+```swift
|
|
|
+extension Server.Builder {
|
|
|
+ internal func withSignalHandler(_ handler: @escaping (Int) -> Void) -> Self {
|
|
|
+ ...
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Promises the `GRPC` team make
|
|
|
+
|
|
|
+Before releasing a new major version, i.e. gRPC Swift 2.0.0, we promise that:
|
|
|
+
|
|
|
+- None of the public API will be knowingly removed. We will restore any
|
|
|
+ accidental removals as we become aware of them.
|
|
|
+- All additions to the global namespace will be prefixed with `GRPC` or `gRPC`.
|
|
|
+
|
|
|
+We may deprecate APIs before the next major release, however, they will remain
|
|
|
+supported.
|
|
|
+
|
|
|
+**Examples**
|
|
|
+
|
|
|
+- We **might** add a new type called `GRPCChannelPool`
|
|
|
+- We **might** add a new module called `GRPCTestKit`
|
|
|
+- We **might** add a new gloabl function called `gRPCRun`
|
|
|
+- We **will not** add a new type called `ChannelPool`
|
|
|
+- We **will not** add a new module called `TestKit`
|
|
|
+- We **will not** add a new gloabl function called `run`
|
|
|
+
|
|
|
+## Generated Code
|
|
|
+
|
|
|
+gRPC Swift generates code via its `protoc` plugin `protoc-gen-grpc-swift`.
|
|
|
+In order to develop the library over time without breaking existing generated
|
|
|
+code it is important to lay out any API and compatability guarantees.
|
|
|
+
|
|
|
+Before releasing a new major version, i.e. gRPC Swift 2.0.0, we promise that:
|
|
|
+
|
|
|
+- The `GRPC` module will be backward compatible with all code generated by
|
|
|
+ the `protoc-gen-grpc-swift` plugin.
|
|
|
+- Generated code will not have its API broken by being updated.
|
|
|
+
|
|
|
+**Examples**
|
|
|
+
|
|
|
+- Code generated with `protoc-gen-grpc-swift` 1.3.0 will always be compatible
|
|
|
+ with `GRPC` 1.3.0 and higher.
|
|
|
+- Code generated with `protoc-gen-grpc-swift` 1.5.0 offers no compatability
|
|
|
+ guarantees compatible with `GRPC` versions lower than 1.5.0.
|
|
|
+
|
|
|
+[semver]: https://semver.org/spec/v2.0.0.html
|