@typespec/protobuf 0.55.0-dev.1 → 0.55.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.
- package/CHANGELOG.md +7 -0
- package/coverage/cobertura-coverage.xml +2352 -0
- package/coverage/coverage-final.json +8 -0
- package/dist/generated-defs/TypeSpec.Protobuf.d.ts +104 -0
- package/dist/generated-defs/TypeSpec.Protobuf.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Protobuf.js +2 -0
- package/dist/generated-defs/TypeSpec.Protobuf.js.map +1 -0
- package/dist/generated-defs/TypeSpec.Protobuf.ts-test.d.ts +2 -0
- package/dist/generated-defs/TypeSpec.Protobuf.ts-test.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Protobuf.ts-test.js +12 -0
- package/dist/generated-defs/TypeSpec.Protobuf.ts-test.js.map +1 -0
- package/dist/src/proto.d.ts +7 -6
- package/dist/src/proto.d.ts.map +1 -1
- package/dist/src/proto.js +10 -10
- package/dist/src/proto.js.map +1 -1
- package/generated-defs/TypeSpec.Protobuf.ts +128 -0
- package/generated-defs/TypeSpec.Protobuf.ts-test.ts +29 -0
- package/package.json +16 -12
- package/src/proto.ts +30 -16
- package/temp/tsconfig.tsbuildinfo +1 -1
- package/test-results.xml +71 -0
- package/tsconfig.json +2 -6
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { DecoratorContext, Interface, ModelProperty, Namespace, Operation, Type } from "@typespec/compiler";
|
|
2
|
+
/**
|
|
3
|
+
* Declares that a model is a Protobuf message.
|
|
4
|
+
*
|
|
5
|
+
* Messages can be detected automatically if either of the following two conditions are met:
|
|
6
|
+
*
|
|
7
|
+
* - The model has a `@field` annotation on all of its properties.
|
|
8
|
+
* - The model is referenced by any service operation.
|
|
9
|
+
*
|
|
10
|
+
* This decorator will force the emitter to check and emit a model.
|
|
11
|
+
*/
|
|
12
|
+
export type MessageDecorator = (context: DecoratorContext, target: Type) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Defines the field index of a model property for conversion to a Protobuf
|
|
15
|
+
* message.
|
|
16
|
+
*
|
|
17
|
+
* The field index of a Protobuf message must:
|
|
18
|
+
* - fall between 1 and 2<sup>29</sup> - 1, inclusive.
|
|
19
|
+
* - not fall within the implementation reserved range of 19000 to 19999, inclusive.
|
|
20
|
+
* - not fall within any range that was [marked reserved](#
|
|
21
|
+
*
|
|
22
|
+
* @TypeSpec .Protobuf.reserve).
|
|
23
|
+
*
|
|
24
|
+
* #### API Compatibility Note
|
|
25
|
+
*
|
|
26
|
+
* Fields are accessed by index, so changing the index of a field is an API breaking change.
|
|
27
|
+
*
|
|
28
|
+
* #### Encoding
|
|
29
|
+
*
|
|
30
|
+
* Field indices between 1 and 15 are encoded using a single byte, while field indices from 16 through 2047 require two
|
|
31
|
+
* bytes, so those indices between 1 and 15 should be preferred and reserved for elements that are frequently or always
|
|
32
|
+
* set in the message. See the [Protobuf binary format](https://protobuf.dev/programming-guides/encoding/).
|
|
33
|
+
* @param index The whole-number index of the field.
|
|
34
|
+
* @example
|
|
35
|
+
* ```typespec
|
|
36
|
+
* model ExampleMessage {
|
|
37
|
+
* @field(1)
|
|
38
|
+
* test: string;
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export type FieldDecorator = (context: DecoratorContext, target: ModelProperty, index: number) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Reserve a field index, range, or name. If a field definition collides with a reservation, the emitter will produce
|
|
45
|
+
* an error.
|
|
46
|
+
*
|
|
47
|
+
* This decorator accepts multiple reservations. Each reservation is one of the following:
|
|
48
|
+
*
|
|
49
|
+
* - a `string`, in which case the reservation refers to a field name.
|
|
50
|
+
* - a `uint32`, in which case the reservation refers to a field index.
|
|
51
|
+
* - a tuple `[uint32, uint32]`, in which case the reservation refers to a field range that is _inclusive_ of both ends.
|
|
52
|
+
*
|
|
53
|
+
* Unlike in Protobuf, where field name and index reservations must be separated, you can mix string and numeric field
|
|
54
|
+
* reservations in a single `@reserve` call in TypeSpec.
|
|
55
|
+
*
|
|
56
|
+
* #### API Compatibility Note
|
|
57
|
+
*
|
|
58
|
+
* Field reservations prevent users of your Protobuf specification from using the given field names or indices. This can
|
|
59
|
+
* be useful if a field is removed, as it will further prevent adding a new, incompatible field and will prevent users
|
|
60
|
+
* from utilizing the field index at runtime in a way that may break compatibility with users of older specifications.
|
|
61
|
+
*
|
|
62
|
+
* See _[Protobuf Language Guide - Reserved Fields](https://protobuf.dev/programming-guides/proto3/#reserved)_ for more
|
|
63
|
+
* information.
|
|
64
|
+
*
|
|
65
|
+
* @param reservations a list of field reservations
|
|
66
|
+
* @example
|
|
67
|
+
* ```typespec
|
|
68
|
+
* // Reserve the fields 8-15 inclusive, 100, and the field name "test" within a model.
|
|
69
|
+
* @reserve([8, 15], 100, "test")
|
|
70
|
+
* model Example {
|
|
71
|
+
* // ...
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export type ReserveDecorator = (context: DecoratorContext, target: Type, ...reservations: (string | unknown | number)[]) => void;
|
|
76
|
+
/**
|
|
77
|
+
* Declares that a TypeSpec interface constitutes a Protobuf service. The contents of the interface will be converted to
|
|
78
|
+
* a `service` declaration in the resulting Protobuf file.
|
|
79
|
+
*/
|
|
80
|
+
export type ServiceDecorator = (context: DecoratorContext, target: Interface) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Declares that a TypeSpec namespace constitutes a Protobuf package. The contents of the namespace will be emitted to a
|
|
83
|
+
* single Protobuf file.
|
|
84
|
+
*
|
|
85
|
+
* @param details the optional details of the package
|
|
86
|
+
*/
|
|
87
|
+
export type PackageDecorator = (context: DecoratorContext, target: Namespace, details?: Type) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Set the streaming mode of an operation. See [StreamMode](./data-types#TypeSpec.Protobuf.StreamMode) for more information.
|
|
90
|
+
*
|
|
91
|
+
* @param mode The streaming mode to apply to this operation.
|
|
92
|
+
* @example
|
|
93
|
+
* ```typespec
|
|
94
|
+
* @stream(StreamMode.Out)
|
|
95
|
+
* op logs(...LogsRequest): LogEvent;
|
|
96
|
+
* ```
|
|
97
|
+
* @example
|
|
98
|
+
* ```typespec
|
|
99
|
+
* @stream(StreamMode.Duplex)
|
|
100
|
+
* op connectToMessageService(...Message): Message;
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export type StreamDecorator = (context: DecoratorContext, target: Operation, mode: Type) => void;
|
|
104
|
+
//# sourceMappingURL=TypeSpec.Protobuf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Protobuf.d.ts","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Protobuf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,SAAS,EACT,SAAS,EACT,IAAI,EACL,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,KAAK,IAAI,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,KACV,IAAI,CAAC;AAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,IAAI,EACZ,GAAG,YAAY,EAAE,CAAC,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,EAAE,KAC3C,IAAI,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;AAEtF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,IAAI,KACX,IAAI,CAAC;AAEV;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Protobuf.js","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Protobuf.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Protobuf.ts-test.d.ts","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Protobuf.ts-test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** An error here would mean that the decorator is not exported or doesn't have the right name. */
|
|
2
|
+
import { $field, $message, $package, $reserve, $service, $stream } from "@typespec/protobuf";
|
|
3
|
+
/** An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ... */
|
|
4
|
+
const _ = {
|
|
5
|
+
$message,
|
|
6
|
+
$field,
|
|
7
|
+
$reserve,
|
|
8
|
+
$service,
|
|
9
|
+
$package,
|
|
10
|
+
$stream,
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=TypeSpec.Protobuf.ts-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Protobuf.ts-test.js","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Protobuf.ts-test.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAmB7F,qKAAqK;AACrK,MAAM,CAAC,GAAe;IACpB,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;CACR,CAAC"}
|
package/dist/src/proto.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { DecoratorContext, EmitContext, EmitOptionsFor,
|
|
1
|
+
import { DecoratorContext, EmitContext, EmitOptionsFor, Interface, Model, Program, StringLiteral, Type } from "@typespec/compiler";
|
|
2
|
+
import { FieldDecorator, MessageDecorator, PackageDecorator, ReserveDecorator, StreamDecorator } from "../generated-defs/TypeSpec.Protobuf.js";
|
|
2
3
|
import { TypeSpecProtobufLibrary } from "./lib.js";
|
|
3
4
|
/**
|
|
4
5
|
* Defined in the [ProtoBuf Language Spec](https://developers.google.com/protocol-buffers/docs/reference/proto3-spec#identifiers).
|
|
@@ -23,7 +24,7 @@ export interface PackageDetails {
|
|
|
23
24
|
* @param ctx - decorator context
|
|
24
25
|
* @param target - target decorator namespace
|
|
25
26
|
*/
|
|
26
|
-
export declare
|
|
27
|
+
export declare const $package: PackageDecorator;
|
|
27
28
|
/**
|
|
28
29
|
* Determines whether a type represents a Protobuf map.
|
|
29
30
|
*
|
|
@@ -33,12 +34,12 @@ export declare function $package(ctx: DecoratorContext, target: Namespace, detai
|
|
|
33
34
|
*/
|
|
34
35
|
export declare function isMap(program: Program, m: Type): boolean;
|
|
35
36
|
export declare function $externRef(ctx: DecoratorContext, target: Model, path: StringLiteral, name: StringLiteral): void;
|
|
36
|
-
export declare
|
|
37
|
+
export declare const $stream: StreamDecorator;
|
|
37
38
|
export type Reservation = string | number | ([number, number] & {
|
|
38
39
|
type: Type;
|
|
39
40
|
});
|
|
40
|
-
export declare
|
|
41
|
-
export declare
|
|
41
|
+
export declare const $reserve: ReserveDecorator;
|
|
42
|
+
export declare const $message: MessageDecorator;
|
|
42
43
|
/**
|
|
43
44
|
* Decorate a model property with a field index. Field indices are required for all fields of emitted messages.
|
|
44
45
|
*
|
|
@@ -47,7 +48,7 @@ export declare function $message(ctx: DecoratorContext, target: Model): void;
|
|
|
47
48
|
* @param fieldIndex
|
|
48
49
|
* @returns
|
|
49
50
|
*/
|
|
50
|
-
export declare
|
|
51
|
+
export declare const $field: FieldDecorator;
|
|
51
52
|
/**
|
|
52
53
|
* Emitter main function.
|
|
53
54
|
*
|
package/dist/src/proto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proto.d.ts","sourceRoot":"","sources":["../../src/proto.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,
|
|
1
|
+
{"version":3,"file":"proto.d.ts","sourceRoot":"","sources":["../../src/proto.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,SAAS,EACT,KAAK,EAKL,OAAO,EAEP,aAAa,EAEb,IAAI,EACL,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EAChB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAmD,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAmBpG;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAA6B,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,QAEhE;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAMtB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAExD;AAYD,wBAAgB,UAAU,CACxB,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,aAAa,QAGpB;AAED,eAAO,MAAM,OAAO,EAAE,eASrB,CAAC;AAkBF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC;AAEhF,eAAO,MAAM,QAAQ,EAAE,gBAYtB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,gBAEtB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,cAyCpB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC,iBAItF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,iBASjD;AAED,eAAO,MAAM,SAAS,sBAAsB,CAAC"}
|
package/dist/src/proto.js
CHANGED
|
@@ -38,9 +38,9 @@ export function $service(ctx, target) {
|
|
|
38
38
|
* @param ctx - decorator context
|
|
39
39
|
* @param target - target decorator namespace
|
|
40
40
|
*/
|
|
41
|
-
export
|
|
41
|
+
export const $package = (ctx, target, details) => {
|
|
42
42
|
ctx.program.stateMap(state.package).set(target, details);
|
|
43
|
-
}
|
|
43
|
+
};
|
|
44
44
|
/**
|
|
45
45
|
* Determines whether a type represents a Protobuf map.
|
|
46
46
|
*
|
|
@@ -63,7 +63,7 @@ export function $_map(ctx, target) {
|
|
|
63
63
|
export function $externRef(ctx, target, path, name) {
|
|
64
64
|
ctx.program.stateMap(state.externRef).set(target, [path.value, name.value]);
|
|
65
65
|
}
|
|
66
|
-
export
|
|
66
|
+
export const $stream = (ctx, target, mode) => {
|
|
67
67
|
const emitStreamingMode = {
|
|
68
68
|
Duplex: 3 /* StreamingMode.Duplex */,
|
|
69
69
|
In: 2 /* StreamingMode.In */,
|
|
@@ -71,7 +71,7 @@ export function $stream(ctx, target, mode) {
|
|
|
71
71
|
None: 0 /* StreamingMode.None */,
|
|
72
72
|
}[mode.name];
|
|
73
73
|
ctx.program.stateMap(state.stream).set(target, emitStreamingMode);
|
|
74
|
-
}
|
|
74
|
+
};
|
|
75
75
|
function getTuple(program, t) {
|
|
76
76
|
if (t.kind !== "Tuple" || t.values.some((v) => v.kind !== "Number") || t.values.length !== 2) {
|
|
77
77
|
reportDiagnostic(program, {
|
|
@@ -82,15 +82,15 @@ function getTuple(program, t) {
|
|
|
82
82
|
}
|
|
83
83
|
return Object.assign(t.values.map((v) => v.value), { type: t });
|
|
84
84
|
}
|
|
85
|
-
export
|
|
85
|
+
export const $reserve = (ctx, target, ...reservations) => {
|
|
86
86
|
const finalReservations = reservations
|
|
87
87
|
.map((reservation) => typeof reservation === "object" ? getTuple(ctx.program, reservation) : reservation)
|
|
88
88
|
.filter((v) => v != null);
|
|
89
89
|
ctx.program.stateMap(state.reserve).set(target, finalReservations);
|
|
90
|
-
}
|
|
91
|
-
export
|
|
90
|
+
};
|
|
91
|
+
export const $message = (ctx, target) => {
|
|
92
92
|
ctx.program.stateSet(state.message).add(target);
|
|
93
|
-
}
|
|
93
|
+
};
|
|
94
94
|
/**
|
|
95
95
|
* Decorate a model property with a field index. Field indices are required for all fields of emitted messages.
|
|
96
96
|
*
|
|
@@ -99,7 +99,7 @@ export function $message(ctx, target) {
|
|
|
99
99
|
* @param fieldIndex
|
|
100
100
|
* @returns
|
|
101
101
|
*/
|
|
102
|
-
export
|
|
102
|
+
export const $field = (ctx, target, fieldIndex) => {
|
|
103
103
|
if (!Number.isInteger(fieldIndex) || fieldIndex <= 0) {
|
|
104
104
|
reportDiagnostic(ctx.program, {
|
|
105
105
|
code: "field-index",
|
|
@@ -135,7 +135,7 @@ export function $field(ctx, target, fieldIndex) {
|
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
ctx.program.stateMap(state.fieldIndex).set(target, fieldIndex);
|
|
138
|
-
}
|
|
138
|
+
};
|
|
139
139
|
/**
|
|
140
140
|
* Emitter main function.
|
|
141
141
|
*
|
package/dist/src/proto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proto.js","sourceRoot":"","sources":["../../src/proto.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,
|
|
1
|
+
{"version":3,"file":"proto.js","sourceRoot":"","sources":["../../src/proto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DecoratorContext,
|
|
3
|
+
Interface,
|
|
4
|
+
ModelProperty,
|
|
5
|
+
Namespace,
|
|
6
|
+
Operation,
|
|
7
|
+
Type,
|
|
8
|
+
} from "@typespec/compiler";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Declares that a model is a Protobuf message.
|
|
12
|
+
*
|
|
13
|
+
* Messages can be detected automatically if either of the following two conditions are met:
|
|
14
|
+
*
|
|
15
|
+
* - The model has a `@field` annotation on all of its properties.
|
|
16
|
+
* - The model is referenced by any service operation.
|
|
17
|
+
*
|
|
18
|
+
* This decorator will force the emitter to check and emit a model.
|
|
19
|
+
*/
|
|
20
|
+
export type MessageDecorator = (context: DecoratorContext, target: Type) => void;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Defines the field index of a model property for conversion to a Protobuf
|
|
24
|
+
* message.
|
|
25
|
+
*
|
|
26
|
+
* The field index of a Protobuf message must:
|
|
27
|
+
* - fall between 1 and 2<sup>29</sup> - 1, inclusive.
|
|
28
|
+
* - not fall within the implementation reserved range of 19000 to 19999, inclusive.
|
|
29
|
+
* - not fall within any range that was [marked reserved](#
|
|
30
|
+
*
|
|
31
|
+
* @TypeSpec .Protobuf.reserve).
|
|
32
|
+
*
|
|
33
|
+
* #### API Compatibility Note
|
|
34
|
+
*
|
|
35
|
+
* Fields are accessed by index, so changing the index of a field is an API breaking change.
|
|
36
|
+
*
|
|
37
|
+
* #### Encoding
|
|
38
|
+
*
|
|
39
|
+
* Field indices between 1 and 15 are encoded using a single byte, while field indices from 16 through 2047 require two
|
|
40
|
+
* bytes, so those indices between 1 and 15 should be preferred and reserved for elements that are frequently or always
|
|
41
|
+
* set in the message. See the [Protobuf binary format](https://protobuf.dev/programming-guides/encoding/).
|
|
42
|
+
* @param index The whole-number index of the field.
|
|
43
|
+
* @example
|
|
44
|
+
* ```typespec
|
|
45
|
+
* model ExampleMessage {
|
|
46
|
+
* @field(1)
|
|
47
|
+
* test: string;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export type FieldDecorator = (
|
|
52
|
+
context: DecoratorContext,
|
|
53
|
+
target: ModelProperty,
|
|
54
|
+
index: number
|
|
55
|
+
) => void;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reserve a field index, range, or name. If a field definition collides with a reservation, the emitter will produce
|
|
59
|
+
* an error.
|
|
60
|
+
*
|
|
61
|
+
* This decorator accepts multiple reservations. Each reservation is one of the following:
|
|
62
|
+
*
|
|
63
|
+
* - a `string`, in which case the reservation refers to a field name.
|
|
64
|
+
* - a `uint32`, in which case the reservation refers to a field index.
|
|
65
|
+
* - a tuple `[uint32, uint32]`, in which case the reservation refers to a field range that is _inclusive_ of both ends.
|
|
66
|
+
*
|
|
67
|
+
* Unlike in Protobuf, where field name and index reservations must be separated, you can mix string and numeric field
|
|
68
|
+
* reservations in a single `@reserve` call in TypeSpec.
|
|
69
|
+
*
|
|
70
|
+
* #### API Compatibility Note
|
|
71
|
+
*
|
|
72
|
+
* Field reservations prevent users of your Protobuf specification from using the given field names or indices. This can
|
|
73
|
+
* be useful if a field is removed, as it will further prevent adding a new, incompatible field and will prevent users
|
|
74
|
+
* from utilizing the field index at runtime in a way that may break compatibility with users of older specifications.
|
|
75
|
+
*
|
|
76
|
+
* See _[Protobuf Language Guide - Reserved Fields](https://protobuf.dev/programming-guides/proto3/#reserved)_ for more
|
|
77
|
+
* information.
|
|
78
|
+
*
|
|
79
|
+
* @param reservations a list of field reservations
|
|
80
|
+
* @example
|
|
81
|
+
* ```typespec
|
|
82
|
+
* // Reserve the fields 8-15 inclusive, 100, and the field name "test" within a model.
|
|
83
|
+
* @reserve([8, 15], 100, "test")
|
|
84
|
+
* model Example {
|
|
85
|
+
* // ...
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export type ReserveDecorator = (
|
|
90
|
+
context: DecoratorContext,
|
|
91
|
+
target: Type,
|
|
92
|
+
...reservations: (string | unknown | number)[]
|
|
93
|
+
) => void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Declares that a TypeSpec interface constitutes a Protobuf service. The contents of the interface will be converted to
|
|
97
|
+
* a `service` declaration in the resulting Protobuf file.
|
|
98
|
+
*/
|
|
99
|
+
export type ServiceDecorator = (context: DecoratorContext, target: Interface) => void;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Declares that a TypeSpec namespace constitutes a Protobuf package. The contents of the namespace will be emitted to a
|
|
103
|
+
* single Protobuf file.
|
|
104
|
+
*
|
|
105
|
+
* @param details the optional details of the package
|
|
106
|
+
*/
|
|
107
|
+
export type PackageDecorator = (
|
|
108
|
+
context: DecoratorContext,
|
|
109
|
+
target: Namespace,
|
|
110
|
+
details?: Type
|
|
111
|
+
) => void;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Set the streaming mode of an operation. See [StreamMode](./data-types#TypeSpec.Protobuf.StreamMode) for more information.
|
|
115
|
+
*
|
|
116
|
+
* @param mode The streaming mode to apply to this operation.
|
|
117
|
+
* @example
|
|
118
|
+
* ```typespec
|
|
119
|
+
* @stream(StreamMode.Out)
|
|
120
|
+
* op logs(...LogsRequest): LogEvent;
|
|
121
|
+
* ```
|
|
122
|
+
* @example
|
|
123
|
+
* ```typespec
|
|
124
|
+
* @stream(StreamMode.Duplex)
|
|
125
|
+
* op connectToMessageService(...Message): Message;
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export type StreamDecorator = (context: DecoratorContext, target: Operation, mode: Type) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** An error here would mean that the decorator is not exported or doesn't have the right name. */
|
|
2
|
+
import { $field, $message, $package, $reserve, $service, $stream } from "@typespec/protobuf";
|
|
3
|
+
import {
|
|
4
|
+
FieldDecorator,
|
|
5
|
+
MessageDecorator,
|
|
6
|
+
PackageDecorator,
|
|
7
|
+
ReserveDecorator,
|
|
8
|
+
ServiceDecorator,
|
|
9
|
+
StreamDecorator,
|
|
10
|
+
} from "./TypeSpec.Protobuf.js";
|
|
11
|
+
|
|
12
|
+
type Decorators = {
|
|
13
|
+
$message: MessageDecorator;
|
|
14
|
+
$field: FieldDecorator;
|
|
15
|
+
$reserve: ReserveDecorator;
|
|
16
|
+
$service: ServiceDecorator;
|
|
17
|
+
$package: PackageDecorator;
|
|
18
|
+
$stream: StreamDecorator;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ... */
|
|
22
|
+
const _: Decorators = {
|
|
23
|
+
$message,
|
|
24
|
+
$field,
|
|
25
|
+
$reserve,
|
|
26
|
+
$service,
|
|
27
|
+
$package,
|
|
28
|
+
$stream,
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/protobuf",
|
|
3
|
-
"version": "0.55.0
|
|
3
|
+
"version": "0.55.0",
|
|
4
4
|
"author": "Microsoft Corporation",
|
|
5
5
|
"description": "TypeSpec library and emitter for Protobuf (gRPC)",
|
|
6
6
|
"homepage": "https://github.com/microsoft/typespec",
|
|
@@ -19,32 +19,36 @@
|
|
|
19
19
|
"grpc"
|
|
20
20
|
],
|
|
21
21
|
"main": "dist/src/index.js",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/src/index.js",
|
|
24
|
+
"./testing": "./dist/src/testing/index.js"
|
|
25
|
+
},
|
|
22
26
|
"type": "module",
|
|
23
27
|
"tspMain": "lib/proto.tsp",
|
|
24
28
|
"peerDependencies": {
|
|
25
|
-
"@typespec/compiler": "~0.
|
|
29
|
+
"@typespec/compiler": "~0.55.0"
|
|
26
30
|
},
|
|
27
31
|
"devDependencies": {
|
|
28
32
|
"@types/micromatch": "^4.0.6",
|
|
29
33
|
"@types/node": "~18.11.19",
|
|
30
|
-
"@
|
|
31
|
-
"@
|
|
32
|
-
"@typespec/eslint-plugin": "~0.54.0 || >=0.55.0-dev <0.55.0",
|
|
33
|
-
"@vitest/coverage-v8": "^1.2.2",
|
|
34
|
-
"@vitest/ui": "^1.2.2",
|
|
34
|
+
"@vitest/coverage-v8": "^1.4.0",
|
|
35
|
+
"@vitest/ui": "^1.4.0",
|
|
35
36
|
"c8": "^9.1.0",
|
|
36
|
-
"eslint": "^8.
|
|
37
|
+
"eslint": "^8.57.0",
|
|
37
38
|
"micromatch": "^4.0.5",
|
|
38
39
|
"rimraf": "~5.0.5",
|
|
39
|
-
"typescript": "~5.
|
|
40
|
-
"vitest": "^1.
|
|
40
|
+
"typescript": "~5.4.3",
|
|
41
|
+
"vitest": "^1.4.0",
|
|
42
|
+
"@typespec/compiler": "~0.55.0",
|
|
43
|
+
"@typespec/eslint-plugin": "~0.55.0",
|
|
44
|
+
"@typespec/eslint-config-typespec": "~0.55.0",
|
|
41
45
|
"@typespec/tspd": "~0.46.0"
|
|
42
46
|
},
|
|
43
|
-
"dependencies": {},
|
|
44
47
|
"scripts": {
|
|
45
48
|
"clean": "rimraf ./dist ./temp",
|
|
46
|
-
"build": "tsc -p .",
|
|
49
|
+
"build": "npm run gen-extern-signature && tsc -p .",
|
|
47
50
|
"watch": "tsc -p . --watch",
|
|
51
|
+
"gen-extern-signature": "tspd --enable-experimental gen-extern-signature .",
|
|
48
52
|
"test": "vitest run",
|
|
49
53
|
"test-official": "vitest run --coverage --reporter=junit --reporter=default --no-file-parallelism",
|
|
50
54
|
"lint": "eslint . --ext .ts --max-warnings=0",
|
package/src/proto.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
DecoratorContext,
|
|
6
6
|
EmitContext,
|
|
7
7
|
EmitOptionsFor,
|
|
8
|
-
EnumMember,
|
|
9
8
|
Interface,
|
|
10
9
|
Model,
|
|
11
10
|
ModelProperty,
|
|
@@ -19,6 +18,13 @@ import {
|
|
|
19
18
|
Type,
|
|
20
19
|
} from "@typespec/compiler";
|
|
21
20
|
|
|
21
|
+
import {
|
|
22
|
+
FieldDecorator,
|
|
23
|
+
MessageDecorator,
|
|
24
|
+
PackageDecorator,
|
|
25
|
+
ReserveDecorator,
|
|
26
|
+
StreamDecorator,
|
|
27
|
+
} from "../generated-defs/TypeSpec.Protobuf.js";
|
|
22
28
|
import { StreamingMode } from "./ast.js";
|
|
23
29
|
import { ProtobufEmitterOptions, reportDiagnostic, state, TypeSpecProtobufLibrary } from "./lib.js";
|
|
24
30
|
import { createProtobufEmitter } from "./transform/index.js";
|
|
@@ -67,9 +73,13 @@ export interface PackageDetails {
|
|
|
67
73
|
* @param ctx - decorator context
|
|
68
74
|
* @param target - target decorator namespace
|
|
69
75
|
*/
|
|
70
|
-
export
|
|
76
|
+
export const $package: PackageDecorator = (
|
|
77
|
+
ctx: DecoratorContext,
|
|
78
|
+
target: Namespace,
|
|
79
|
+
details?: Type
|
|
80
|
+
) => {
|
|
71
81
|
ctx.program.stateMap(state.package).set(target, details);
|
|
72
|
-
}
|
|
82
|
+
};
|
|
73
83
|
|
|
74
84
|
/**
|
|
75
85
|
* Determines whether a type represents a Protobuf map.
|
|
@@ -101,16 +111,16 @@ export function $externRef(
|
|
|
101
111
|
ctx.program.stateMap(state.externRef).set(target, [path.value, name.value]);
|
|
102
112
|
}
|
|
103
113
|
|
|
104
|
-
export
|
|
114
|
+
export const $stream: StreamDecorator = (ctx: DecoratorContext, target: Operation, mode: Type) => {
|
|
105
115
|
const emitStreamingMode = {
|
|
106
116
|
Duplex: StreamingMode.Duplex,
|
|
107
117
|
In: StreamingMode.In,
|
|
108
118
|
Out: StreamingMode.Out,
|
|
109
119
|
None: StreamingMode.None,
|
|
110
|
-
}[mode.name as string];
|
|
120
|
+
}[(mode as any).name as string];
|
|
111
121
|
|
|
112
122
|
ctx.program.stateMap(state.stream).set(target, emitStreamingMode);
|
|
113
|
-
}
|
|
123
|
+
};
|
|
114
124
|
|
|
115
125
|
function getTuple(program: Program, t: Type): [number, number] | null {
|
|
116
126
|
if (t.kind !== "Tuple" || t.values.some((v) => v.kind !== "Number") || t.values.length !== 2) {
|
|
@@ -130,23 +140,23 @@ function getTuple(program: Program, t: Type): [number, number] | null {
|
|
|
130
140
|
|
|
131
141
|
export type Reservation = string | number | ([number, number] & { type: Type });
|
|
132
142
|
|
|
133
|
-
export
|
|
143
|
+
export const $reserve: ReserveDecorator = (
|
|
134
144
|
ctx: DecoratorContext,
|
|
135
|
-
target:
|
|
136
|
-
...reservations: readonly (
|
|
137
|
-
) {
|
|
145
|
+
target: Type,
|
|
146
|
+
...reservations: readonly (unknown | number | string)[]
|
|
147
|
+
) => {
|
|
138
148
|
const finalReservations = reservations
|
|
139
149
|
.map((reservation) =>
|
|
140
|
-
typeof reservation === "object" ? getTuple(ctx.program, reservation) : reservation
|
|
150
|
+
typeof reservation === "object" ? getTuple(ctx.program, reservation as Type) : reservation
|
|
141
151
|
)
|
|
142
152
|
.filter((v) => v != null);
|
|
143
153
|
|
|
144
154
|
ctx.program.stateMap(state.reserve).set(target, finalReservations);
|
|
145
|
-
}
|
|
155
|
+
};
|
|
146
156
|
|
|
147
|
-
export
|
|
157
|
+
export const $message: MessageDecorator = (ctx: DecoratorContext, target: Type) => {
|
|
148
158
|
ctx.program.stateSet(state.message).add(target);
|
|
149
|
-
}
|
|
159
|
+
};
|
|
150
160
|
|
|
151
161
|
/**
|
|
152
162
|
* Decorate a model property with a field index. Field indices are required for all fields of emitted messages.
|
|
@@ -156,7 +166,11 @@ export function $message(ctx: DecoratorContext, target: Model) {
|
|
|
156
166
|
* @param fieldIndex
|
|
157
167
|
* @returns
|
|
158
168
|
*/
|
|
159
|
-
export
|
|
169
|
+
export const $field: FieldDecorator = (
|
|
170
|
+
ctx: DecoratorContext,
|
|
171
|
+
target: ModelProperty,
|
|
172
|
+
fieldIndex: number
|
|
173
|
+
) => {
|
|
160
174
|
if (!Number.isInteger(fieldIndex) || fieldIndex <= 0) {
|
|
161
175
|
reportDiagnostic(ctx.program, {
|
|
162
176
|
code: "field-index",
|
|
@@ -193,7 +207,7 @@ export function $field(ctx: DecoratorContext, target: ModelProperty, fieldIndex:
|
|
|
193
207
|
}
|
|
194
208
|
|
|
195
209
|
ctx.program.stateMap(state.fieldIndex).set(target, fieldIndex);
|
|
196
|
-
}
|
|
210
|
+
};
|
|
197
211
|
|
|
198
212
|
/**
|
|
199
213
|
* Emitter main function.
|