@typespec/events 0.60.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/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/generated-defs/TypeSpec.Events.d.ts +56 -0
- package/dist/generated-defs/TypeSpec.Events.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Events.js +2 -0
- package/dist/generated-defs/TypeSpec.Events.js.map +1 -0
- package/dist/generated-defs/TypeSpec.Events.ts-test.d.ts +2 -0
- package/dist/generated-defs/TypeSpec.Events.ts-test.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Events.ts-test.js +5 -0
- package/dist/generated-defs/TypeSpec.Events.ts-test.js.map +1 -0
- package/dist/src/decorators.d.ts +12 -0
- package/dist/src/decorators.d.ts.map +1 -0
- package/dist/src/decorators.js +19 -0
- package/dist/src/decorators.js.map +1 -0
- package/dist/src/experimental/get-event-definitions.d.ts +43 -0
- package/dist/src/experimental/get-event-definitions.d.ts.map +1 -0
- package/dist/src/experimental/get-event-definitions.js +165 -0
- package/dist/src/experimental/get-event-definitions.js.map +1 -0
- package/dist/src/experimental/index.d.ts +3 -0
- package/dist/src/experimental/index.d.ts.map +1 -0
- package/dist/src/experimental/index.js +2 -0
- package/dist/src/experimental/index.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib.d.ts +43 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +26 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/testing/index.d.ts +2 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +6 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/tsp-index.d.ts +10 -0
- package/dist/src/tsp-index.d.ts.map +1 -0
- package/dist/src/tsp-index.js +11 -0
- package/dist/src/tsp-index.js.map +1 -0
- package/dist/src/validate.d.ts +3 -0
- package/dist/src/validate.d.ts.map +1 -0
- package/dist/src/validate.js +12 -0
- package/dist/src/validate.js.map +1 -0
- package/lib/decorators.tsp +59 -0
- package/lib/main.tsp +2 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# @typespec/events
|
|
2
|
+
|
|
3
|
+
TypeSpec library providing events bindings
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @typespec/events
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Decorators
|
|
12
|
+
|
|
13
|
+
### TypeSpec.Events
|
|
14
|
+
|
|
15
|
+
- [`@contentType`](#@contenttype)
|
|
16
|
+
- [`@data`](#@data)
|
|
17
|
+
- [`@events`](#@events)
|
|
18
|
+
|
|
19
|
+
#### `@contentType`
|
|
20
|
+
|
|
21
|
+
Specifies the content type of the event envelope, event body, or event payload.
|
|
22
|
+
When applied to an event payload, that field must also have a corresponding `@data`
|
|
23
|
+
decorator.
|
|
24
|
+
|
|
25
|
+
```typespec
|
|
26
|
+
@TypeSpec.Events.contentType(contentType: valueof string)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
##### Target
|
|
30
|
+
|
|
31
|
+
`UnionVariant | ModelProperty`
|
|
32
|
+
|
|
33
|
+
##### Parameters
|
|
34
|
+
|
|
35
|
+
| Name | Type | Description |
|
|
36
|
+
| ----------- | ---------------- | ----------- |
|
|
37
|
+
| contentType | `valueof string` | |
|
|
38
|
+
|
|
39
|
+
##### Examples
|
|
40
|
+
|
|
41
|
+
```typespec
|
|
42
|
+
@events
|
|
43
|
+
union MixedEvents {
|
|
44
|
+
@contentType("application/json")
|
|
45
|
+
message: {
|
|
46
|
+
id: string,
|
|
47
|
+
text: string,
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
###### Specify the content type of the event payload.
|
|
53
|
+
|
|
54
|
+
```typespec
|
|
55
|
+
@events
|
|
56
|
+
union MixedEvents {
|
|
57
|
+
{
|
|
58
|
+
done: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
done: false,
|
|
62
|
+
@data @contentType("text/plain") value: string,
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### `@data`
|
|
68
|
+
|
|
69
|
+
Identifies the payload of an event.
|
|
70
|
+
Only one field in an event can be marked as the payload.
|
|
71
|
+
|
|
72
|
+
```typespec
|
|
73
|
+
@TypeSpec.Events.data
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
##### Target
|
|
77
|
+
|
|
78
|
+
`ModelProperty`
|
|
79
|
+
|
|
80
|
+
##### Parameters
|
|
81
|
+
|
|
82
|
+
None
|
|
83
|
+
|
|
84
|
+
##### Examples
|
|
85
|
+
|
|
86
|
+
```typespec
|
|
87
|
+
@events
|
|
88
|
+
union MixedEvents {
|
|
89
|
+
{
|
|
90
|
+
metadata: Record<string>,
|
|
91
|
+
@data payload: string,
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### `@events`
|
|
97
|
+
|
|
98
|
+
Specify that this union describes a set of events.
|
|
99
|
+
|
|
100
|
+
```typespec
|
|
101
|
+
@TypeSpec.Events.events
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
##### Target
|
|
105
|
+
|
|
106
|
+
`Union`
|
|
107
|
+
|
|
108
|
+
##### Parameters
|
|
109
|
+
|
|
110
|
+
None
|
|
111
|
+
|
|
112
|
+
##### Examples
|
|
113
|
+
|
|
114
|
+
```typespec
|
|
115
|
+
@events
|
|
116
|
+
union MixedEvents {
|
|
117
|
+
pingEvent: string,
|
|
118
|
+
doneEvent: "done",
|
|
119
|
+
}
|
|
120
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { DecoratorContext, ModelProperty, Union, UnionVariant } from "@typespec/compiler";
|
|
2
|
+
/**
|
|
3
|
+
* Specify that this union describes a set of events.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typespec
|
|
7
|
+
* @events
|
|
8
|
+
* union MixedEvents {
|
|
9
|
+
* pingEvent: string;
|
|
10
|
+
*
|
|
11
|
+
* doneEvent: "done";
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type EventsDecorator = (context: DecoratorContext, target: Union) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Specifies the content type of the event envelope, event body, or event payload.
|
|
18
|
+
* When applied to an event payload, that field must also have a corresponding `@data`
|
|
19
|
+
* decorator.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typespec
|
|
23
|
+
* @events union MixedEvents {
|
|
24
|
+
* @contentType("application/json")
|
|
25
|
+
* message: { id: string, text: string, }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
* @example Specify the content type of the event payload.
|
|
29
|
+
*
|
|
30
|
+
* ```typespec
|
|
31
|
+
* @events union MixedEvents {
|
|
32
|
+
* { done: true },
|
|
33
|
+
*
|
|
34
|
+
* { done: false, @data @contentType("text/plain") value: string,}
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export type ContentTypeDecorator = (context: DecoratorContext, target: UnionVariant | ModelProperty, contentType: string) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Identifies the payload of an event.
|
|
41
|
+
* Only one field in an event can be marked as the payload.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typespec
|
|
45
|
+
* @events union MixedEvents {
|
|
46
|
+
* { metadata: Record<string>, @data payload: string,}
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export type DataDecorator = (context: DecoratorContext, target: ModelProperty) => void;
|
|
51
|
+
export type TypeSpecEventsDecorators = {
|
|
52
|
+
events: EventsDecorator;
|
|
53
|
+
contentType: ContentTypeDecorator;
|
|
54
|
+
data: DataDecorator;
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=TypeSpec.Events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Events.d.ts","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE/F;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,KAAK,IAAI,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,YAAY,GAAG,aAAa,EACpC,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;AAEV;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;AAEvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,oBAAoB,CAAC;IAClC,IAAI,EAAE,aAAa,CAAC;CACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Events.js","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Events.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Events.ts-test.d.ts","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Events.ts-test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** An error here would mean that the decorator is not exported or doesn't have the right name. */
|
|
2
|
+
import { $decorators } from "@typespec/events";
|
|
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 _ = $decorators["TypeSpec.Events"];
|
|
5
|
+
//# sourceMappingURL=TypeSpec.Events.ts-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeSpec.Events.ts-test.js","sourceRoot":"","sources":["../../generated-defs/TypeSpec.Events.ts-test.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,qKAAqK;AACrK,MAAM,CAAC,GAA6B,WAAW,CAAC,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ModelProperty, type Union, type UnionVariant } from "@typespec/compiler";
|
|
2
|
+
import type { ContentTypeDecorator, DataDecorator, EventsDecorator } from "../generated-defs/TypeSpec.Events.js";
|
|
3
|
+
declare const isEvents: (program: import("@typespec/compiler").Program, type: Union) => boolean;
|
|
4
|
+
export declare const $eventsDecorator: EventsDecorator;
|
|
5
|
+
export { isEvents };
|
|
6
|
+
declare const getContentType: (program: import("@typespec/compiler").Program, type: ModelProperty | UnionVariant) => string | undefined;
|
|
7
|
+
export declare const $contentTypeDecorator: ContentTypeDecorator;
|
|
8
|
+
export { getContentType };
|
|
9
|
+
declare const isEventData: (program: import("@typespec/compiler").Program, type: ModelProperty) => boolean;
|
|
10
|
+
export declare const $dataDecorator: DataDecorator;
|
|
11
|
+
export { isEventData };
|
|
12
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,eAAe,EAChB,MAAM,sCAAsC,CAAC;AAG9C,QAAA,MAAO,QAAQ,yEAAgE,CAAC;AAEhF,eAAO,MAAM,gBAAgB,EAAE,eAE9B,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,QAAA,MAAO,cAAc,2GAEpB,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,oBAEnC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,QAAA,MAAO,WAAW,iFAAyE,CAAC;AAE5F,eAAO,MAAM,cAAc,EAAE,aAE5B,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {} from "@typespec/compiler";
|
|
2
|
+
import { unsafe_useStateMap, unsafe_useStateSet } from "@typespec/compiler/experimental";
|
|
3
|
+
import { EventsStateKeys } from "./lib.js";
|
|
4
|
+
const [isEvents, setEvents] = unsafe_useStateSet(EventsStateKeys.events);
|
|
5
|
+
export const $eventsDecorator = (context, target) => {
|
|
6
|
+
setEvents(context.program, target);
|
|
7
|
+
};
|
|
8
|
+
export { isEvents };
|
|
9
|
+
const [getContentType, setContentType] = unsafe_useStateMap(EventsStateKeys.contentType);
|
|
10
|
+
export const $contentTypeDecorator = (context, target, contentType) => {
|
|
11
|
+
setContentType(context.program, target, contentType);
|
|
12
|
+
};
|
|
13
|
+
export { getContentType };
|
|
14
|
+
const [isEventData, setEventData] = unsafe_useStateSet(EventsStateKeys.data);
|
|
15
|
+
export const $dataDecorator = (context, target) => {
|
|
16
|
+
setEventData(context.program, target);
|
|
17
|
+
};
|
|
18
|
+
export { isEventData };
|
|
19
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAMzF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,kBAAkB,CAAQ,eAAe,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,CAAC,MAAM,gBAAgB,GAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACnE,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC,GAAG,kBAAkB,CACzD,eAAe,CAAC,WAAW,CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE;IAC1F,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,kBAAkB,CAAgB,eAAe,CAAC,IAAI,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,cAAc,GAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC/D,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type DiagnosticResult, type Program, type Type, type Union, type UnionVariant } from "@typespec/compiler";
|
|
2
|
+
export declare function getEventDefinitions(program: Program, target: Union): DiagnosticResult<EventDefinition[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Represents the definition of an event.
|
|
5
|
+
*/
|
|
6
|
+
export interface EventDefinition {
|
|
7
|
+
/**
|
|
8
|
+
* The name of the event type.
|
|
9
|
+
* This may be used when the underlying event protocol supports event types
|
|
10
|
+
* out-of-band from the event evelope or event payload.
|
|
11
|
+
*/
|
|
12
|
+
readonly eventType?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The root variant of the union that represents the event.
|
|
15
|
+
*/
|
|
16
|
+
readonly root: UnionVariant;
|
|
17
|
+
/**
|
|
18
|
+
* Indicates whether the `type` describes an event envelope
|
|
19
|
+
* with a separate event payload.
|
|
20
|
+
*/
|
|
21
|
+
readonly isEventEnvelope: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The type of the event.
|
|
24
|
+
* This represents an event envelope if `isEventEnvelope` is `true`.
|
|
25
|
+
*/
|
|
26
|
+
readonly type: Type;
|
|
27
|
+
/**
|
|
28
|
+
* The content type of the event.
|
|
29
|
+
* This represents the content type of the event envelope if `isEventEnvelope` is `true`.
|
|
30
|
+
*/
|
|
31
|
+
readonly contentType?: string;
|
|
32
|
+
/**
|
|
33
|
+
* The type of the event payload.
|
|
34
|
+
* This matches `type` if `isEventEnvelope` is `false`.
|
|
35
|
+
*/
|
|
36
|
+
readonly payloadType: Type;
|
|
37
|
+
/**
|
|
38
|
+
* The content type of the event payload.
|
|
39
|
+
* This matches `contentType` if `isEventEnvelope` is `false`.
|
|
40
|
+
*/
|
|
41
|
+
readonly payloadContentType?: string;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=get-event-definitions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-event-definitions.d.ts","sourceRoot":"","sources":["../../../src/experimental/get-event-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EAGrB,KAAK,OAAO,EAEZ,KAAK,IAAI,EACT,KAAK,KAAK,EACV,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AA0L5B,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,KAAK,GACZ,gBAAgB,CAAC,eAAe,EAAE,CAAC,CAUrC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createDiagnosticCollector, navigateType, } from "@typespec/compiler";
|
|
2
|
+
import { getContentType, isEventData } from "../decorators.js";
|
|
3
|
+
import { createDiagnostic } from "../lib.js";
|
|
4
|
+
function validateContentType(program, target) {
|
|
5
|
+
const contentType = getContentType(program, target);
|
|
6
|
+
if (!contentType || isEventData(program, target))
|
|
7
|
+
return;
|
|
8
|
+
return createDiagnostic({
|
|
9
|
+
code: "invalid-content-type-target",
|
|
10
|
+
target,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function stringifyPropertyPath(path) {
|
|
14
|
+
return path
|
|
15
|
+
.map((p) => {
|
|
16
|
+
switch (p.kind) {
|
|
17
|
+
case "ModelProperty":
|
|
18
|
+
return p.name;
|
|
19
|
+
case "Tuple":
|
|
20
|
+
return "[]";
|
|
21
|
+
case "Model":
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.join(".");
|
|
27
|
+
}
|
|
28
|
+
function getEventDefinition(program, target) {
|
|
29
|
+
const diagnostics = createDiagnosticCollector();
|
|
30
|
+
// If the variant has a name, that may be used for out-of-band event types.
|
|
31
|
+
const eventType = typeof target.name === "string" ? target.name : undefined;
|
|
32
|
+
const envelopeContentType = getContentType(program, target);
|
|
33
|
+
let payloadType;
|
|
34
|
+
let payloadContentType;
|
|
35
|
+
let pathToPayload = "";
|
|
36
|
+
// Keeps track of if we're in a Record or Array.
|
|
37
|
+
let indexerDepth = 0;
|
|
38
|
+
// Keeps track of the path from the target to the current model property.
|
|
39
|
+
const currentPropertyPath = [];
|
|
40
|
+
// Keeps track of the types that have a descendant that leads to the event payload.
|
|
41
|
+
const typesThatChainToPayload = new Set();
|
|
42
|
+
// Look for a model property that is decorated with `@data`.
|
|
43
|
+
// This property will be used as the event payload.
|
|
44
|
+
// It can only be applied once within an event, and if it is not found,
|
|
45
|
+
// the target type is the payload.
|
|
46
|
+
navigateType(target.type, {
|
|
47
|
+
modelProperty(prop) {
|
|
48
|
+
currentPropertyPath.push(prop);
|
|
49
|
+
const contentTypeDiagnostic = validateContentType(program, prop);
|
|
50
|
+
if (contentTypeDiagnostic) {
|
|
51
|
+
diagnostics.add(contentTypeDiagnostic);
|
|
52
|
+
}
|
|
53
|
+
// This detects the scenario where a model that contains a `@data` property
|
|
54
|
+
// is referenced multiple times directly or indirectly by the target event.
|
|
55
|
+
if (typesThatChainToPayload.has(prop.type)) {
|
|
56
|
+
diagnostics.add(createDiagnostic({
|
|
57
|
+
code: "multiple-event-payloads",
|
|
58
|
+
format: {
|
|
59
|
+
dataPath: pathToPayload,
|
|
60
|
+
currentPath: stringifyPropertyPath(currentPropertyPath),
|
|
61
|
+
},
|
|
62
|
+
target,
|
|
63
|
+
}));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Haven't found a payload property yet, move on.
|
|
67
|
+
if (!isEventData(program, prop))
|
|
68
|
+
return;
|
|
69
|
+
// Mark all the types in the current path as having a descendant that leads to the payload.
|
|
70
|
+
currentPropertyPath.forEach((p) => {
|
|
71
|
+
if (p.kind === "ModelProperty") {
|
|
72
|
+
typesThatChainToPayload.add(p.type);
|
|
73
|
+
}
|
|
74
|
+
else if (p.kind === "Model" || p.kind === "Tuple") {
|
|
75
|
+
typesThatChainToPayload.add(p);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// Found the payload property but it's referenced indirectly by
|
|
79
|
+
// a Record or Array, which implies there would be more than 1 payload.
|
|
80
|
+
if (indexerDepth > 0) {
|
|
81
|
+
diagnostics.add(createDiagnostic({
|
|
82
|
+
code: "multiple-event-payloads",
|
|
83
|
+
messageId: "payloadInIndexedModel",
|
|
84
|
+
format: {
|
|
85
|
+
dataPath: stringifyPropertyPath(currentPropertyPath.slice(0, -1)),
|
|
86
|
+
},
|
|
87
|
+
target,
|
|
88
|
+
}));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// A payload type was previously found, but only one is allowed.
|
|
92
|
+
if (payloadType) {
|
|
93
|
+
diagnostics.add(createDiagnostic({
|
|
94
|
+
code: "multiple-event-payloads",
|
|
95
|
+
format: {
|
|
96
|
+
dataPath: pathToPayload,
|
|
97
|
+
currentPath: stringifyPropertyPath(currentPropertyPath),
|
|
98
|
+
},
|
|
99
|
+
target,
|
|
100
|
+
}));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// A payload property was found.
|
|
104
|
+
payloadType = prop.type;
|
|
105
|
+
payloadContentType = getContentType(program, prop);
|
|
106
|
+
pathToPayload = stringifyPropertyPath(currentPropertyPath);
|
|
107
|
+
},
|
|
108
|
+
exitModelProperty() {
|
|
109
|
+
currentPropertyPath.pop();
|
|
110
|
+
},
|
|
111
|
+
tuple(tuple) {
|
|
112
|
+
currentPropertyPath.push(tuple);
|
|
113
|
+
// Check if any of the tuple values have already been marked as a payload/payload ancestor.
|
|
114
|
+
// They won't be visited again, so need to create diagnostic here.
|
|
115
|
+
tuple.values.forEach((value) => {
|
|
116
|
+
if (typesThatChainToPayload.has(value)) {
|
|
117
|
+
diagnostics.add(createDiagnostic({
|
|
118
|
+
code: "multiple-event-payloads",
|
|
119
|
+
format: {
|
|
120
|
+
dataPath: pathToPayload,
|
|
121
|
+
currentPath: stringifyPropertyPath(currentPropertyPath),
|
|
122
|
+
},
|
|
123
|
+
target,
|
|
124
|
+
}));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
exitTuple() {
|
|
130
|
+
currentPropertyPath.pop();
|
|
131
|
+
},
|
|
132
|
+
model(model) {
|
|
133
|
+
if (model.indexer) {
|
|
134
|
+
indexerDepth++;
|
|
135
|
+
}
|
|
136
|
+
currentPropertyPath.push(model);
|
|
137
|
+
},
|
|
138
|
+
exitModel(model) {
|
|
139
|
+
if (model.indexer) {
|
|
140
|
+
indexerDepth--;
|
|
141
|
+
}
|
|
142
|
+
currentPropertyPath.pop();
|
|
143
|
+
},
|
|
144
|
+
}, {});
|
|
145
|
+
const eventDefinition = {
|
|
146
|
+
eventType,
|
|
147
|
+
root: target,
|
|
148
|
+
isEventEnvelope: !!payloadType,
|
|
149
|
+
type: target.type,
|
|
150
|
+
contentType: envelopeContentType,
|
|
151
|
+
payloadType: payloadType ?? target.type,
|
|
152
|
+
payloadContentType: payloadType ? payloadContentType : envelopeContentType,
|
|
153
|
+
};
|
|
154
|
+
return diagnostics.wrap(eventDefinition);
|
|
155
|
+
}
|
|
156
|
+
export function getEventDefinitions(program, target) {
|
|
157
|
+
const diagnostics = createDiagnosticCollector();
|
|
158
|
+
// 1. Iterate over each variant of the action
|
|
159
|
+
const events = [];
|
|
160
|
+
target.variants.forEach((variant) => {
|
|
161
|
+
events.push(diagnostics.pipe(getEventDefinition(program, variant)));
|
|
162
|
+
});
|
|
163
|
+
return diagnostics.wrap(events);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=get-event-definitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-event-definitions.js","sourceRoot":"","sources":["../../../src/experimental/get-event-definitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,IAAI,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC/F,YAAY,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,IAAI,0BAA0B,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const $lib: import("@typespec/compiler").TypeSpecLibrary<{
|
|
2
|
+
"invalid-content-type-target": {
|
|
3
|
+
readonly default: "@contentType can only be specified on the top-level event envelope, or the event payload marked with @data";
|
|
4
|
+
};
|
|
5
|
+
"multiple-event-payloads": {
|
|
6
|
+
readonly default: import("@typespec/compiler").CallableMessage<["dataPath", "currentPath"]>;
|
|
7
|
+
readonly payloadInIndexedModel: import("@typespec/compiler").CallableMessage<["dataPath"]>;
|
|
8
|
+
};
|
|
9
|
+
}, Record<string, any>, "data" | "events" | "contentType">;
|
|
10
|
+
export declare const reportDiagnostic: <C extends "invalid-content-type-target" | "multiple-event-payloads", M extends keyof {
|
|
11
|
+
"invalid-content-type-target": {
|
|
12
|
+
readonly default: "@contentType can only be specified on the top-level event envelope, or the event payload marked with @data";
|
|
13
|
+
};
|
|
14
|
+
"multiple-event-payloads": {
|
|
15
|
+
readonly default: import("@typespec/compiler").CallableMessage<["dataPath", "currentPath"]>;
|
|
16
|
+
readonly payloadInIndexedModel: import("@typespec/compiler").CallableMessage<["dataPath"]>;
|
|
17
|
+
};
|
|
18
|
+
}[C]>(program: import("@typespec/compiler").Program, diag: import("@typespec/compiler").DiagnosticReport<{
|
|
19
|
+
"invalid-content-type-target": {
|
|
20
|
+
readonly default: "@contentType can only be specified on the top-level event envelope, or the event payload marked with @data";
|
|
21
|
+
};
|
|
22
|
+
"multiple-event-payloads": {
|
|
23
|
+
readonly default: import("@typespec/compiler").CallableMessage<["dataPath", "currentPath"]>;
|
|
24
|
+
readonly payloadInIndexedModel: import("@typespec/compiler").CallableMessage<["dataPath"]>;
|
|
25
|
+
};
|
|
26
|
+
}, C, M>) => void, createDiagnostic: <C extends "invalid-content-type-target" | "multiple-event-payloads", M extends keyof {
|
|
27
|
+
"invalid-content-type-target": {
|
|
28
|
+
readonly default: "@contentType can only be specified on the top-level event envelope, or the event payload marked with @data";
|
|
29
|
+
};
|
|
30
|
+
"multiple-event-payloads": {
|
|
31
|
+
readonly default: import("@typespec/compiler").CallableMessage<["dataPath", "currentPath"]>;
|
|
32
|
+
readonly payloadInIndexedModel: import("@typespec/compiler").CallableMessage<["dataPath"]>;
|
|
33
|
+
};
|
|
34
|
+
}[C]>(diag: import("@typespec/compiler").DiagnosticReport<{
|
|
35
|
+
"invalid-content-type-target": {
|
|
36
|
+
readonly default: "@contentType can only be specified on the top-level event envelope, or the event payload marked with @data";
|
|
37
|
+
};
|
|
38
|
+
"multiple-event-payloads": {
|
|
39
|
+
readonly default: import("@typespec/compiler").CallableMessage<["dataPath", "currentPath"]>;
|
|
40
|
+
readonly payloadInIndexedModel: import("@typespec/compiler").CallableMessage<["dataPath"]>;
|
|
41
|
+
};
|
|
42
|
+
}, C, M>) => import("@typespec/compiler").Diagnostic, EventsStateKeys: Record<"data" | "events" | "contentType", symbol>;
|
|
43
|
+
//# sourceMappingURL=lib.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI;;;;;;;;0DAuBf,CAAC;AAEH,eAAO,MAAQ,gBAAgB;;;;;;;;;;;;;;;;mBAAE,gBAAgB;;;;;;;;;;;;;;;;sDAAa,eAAe,mDAAS,CAAC"}
|
package/dist/src/lib.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createTypeSpecLibrary, paramMessage } from "@typespec/compiler";
|
|
2
|
+
export const $lib = createTypeSpecLibrary({
|
|
3
|
+
name: "@typespec/events",
|
|
4
|
+
diagnostics: {
|
|
5
|
+
"invalid-content-type-target": {
|
|
6
|
+
severity: "error",
|
|
7
|
+
messages: {
|
|
8
|
+
default: `@contentType can only be specified on the top-level event envelope, or the event payload marked with @data`,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
"multiple-event-payloads": {
|
|
12
|
+
severity: "error",
|
|
13
|
+
messages: {
|
|
14
|
+
default: paramMessage `Event payload already applied to ${"dataPath"} but also exists under ${"currentPath"}`,
|
|
15
|
+
payloadInIndexedModel: paramMessage `Event payload applied from inside a Record or Array at ${"dataPath"}`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
state: {
|
|
20
|
+
events: { description: "State for the @events decorator." },
|
|
21
|
+
contentType: { description: "State for the @contentType decorator." },
|
|
22
|
+
data: { description: "State for the @data decorator." },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
export const { reportDiagnostic, createDiagnostic, stateKeys: EventsStateKeys } = $lib;
|
|
26
|
+
//# sourceMappingURL=lib.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzE,MAAM,CAAC,MAAM,IAAI,GAAG,qBAAqB,CAAC;IACxC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE;QACX,6BAA6B,EAAE;YAC7B,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,4GAA4G;aACtH;SACF;QACD,yBAAyB,EAAE;YACzB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,YAAY,CAAA,oCAAoC,UAAU,0BAA0B,aAAa,EAAE;gBAE5G,qBAAqB,EAAE,YAAY,CAAA,0DAA0D,UAAU,EAAE;aAC1G;SACF;KACF;IACD,KAAK,EAAE;QACL,MAAM,EAAE,EAAE,WAAW,EAAE,kCAAkC,EAAE;QAC3D,WAAW,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE;QACrE,IAAI,EAAE,EAAE,WAAW,EAAE,gCAAgC,EAAE;KACxD;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,0DAG5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;IACjD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,MAAM,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;CACxD,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { $lib } from "./lib.js";
|
|
2
|
+
export { $onValidate } from "./validate.js";
|
|
3
|
+
export declare const $decorators: {
|
|
4
|
+
"TypeSpec.Events": {
|
|
5
|
+
contentType: import("../generated-defs/TypeSpec.Events.js").ContentTypeDecorator;
|
|
6
|
+
data: import("../generated-defs/TypeSpec.Events.js").DataDecorator;
|
|
7
|
+
events: import("../generated-defs/TypeSpec.Events.js").EventsDecorator;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=tsp-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsp-index.d.ts","sourceRoot":"","sources":["../../src/tsp-index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { $contentTypeDecorator, $dataDecorator, $eventsDecorator } from "./decorators.js";
|
|
2
|
+
export { $lib } from "./lib.js";
|
|
3
|
+
export { $onValidate } from "./validate.js";
|
|
4
|
+
export const $decorators = {
|
|
5
|
+
"TypeSpec.Events": {
|
|
6
|
+
contentType: $contentTypeDecorator,
|
|
7
|
+
data: $dataDecorator,
|
|
8
|
+
events: $eventsDecorator,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=tsp-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsp-index.js","sourceRoot":"","sources":["../../src/tsp-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE1F,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iBAAiB,EAAE;QACjB,WAAW,EAAE,qBAAqB;QAClC,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,gBAAgB;KACzB;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAS,MAAM,oBAAoB,CAAC;AAGzD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAE3C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { unsafe_getEventDefinitions } from "./experimental/index.js";
|
|
2
|
+
import { EventsStateKeys } from "./lib.js";
|
|
3
|
+
export function $onValidate(program) {
|
|
4
|
+
checkForInvalidEvents(program);
|
|
5
|
+
}
|
|
6
|
+
function checkForInvalidEvents(program) {
|
|
7
|
+
program.stateSet(EventsStateKeys.events).forEach((events) => {
|
|
8
|
+
const [, diagnostics] = unsafe_getEventDefinitions(program, events);
|
|
9
|
+
program.reportDiagnostics(diagnostics);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,qBAAqB,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC1D,MAAM,CAAC,EAAE,WAAW,CAAC,GAAG,0BAA0B,CAAC,OAAO,EAAE,MAAe,CAAC,CAAC;QAC7E,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
using TypeSpec.Reflection;
|
|
2
|
+
|
|
3
|
+
namespace TypeSpec.Events;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Specify that this union describes a set of events.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* ```typespec
|
|
11
|
+
* @events
|
|
12
|
+
* union MixedEvents {
|
|
13
|
+
* pingEvent: string;
|
|
14
|
+
*
|
|
15
|
+
* doneEvent: "done";
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
extern dec events(target: Union);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Specifies the content type of the event envelope, event body, or event payload.
|
|
23
|
+
* When applied to an event payload, that field must also have a corresponding `@data`
|
|
24
|
+
* decorator.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
*
|
|
28
|
+
* ```typespec
|
|
29
|
+
* @events union MixedEvents {
|
|
30
|
+
* @contentType("application/json")
|
|
31
|
+
* message: { id: string, text: string, }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Specify the content type of the event payload.
|
|
36
|
+
*
|
|
37
|
+
* ```typespec
|
|
38
|
+
* @events union MixedEvents {
|
|
39
|
+
* { done: true },
|
|
40
|
+
*
|
|
41
|
+
* { done: false, @data @contentType("text/plain") value: string,}
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
extern dec contentType(target: UnionVariant | ModelProperty, contentType: valueof string);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Identifies the payload of an event.
|
|
49
|
+
* Only one field in an event can be marked as the payload.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
*
|
|
53
|
+
* ```typespec
|
|
54
|
+
* @events union MixedEvents {
|
|
55
|
+
* { metadata: Record<string>, @data payload: string,}
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
extern dec data(target: ModelProperty);
|
package/lib/main.tsp
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@typespec/events",
|
|
3
|
+
"version": "0.60.0",
|
|
4
|
+
"author": "Microsoft Corporation",
|
|
5
|
+
"description": "TypeSpec library providing events bindings",
|
|
6
|
+
"homepage": "https://typespec.io",
|
|
7
|
+
"readme": "https://github.com/microsoft/typespec/blob/main/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
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "dist/src/index.js",
|
|
21
|
+
"tspMain": "lib/main.tsp",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/src/index.js",
|
|
24
|
+
"./testing": "./dist/src/testing/index.js",
|
|
25
|
+
"./experimental": {
|
|
26
|
+
"types": "./dist/src/experimental/index.d.ts",
|
|
27
|
+
"default": "./dist/src/experimental/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"lib/*.tsp",
|
|
35
|
+
"dist/**",
|
|
36
|
+
"!dist/test/**"
|
|
37
|
+
],
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@typespec/compiler": "~0.60.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "~22.7.1",
|
|
43
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
44
|
+
"@vitest/ui": "^2.1.1",
|
|
45
|
+
"c8": "^10.1.2",
|
|
46
|
+
"rimraf": "~6.0.1",
|
|
47
|
+
"typescript": "~5.6.2",
|
|
48
|
+
"vitest": "^2.1.1",
|
|
49
|
+
"@typespec/library-linter": "~0.60.0",
|
|
50
|
+
"@typespec/compiler": "~0.60.1",
|
|
51
|
+
"@typespec/tspd": "~0.46.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"clean": "rimraf ./dist ./temp",
|
|
55
|
+
"build": "npm run gen-extern-signature && tsc -p . && npm run lint-typespec-library",
|
|
56
|
+
"watch": "tsc -p . --watch",
|
|
57
|
+
"gen-extern-signature": "tspd --enable-experimental gen-extern-signature .",
|
|
58
|
+
"lint-typespec-library": "tsp compile . --warn-as-error --import @typespec/library-linter --no-emit",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest -w",
|
|
61
|
+
"test:ui": "vitest --ui",
|
|
62
|
+
"test-official": "vitest run --coverage --reporter=junit --reporter=default --no-file-parallelism",
|
|
63
|
+
"lint": "eslint . --ext .ts --max-warnings=0",
|
|
64
|
+
"lint:fix": "eslint . --fix --ext .ts",
|
|
65
|
+
"regen-docs": "tspd doc . --enable-experimental --output-dir ../../docs/libraries/events/reference"
|
|
66
|
+
}
|
|
67
|
+
}
|