@typespec/protobuf 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.c8rc.json +3 -0
  2. package/.eslintrc.cjs +7 -0
  3. package/.mocharc.yaml +4 -0
  4. package/.rush/temp/operation/build/state.json +3 -0
  5. package/.rush/temp/operation/test-official/state.json +3 -0
  6. package/.rush/temp/package-deps_build.json +81 -0
  7. package/.rush/temp/package-deps_test-official.json +81 -0
  8. package/.rush/temp/shrinkwrap-deps.json +177 -0
  9. package/CHANGELOG.json +4 -0
  10. package/LICENSE +21 -0
  11. package/README.md +30 -0
  12. package/coverage/cobertura-coverage.xml +2291 -0
  13. package/coverage/coverage-final.json +7 -0
  14. package/coverage/tmp/coverage-6408-1683144315012-0.json +1 -0
  15. package/dist/src/ast.d.ts +199 -0
  16. package/dist/src/ast.d.ts.map +1 -0
  17. package/dist/src/ast.js +60 -0
  18. package/dist/src/ast.js.map +1 -0
  19. package/dist/src/index.d.ts +62 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +5 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/lib.d.ts +197 -0
  24. package/dist/src/lib.d.ts.map +1 -0
  25. package/dist/src/lib.js +134 -0
  26. package/dist/src/lib.js.map +1 -0
  27. package/dist/src/proto.d.ts +62 -0
  28. package/dist/src/proto.d.ts.map +1 -0
  29. package/dist/src/proto.js +162 -0
  30. package/dist/src/proto.js.map +1 -0
  31. package/dist/src/transform/index.d.ts +7 -0
  32. package/dist/src/transform/index.d.ts.map +1 -0
  33. package/dist/src/transform/index.js +744 -0
  34. package/dist/src/transform/index.js.map +1 -0
  35. package/dist/src/write.d.ts +12 -0
  36. package/dist/src/write.d.ts.map +1 -0
  37. package/dist/src/write.js +204 -0
  38. package/dist/src/write.js.map +1 -0
  39. package/dist/test/scenarios.test.d.ts +2 -0
  40. package/dist/test/scenarios.test.d.ts.map +1 -0
  41. package/dist/test/scenarios.test.js +165 -0
  42. package/dist/test/scenarios.test.js.map +1 -0
  43. package/lib/proto.tsp +303 -0
  44. package/package.json +49 -0
  45. package/protobuf.build.log +48 -0
  46. package/src/ast.ts +279 -0
  47. package/src/index.ts +7 -0
  48. package/src/lib.ts +161 -0
  49. package/src/proto.ts +217 -0
  50. package/src/transform/index.ts +980 -0
  51. package/src/write.ts +244 -0
  52. package/temp/tsconfig.tsbuildinfo +1 -0
  53. package/test/include/foo/bar.proto +7 -0
  54. package/test/scenarios/addressbook/input/addressbook.tsp +27 -0
  55. package/test/scenarios/addressbook/input/main.tsp +13 -0
  56. package/test/scenarios/addressbook/output/@typespec/protobuf/addressbook.proto +26 -0
  57. package/test/scenarios/addressbook/output/@typespec/protobuf/main.proto +14 -0
  58. package/test/scenarios/anonymous-model/diagnostics.txt +1 -0
  59. package/test/scenarios/anonymous-model/input/main.tsp +24 -0
  60. package/test/scenarios/anonymous-package/input/main.tsp +19 -0
  61. package/test/scenarios/anonymous-package/output/@typespec/protobuf/main.proto +15 -0
  62. package/test/scenarios/array/input/main.tsp +22 -0
  63. package/test/scenarios/array/output/@typespec/protobuf/com/azure/test.proto +18 -0
  64. package/test/scenarios/array-nested/diagnostics.txt +1 -0
  65. package/test/scenarios/array-nested/input/main.tsp +20 -0
  66. package/test/scenarios/cross package references/input/main.tsp +27 -0
  67. package/test/scenarios/cross package references/output/@typespec/protobuf/A.proto +10 -0
  68. package/test/scenarios/cross package references/output/@typespec/protobuf/B.proto +15 -0
  69. package/test/scenarios/derived-scalar/input/main.tsp +24 -0
  70. package/test/scenarios/derived-scalar/output/@typespec/protobuf/com/azure/Test.proto +18 -0
  71. package/test/scenarios/enum/input/main.tsp +33 -0
  72. package/test/scenarios/enum/output/@typespec/protobuf/main.proto +31 -0
  73. package/test/scenarios/enum-nonintegral/diagnostics.txt +4 -0
  74. package/test/scenarios/enum-nonintegral/input/main.tsp +31 -0
  75. package/test/scenarios/enum-nozero/diagnostics.txt +1 -0
  76. package/test/scenarios/enum-nozero/input/main.tsp +25 -0
  77. package/test/scenarios/extern/input/main.tsp +17 -0
  78. package/test/scenarios/extern/output/@typespec/protobuf/main.proto +19 -0
  79. package/test/scenarios/illegal field reservations/diagnostics.txt +2 -0
  80. package/test/scenarios/illegal field reservations/input/main.tsp +16 -0
  81. package/test/scenarios/inferred-message-names/input/main.tsp +16 -0
  82. package/test/scenarios/inferred-message-names/output/@typespec/protobuf/com/azure/test.proto +18 -0
  83. package/test/scenarios/intrinsics/input/main.tsp +17 -0
  84. package/test/scenarios/intrinsics/output/@typespec/protobuf/com/azure/Test.proto +16 -0
  85. package/test/scenarios/map/input/main.tsp +15 -0
  86. package/test/scenarios/map/output/@typespec/protobuf/main.proto +13 -0
  87. package/test/scenarios/model-no-package/diagnostics.txt +2 -0
  88. package/test/scenarios/model-no-package/input/main.tsp +19 -0
  89. package/test/scenarios/name-collision/input/main.tsp +24 -0
  90. package/test/scenarios/name-collision/output/@typespec/protobuf/main.proto +24 -0
  91. package/test/scenarios/options/input/main.tsp +25 -0
  92. package/test/scenarios/options/output/@typespec/protobuf/com/azure/Test.proto +20 -0
  93. package/test/scenarios/options-invalid/diagnostics.txt +1 -0
  94. package/test/scenarios/options-invalid/input/main.tsp +25 -0
  95. package/test/scenarios/reserved field collisions/diagnostics.txt +5 -0
  96. package/test/scenarios/reserved field collisions/input/main.tsp +19 -0
  97. package/test/scenarios/reserved fields/input/main.tsp +16 -0
  98. package/test/scenarios/reserved fields/output/@typespec/protobuf/main.proto +16 -0
  99. package/test/scenarios/simple/input/main.tsp +22 -0
  100. package/test/scenarios/simple/output/@typespec/protobuf/com/azure/Test.proto +18 -0
  101. package/test/scenarios/simple-error/diagnostics.txt +6 -0
  102. package/test/scenarios/simple-error/input/main.tsp +22 -0
  103. package/test/scenarios/simple-no-service/input/main.tsp +22 -0
  104. package/test/scenarios/simple-no-service/output/@typespec/protobuf/com/azure/Test.proto +18 -0
  105. package/test/scenarios/streams/input/main.tsp +30 -0
  106. package/test/scenarios/streams/output/@typespec/protobuf/main.proto +19 -0
  107. package/test/scenarios/type-validation/diagnostics.txt +1 -0
  108. package/test/scenarios/type-validation/input/main.tsp +11 -0
  109. package/test/scenarios/union/diagnostics.txt +1 -0
  110. package/test/scenarios/union/input/main.tsp +33 -0
  111. package/test/scenarios.test.ts +226 -0
  112. package/tsconfig.json +15 -0
package/lib/proto.tsp ADDED
@@ -0,0 +1,303 @@
1
+ import "../dist/src/index.js";
2
+
3
+ namespace TypeSpec.Protobuf;
4
+
5
+ /**
6
+ * A model that represents an external Protobuf reference. This type can be used to import and utilize Protobuf
7
+ * declarations that are not declared in TypeSpec within TypeSpec sources. When the emitter encounters an `Extern`, it
8
+ * will insert an `import` statement for the corresponding `Path` and refer to the type by `Name`.
9
+ *
10
+ * #### Usage
11
+ *
12
+ * If you have a file called `test.proto` that declares a package named `test` and a message named `Widget`, you can
13
+ * use the `Extern` type to declare a model in TypeSpec that refers to your external definition of `test.Widget`. See
14
+ * the example below.
15
+ *
16
+ * When the TypeSpec definition of `Widget` is encountered, the Protobuf emitter will represent it as a reference to
17
+ * `test.Widget` and insert an import for it, rather than attempt to convert the model to an equivalent message.
18
+ *
19
+ * @template Path the relative path to a `.proto` file to import
20
+ * @template Name the fully-qualified reference to the type this model represents within the `.proto` file
21
+ *
22
+ * @example
23
+ *
24
+ * ```typespec
25
+ * model Widget is Extern<"path/to/test.proto", "test.Widget">;
26
+ * ```
27
+ */
28
+ @externRef(Path, Name)
29
+ model Extern<Path extends string, Name extends string> {
30
+ // This _extern property is needed so that getEffectiveModelType will have something to look up. Without it, if an
31
+ // Extern model is spread into the parameter of an operation, the resulting model is empty and carries no information
32
+ // that can relate it back to its original definition.
33
+ _extern: never;
34
+ }
35
+
36
+ /**
37
+ * Contains some common well-known Protobuf types defined by the google.protobuf library.
38
+ */
39
+ namespace WellKnown {
40
+ /**
41
+ * An empty message.
42
+ *
43
+ * This model references `google.protobuf.Empty` from `google/protobuf/empty.proto`.
44
+ */
45
+ model Empty is Extern<"google/protobuf/empty.proto", "google.protobuf.Empty">;
46
+
47
+ /**
48
+ * A timestamp.
49
+ *
50
+ * This model references `google.protobuf.Timestamp` from `google/protobuf/timestamp.proto`.
51
+ */
52
+ model Timestamp is Extern<"google/protobuf/timestamp.proto", "google.protobuf.Timestamp">;
53
+
54
+ /**
55
+ * Any value.
56
+ *
57
+ * This model references `google.protobuf.Any` from `google/protobuf/any.proto`.
58
+ */
59
+ model Any is Extern<"google/protobuf/any.proto", "google.protobuf.Any">;
60
+
61
+ /**
62
+ * A latitude and longitude.
63
+ *
64
+ * This model references `google.type.LatLng` from `google/type/latlng.proto`.
65
+ */
66
+ model LatLng is Extern<"google/type/latlng.proto", "google.type.LatLng">;
67
+ }
68
+
69
+ /**
70
+ * A signed 32-bit integer that will use the `sint32` encoding when used in a Protobuf message.
71
+ *
72
+ * #### Protobuf binary format
73
+ *
74
+ * Uses variable-length encoding. These more efficiently encode negative numbers than regular int32s.
75
+ */
76
+ scalar sint32 extends int32;
77
+ /**
78
+ * A signed 64-bit integer that will use the `sint64` encoding when used in a Protobuf message.
79
+ *
80
+ * #### Protobuf binary format
81
+ *
82
+ * Uses variable-length encoding. These more efficiently encode negative numbers than regular `int64s`.
83
+ */
84
+ scalar sint64 extends int64;
85
+ /**
86
+ * A signed 32-bit integer that will use the `sfixed32` encoding when used in a Protobuf message.
87
+ *
88
+ * #### Protobuf binary format
89
+ *
90
+ * Always four bytes.
91
+ */
92
+ scalar sfixed32 extends int32;
93
+ /**
94
+ * A signed 64-bit integer that will use the `sfixed64` encoding when used in a Protobuf message.
95
+ *
96
+ * #### Protobuf binary format
97
+ *
98
+ * Always eight bytes.
99
+ */
100
+ scalar sfixed64 extends int64;
101
+ /**
102
+ * An unsigned 32-bit integer that will use the `fixed32` encoding when used in a Protobuf message.
103
+ *
104
+ * #### Protobuf binary format
105
+ *
106
+ * Always four bytes. More efficient than `uint32` if values are often greater than 2<sup>28</sup>.
107
+ */
108
+ scalar fixed32 extends uint32;
109
+ /**
110
+ * An unsigned 64-bit integer that will use the `fixed64` encoding when used in a Protobuf message.
111
+ *
112
+ * #### Protobuf binary format
113
+ *
114
+ * Always eight bytes. More efficient than `uint64` if values are often greater than 2<sup>56</sup>.
115
+ */
116
+ scalar fixed64 extends uint64;
117
+
118
+ /**
119
+ * Types recognized as "integral" types
120
+ */
121
+ alias integral = int32 | int64 | uint32 | uint64 | boolean;
122
+
123
+ /**
124
+ * A type representing a Protobuf `map`. Instances of this type in models will be converted to the built-in `map` type
125
+ * in Protobuf.
126
+ *
127
+ * The key type of a Protobuf `map` must be any integral type or `string`. The value type can be any type other than
128
+ * another `Map`.
129
+ *
130
+ * @template K the key type (any integral type or string)
131
+ * @template V the value type (any type other than another map)
132
+ */
133
+ @_map
134
+ model Map<K extends integral | string, V> {}
135
+
136
+ /**
137
+ * Declares that a model is a Protobuf message.
138
+ *
139
+ * Messages can be detected automatically if either of the following two conditions are met:
140
+ *
141
+ * - The model has a `@field` annotation on all of its properties.
142
+ * - The model is referenced by any service operation.
143
+ *
144
+ * This decorator will force the emitter to check and emit a model.
145
+ */
146
+ extern dec message(target: object);
147
+
148
+ /**
149
+ * Defines the field index of a model property for conversion to a Protobuf
150
+ * message.
151
+ *
152
+ * The field index of a Protobuf message must:
153
+ * - fall between 1 and 2<sup>29</sup> - 1, inclusive.
154
+ * - not fall within the implementation reserved range of 19000 to 19999, inclusive.
155
+ * - not fall within any range that was [marked reserved](#@TypeSpec.Protobuf.reserve).
156
+ *
157
+ * #### API Compatibility Note
158
+ *
159
+ * Fields are accessed by index, so changing the index of a field is an API breaking change.
160
+ *
161
+ * #### Encoding
162
+ *
163
+ * Field indices between 1 and 15 are encoded using a single byte, while field indices from 16 through 2047 require two
164
+ * bytes, so those indices between 1 and 15 should be preferred and reserved for elements that are frequently or always
165
+ * set in the message. See the [Protobuf binary format](https://protobuf.dev/programming-guides/encoding/).
166
+ *
167
+ * @param index The whole-number index of the field.
168
+ *
169
+ * @example
170
+ *
171
+ * ```typespec
172
+ * model ExampleMessage {
173
+ * @field(1)
174
+ * test: string;
175
+ * }
176
+ * ```
177
+ */
178
+ extern dec field(target: TypeSpec.Reflection.ModelProperty, index: uint32);
179
+
180
+ /**
181
+ * Reserve a field index, range, or name. If a field definition collides with a reservation, the emitter will produce
182
+ * an error.
183
+ *
184
+ * This decorator accepts multiple reservations. Each reservation is one of the following:
185
+ *
186
+ * - a `string`, in which case the reservation refers to a field name.
187
+ * - a `uint32`, in which case the reservation refers to a field index.
188
+ * - a tuple `[uint32, uint32]`, in which case the reservation refers to a field range that is _inclusive_ of both ends.
189
+ *
190
+ * Unlike in Protobuf, where field name and index reservations must be separated, you can mix string and numeric field
191
+ * reservations in a single `@reserve` call in TypeSpec.
192
+ *
193
+ * #### API Compatibility Note
194
+ *
195
+ * Field reservations prevent users of your Protobuf specification from using the given field names or indices. This can
196
+ * be useful if a field is removed, as it will further prevent adding a new, incompatible field and will prevent users
197
+ * from utilizing the field index at runtime in a way that may break compatibility with users of older specifications.
198
+ *
199
+ * See _[Protobuf Language Guide - Reserved Fields](https://protobuf.dev/programming-guides/proto3/#reserved)_ for more
200
+ * information.
201
+ *
202
+ * @param reservations a list of field reservations
203
+ *
204
+ * @example
205
+ *
206
+ * ```typespec
207
+ * // Reserve the fields 8-15 inclusive, 100, and the field name "test" within a model.
208
+ * @reserve([8, 15], 100, "test")
209
+ * model Example {
210
+ * // ...
211
+ * }
212
+ * ```
213
+ */
214
+ extern dec reserve(target: object, ...reservations: (string | [uint32, uint32] | uint32)[]);
215
+
216
+ /**
217
+ * Declares that a TypeSpec interface constitutes a Protobuf service. The contents of the interface will be converted to
218
+ * a `service` declaration in the resulting Protobuf file.
219
+ */
220
+ extern dec service(target: TypeSpec.Reflection.Interface);
221
+
222
+ // FIXME: cannot link to the package decorator directly because it is detected as a broken link.
223
+ /**
224
+ * Details applied to a package definition by the [`@package`](./decorators#@TypeSpec.Protobuf.package) decorator.
225
+ */
226
+ model PackageDetails {
227
+ /**
228
+ * The package's name.
229
+ *
230
+ * By default, the package's name is constructed from the namespace it is applied to.
231
+ */
232
+ name?: string;
233
+ /**
234
+ * The package's top-level options.
235
+ *
236
+ * See the [Protobuf Language Guide - Options](https://protobuf.dev/programming-guides/proto3/#options) for more information.
237
+ *
238
+ * Currently, only string, boolean, and numeric options are supported.
239
+ */
240
+ options?: Record<string | boolean | numeric>;
241
+ }
242
+
243
+ /**
244
+ * Declares that a TypeSpec namespace constitutes a Protobuf package. The contents of the namespace will be emitted to a
245
+ * single Protobuf file.
246
+ *
247
+ * @param details the optional details of the package
248
+ */
249
+ extern dec package(target: TypeSpec.Reflection.Namespace, details?: PackageDetails);
250
+
251
+ /**
252
+ * The streaming mode of an operation. One of:
253
+ *
254
+ * - `Duplex`: both the input and output of the operation are streaming.
255
+ * - `In`: the input of the operation is streaming.
256
+ * - `Out`: the output of the operation is streaming.
257
+ * - `None`: neither the input nor the output are streaming.
258
+ *
259
+ * See the [`@stream`](./decorators#@TypeSpec.Protobuf.stream) decorator.
260
+ */
261
+ enum StreamMode {
262
+ /**
263
+ * Both the input and output of the operation are streaming. Both the client and service will stream messages to each
264
+ * other until the connections are closed.
265
+ */
266
+ Duplex,
267
+ /**
268
+ * The input of the operation is streaming. The client will send a stream of events; and, once the stream is closed,
269
+ * the service will respond with a message.
270
+ */
271
+ In,
272
+ /**
273
+ * The output of the operation is streaming. The client will send a message to the service, and the service will send
274
+ * a stream of events back to the client.
275
+ */
276
+ Out,
277
+ /**
278
+ * Neither the input nor the output are streaming. This is the default mode of an operation without the `@stream`
279
+ * decorator.
280
+ */
281
+ None,
282
+ }
283
+
284
+ /**
285
+ * Set the streaming mode of an operation. See [StreamMode](./data-types#TypeSpec.Protobuf.StreamMode) for more information.
286
+ *
287
+ * @param mode The streaming mode to apply to this operation.
288
+ *
289
+ * @example
290
+ *
291
+ * ```typespec
292
+ * @stream(StreamMode.Out)
293
+ * op logs(...LogsRequest): LogEvent;
294
+ * ```
295
+ *
296
+ * @example
297
+ *
298
+ * ```typespec
299
+ * @stream(StreamMode.Duplex)
300
+ * op connectToMessageService(...Message): Message;
301
+ * ```
302
+ */
303
+ extern dec stream(target: TypeSpec.Reflection.Operation, mode: StreamMode);
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@typespec/protobuf",
3
+ "version": "0.43.0",
4
+ "author": "Microsoft Corporation",
5
+ "description": "TypeSpec library and emitter for Protobuf (gRPC)",
6
+ "homepage": "https://github.com/Microsoft/typespec",
7
+ "readme": "https://github.com/Microsoft/typespec/blob/main/packages/protobuf/README.md",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Microsoft/typespec.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/Microsoft/typespec/issues"
15
+ },
16
+ "keywords": [
17
+ "typespec",
18
+ "protobuf",
19
+ "grpc"
20
+ ],
21
+ "main": "dist/src/index.js",
22
+ "type": "module",
23
+ "tspMain": "lib/proto.tsp",
24
+ "dependencies": {
25
+ "@typespec/compiler": "~0.43.0"
26
+ },
27
+ "devDependencies": {
28
+ "@typespec/eslint-config-typespec": "~0.6.0",
29
+ "@typespec/eslint-plugin": "~0.43.0",
30
+ "@types/mocha": "~10.0.0",
31
+ "@types/node": "~18.11.9",
32
+ "c8": "~7.13.0",
33
+ "eslint": "^8.36.0",
34
+ "mocha": "~10.2.0",
35
+ "rimraf": "~5.0.0",
36
+ "typescript": "~5.0.2",
37
+ "micromatch": "^4.0.5",
38
+ "@types/micromatch": "^4.0.2"
39
+ },
40
+ "scripts": {
41
+ "clean": "rimraf ./dist ./temp",
42
+ "build": "tsc -p .",
43
+ "watch": "tsc -p . --watch",
44
+ "test": "mocha",
45
+ "test-official": "c8 mocha --forbid-only",
46
+ "lint": "eslint . --ext .ts --max-warnings=0",
47
+ "lint:fix": "eslint . --fix --ext .ts"
48
+ }
49
+ }
@@ -0,0 +1,48 @@
1
+ Invoking: c8 mocha --forbid-only
2
+
3
+
4
+ protobuf scenarios
5
+ √ addressbook (300ms)
6
+ √ anonymous-model (74ms)
7
+ √ anonymous-package (154ms)
8
+ √ array (134ms)
9
+ √ array-nested (47ms)
10
+ √ cross package references (56ms)
11
+ √ derived-scalar (122ms)
12
+ √ enum (164ms)
13
+ √ enum-nonintegral (39ms)
14
+ √ enum-nozero
15
+ √ extern (63ms)
16
+ √ illegal field reservations (40ms)
17
+ √ inferred-message-names
18
+ √ intrinsics
19
+ √ map (50ms)
20
+ √ model-no-package (44ms)
21
+ √ name-collision (145ms)
22
+ √ options (84ms)
23
+ √ options-invalid (120ms)
24
+ √ reserved field collisions (41ms)
25
+ √ reserved fields (82ms)
26
+ √ simple (124ms)
27
+ √ simple-error (55ms)
28
+ √ simple-no-service (74ms)
29
+ √ streams (81ms)
30
+ √ type-validation
31
+ √ union (85ms)
32
+
33
+
34
+ 27 passing (2s)
35
+
36
+ ---------------|---------|----------|---------|---------|-------------------------------------------
37
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
38
+ ---------------|---------|----------|---------|---------|-------------------------------------------
39
+ All files | 94.86 | 88.37 | 98.57 | 94.86 |
40
+ src | 99.11 | 96.22 | 97.29 | 99.11 |
41
+ ast.ts | 100 | 100 | 100 | 100 |
42
+ index.ts | 100 | 100 | 100 | 100 |
43
+ lib.ts | 100 | 100 | 100 | 100 |
44
+ proto.ts | 100 | 100 | 100 | 100 |
45
+ write.ts | 96.72 | 93.75 | 94.73 | 96.72 | 75-76,144-149
46
+ src/transform | 90.91 | 84.61 | 100 | 90.91 |
47
+ index.ts | 90.91 | 84.61 | 100 | 90.91 | ...96,948,950-953,955,970,973,975-978,980
48
+ ---------------|---------|----------|---------|---------|-------------------------------------------
package/src/ast.ts ADDED
@@ -0,0 +1,279 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+
3
+ import { Namespace } from "@typespec/compiler";
4
+
5
+ /**
6
+ * This module describes an AST for Protobuf.
7
+ */
8
+
9
+ /**
10
+ * A single .proto file.
11
+ */
12
+ export interface ProtoFile {
13
+ /**
14
+ * The package name, if one is known.
15
+ */
16
+ package?: string;
17
+ /**
18
+ * The `option` specifiers to include in the file.
19
+ */
20
+ options: Partial<WellKnownFileOptions>;
21
+
22
+ /**
23
+ * Paths imported by this file.
24
+ */
25
+ imports: string[];
26
+
27
+ /**
28
+ * The declarations in the file.
29
+ *
30
+ * Only `service` and `message` declarations may exist at the root of the file.
31
+ */
32
+ declarations: Iterable<ProtoTopLevelDeclaration>;
33
+
34
+ /**
35
+ * The original namespace node from which this ProtoFile originated.
36
+ */
37
+ source: Namespace;
38
+ }
39
+
40
+ /**
41
+ * The built-in options that are defined by Protobuf.
42
+ */
43
+ export interface WellKnownFileOptions {
44
+ java_package: string;
45
+ java_outer_classname: string;
46
+
47
+ optimize_for: "SPEED" | "CODE_SIZE" | "LITE_RUNTIME";
48
+
49
+ cc_enable_arenas: boolean;
50
+ }
51
+
52
+ /**
53
+ * A top-level declaration.
54
+ */
55
+ export type ProtoTopLevelDeclaration =
56
+ | ProtoServiceDeclaration
57
+ | ProtoMessageDeclaration
58
+ | ProtoEnumDeclaration;
59
+
60
+ /**
61
+ * A declaration. One of `service`, `message`, a field within a message, `one_of`, `enum`, or an `rpc` method.
62
+ */
63
+ export type ProtoDeclaration =
64
+ | ProtoServiceDeclaration
65
+ | ProtoMessageDeclaration
66
+ | ProtoFieldDeclaration
67
+ | ProtoOneOfDeclaration
68
+ | ProtoEnumDeclaration
69
+ | ProtoMethodDeclaration;
70
+
71
+ /**
72
+ * A Protobuf scalar type.
73
+ */
74
+ export type ScalarName = ScalarIntegralName | "double" | "float" | "bytes" | "string";
75
+
76
+ /**
77
+ * A Protobuf integral type.
78
+ */
79
+ export type ScalarIntegralName = ScalarIntegerName | ScalarFixedName | "bool";
80
+
81
+ /**
82
+ * A Protobuf variable-length integer type.
83
+ */
84
+ export type ScalarIntegerName = `${"u" | "s" | ""}int${"32" | "64"}`;
85
+
86
+ /**
87
+ * A Protobuf fixed-length integer type.
88
+ */
89
+ export type ScalarFixedName = `${"s" | ""}fixed${"32" | "64"}`;
90
+
91
+ // Symbols for type destructuring
92
+ const $scalar = Symbol("$scalar");
93
+ const $ref = Symbol("$ref");
94
+ const $map = Symbol("$map");
95
+
96
+ /**
97
+ * A map type. Map keys can be any integral or string type (any scalar except float, double, and bytes).
98
+ *
99
+ * The value may be any type other than another map.
100
+ */
101
+ export type ProtoMap = [typeof $map, ScalarIntegralName | "string", ProtoRef | ProtoScalar];
102
+
103
+ /**
104
+ * A reference to a named message type.
105
+ */
106
+ export type ProtoRef = [typeof $ref, string];
107
+
108
+ /**
109
+ * A scalar type.
110
+ */
111
+ export type ProtoScalar = [typeof $scalar, ScalarName];
112
+
113
+ /**
114
+ * A Protobuf type.
115
+ */
116
+ export type ProtoType = ProtoScalar | ProtoRef | ProtoMap;
117
+
118
+ /**
119
+ * Create a scalar type by name.
120
+ */
121
+ export function scalar(t: ScalarName): ProtoScalar {
122
+ return [$scalar, t];
123
+ }
124
+
125
+ /**
126
+ * Create a type reference (symbol) to a named message.
127
+ */
128
+ export function ref(t: string): ProtoRef {
129
+ return [$ref, t];
130
+ }
131
+
132
+ /**
133
+ * Create a map from a key type to a value type.
134
+ */
135
+ export function map(k: ScalarIntegralName | "string", v: Exclude<ProtoType, ProtoMap>): ProtoMap {
136
+ return [$map, k, v];
137
+ }
138
+
139
+ /* c8 ignore start */
140
+
141
+ // Unreachable, by definition, should not be covered :)
142
+
143
+ /**
144
+ * Creates a type that will throw an internal error if the system attempts to emit it.
145
+ *
146
+ * @param message - optional message that should be printed
147
+ */
148
+ export function unreachable(message: string = "tried to emit unreachable type"): never {
149
+ // This little "array-like" object will throw an internal error as soon as the "tag" is inspected.
150
+ return Object.freeze({
151
+ get [0]() {
152
+ throw new Error("Internal Error: " + message);
153
+ },
154
+ }) as never;
155
+ }
156
+
157
+ /* c8 ignore stop */
158
+
159
+ /**
160
+ * A "pattern" object with variants for each Protobuf type.
161
+ */
162
+ export interface ProtoTypeMatchPattern<T> {
163
+ scalar: (s: ScalarName) => T;
164
+ ref: (r: string) => T;
165
+ map: (k: ScalarIntegralName | "string", v: Exclude<ProtoType, ProtoMap>) => T;
166
+ }
167
+
168
+ /**
169
+ * A helper function that matches and delegates a Protobuf type to a handler per type.
170
+ *
171
+ * @param type - the Protobuf type to match and delegate
172
+ * @param pattern - the matching pattern of delegates to apply
173
+ * @returns
174
+ */
175
+ export function matchType<Result>(type: ProtoType, pattern: ProtoTypeMatchPattern<Result>): Result {
176
+ switch (type[0]) {
177
+ case $ref:
178
+ return pattern.ref(type[1]);
179
+ case $scalar:
180
+ return pattern.scalar(type[1]);
181
+ case $map:
182
+ return pattern.map(type[1], type[2] as Exclude<ProtoType, ProtoMap>);
183
+ /* c8 ignore next 5 */
184
+ default:
185
+ const __exhaust: never = type[0];
186
+ throw new Error(`Internal Error: unreachable matchType variant ${__exhaust}`);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * A `service` declaration.
192
+ */
193
+ export interface ProtoServiceDeclaration {
194
+ kind: "service";
195
+ name: string;
196
+ operations: ProtoMethodDeclaration[];
197
+ }
198
+
199
+ /**
200
+ * An operation's streaming mode.
201
+ */
202
+ export const enum StreamingMode {
203
+ Duplex = 3,
204
+ In = 2,
205
+ Out = 1,
206
+ None = 0,
207
+ }
208
+
209
+ /**
210
+ * An `rfc` method declaration.
211
+ */
212
+ export interface ProtoMethodDeclaration {
213
+ kind: "method";
214
+ stream: StreamingMode;
215
+ name: string;
216
+ input: ProtoRef;
217
+ returns: ProtoRef;
218
+ }
219
+
220
+ /**
221
+ * A declaration that can fit within the body of a message declaration.
222
+ */
223
+ export type ProtoMessageBodyDeclaration =
224
+ | ProtoFieldDeclaration
225
+ | ProtoMessageDeclaration
226
+ | ProtoOneOfDeclaration
227
+ | ProtoEnumDeclaration;
228
+
229
+ /**
230
+ * A `message` declaration.
231
+ */
232
+ export interface ProtoMessageDeclaration {
233
+ kind: "message";
234
+ name: string;
235
+ declarations: Array<ProtoMessageBodyDeclaration>;
236
+ reservations?: Array<string | number | [number, number]>;
237
+ }
238
+
239
+ /**
240
+ * A field declaration within a message.
241
+ */
242
+ export interface ProtoFieldDeclaration {
243
+ kind: "field";
244
+ name: string;
245
+ /**
246
+ * Whether or not the field is repeated (i.e. an array).
247
+ */
248
+ repeated?: boolean;
249
+ options?: Partial<DefaultFieldOptions>;
250
+ type: ProtoType;
251
+ index: number;
252
+ }
253
+
254
+ /**
255
+ * The options for fields defined by the Protobuf specification.
256
+ */
257
+ export interface DefaultFieldOptions {
258
+ packed: true;
259
+ deprecated: true;
260
+ }
261
+
262
+ /**
263
+ * A `one_of` declaration.
264
+ */
265
+ export interface ProtoOneOfDeclaration {
266
+ kind: "oneof";
267
+ name: string;
268
+ declarations: ProtoFieldDeclaration[];
269
+ }
270
+
271
+ /**
272
+ * An `enum` declaration.
273
+ */
274
+ export interface ProtoEnumDeclaration {
275
+ kind: "enum";
276
+ name: string;
277
+ allowAlias?: boolean;
278
+ variants: [string, number][];
279
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { TypeSpecProtobufLibrary } from "./lib.js";
2
+
3
+ export const namespace = "TypeSpec.Protobuf";
4
+
5
+ export * from "./proto.js";
6
+
7
+ export const $lib = TypeSpecProtobufLibrary;