@typespec/rest 0.41.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 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,134 @@
1
+ # TypeSpec REST Library
2
+
3
+ This package provides [TypeSpec](https://github.com/microsoft/TypeSpec) decorators, models, and interfaces to describe APIs using the [REST style](https://en.wikipedia.org/wiki/Representational_state_transfer). These building blocks make defining REST resources and operations based on standard patterns extremely simple.
4
+
5
+ ## Install
6
+
7
+ In your TypeSpec project root
8
+
9
+ ```bash
10
+ npm install @typespec/rest
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```TypeSpec
16
+ import "@typespec/rest";
17
+
18
+ using TypeSpec.Rest;
19
+ ```
20
+
21
+ See [Http and rest](https://microsoft.github.io/typespec/docs/standard-library/rest/).
22
+
23
+ ## Library Tour
24
+
25
+ `@typespec/rest` library defines of the following artifacts:
26
+
27
+ - [TypeSpec HTTP/Rest Library](#typespec-httprest-library)
28
+ - [Install](#install)
29
+ - [Usage](#usage)
30
+ - [Library Tour](#library-tour)
31
+ - [Models](#models)
32
+ - [Decorators](#decorators)
33
+ - [Interfaces](#interfaces)
34
+ - [See also](#see-also)
35
+
36
+ ## Models
37
+
38
+ | Model | Notes |
39
+ | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
40
+ | KeysOf<T> | Dynamically gathers keys of the model type T. |
41
+ | Page<T> | A model defines page of T which includes an array of T and optional next link. |
42
+ | ParentKeysOf<T> | Dynamically gathers parent keys of the model type T, which are referenced with `@parentResource` decorator. |
43
+ | ResourceError | The default error response for resource operations that includes <br> `code: int32` and `message string`. |
44
+ | ResourceParameters&lt;TResource> | Represents operation parameters for resource TResource. Default to KeysOf&lt;T>. |
45
+ | ResourceCollectionParameters&lt;TResource> | Represents collection operation parameters for resource TResource. Default to ParentKeysOf&lt;T> |
46
+ | ResourceCreatedResponse&lt;T> | Resource create operation completed successfully. |
47
+ | ResourceDeletedResponse | Resource deleted successfully. |
48
+
49
+ ## Decorators
50
+
51
+ The `@typespec/rest` library defines the following decorators in `TypeSpec.Rest` namespace:
52
+
53
+ | Declarator | Scope | Syntax |
54
+ | ------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
55
+ | @discriminator | models | Syntax:<br> `@discriminator(kindString)` <br><br>Note:<br> `@discriminator` allows defining polymorphic models to be used by API as parameters and return types. In many strongly typed languages, they are expressed as inheritance. |
56
+ | @resource | Model | Syntax:<br> `@resource(collectionName)` <br><br>Note:<br> This decorator is to used to mark a model as a resource type with a name for the type's collection. |
57
+ | @readsResource | operations | Syntax:<br> `@readsResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the Read operation for a particular resource. |
58
+ | @createsResource | operations | Syntax:<br> `@createsResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the Create operation for a particular resource. |
59
+ | @createsOrUpdatesResource | operations | Syntax:<br> `@createsOrUpdatesResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the CreatesOrUpdate operation for a particular resource. |
60
+ | @updatesResource | operations | Syntax:<br> `@updatesResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the Update operation for a particular resource. |
61
+ | @deletesResource | operations | Syntax:<br> `@deletesResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the Delete operation for a particular resource. |
62
+ | @listsResource | operations | Syntax:<br> `@listsResource(modelType)` <br><br>Note:<br> This decorator is to used to signal the operation that is the List operation for a particular resource. |
63
+ | @parentResource | models | Syntax:<br> `@parentResource(parentModelTypeReference)` <br><br>Note:<br> `@parentResource` marks a model property with a reference to its parent resource type. The first argument should be a reference to a model type which will be treated as the parent type of the target model type. This will cause the `@key` properties of all parent types of the target type to show up in operations of the `Resource*<T>` interfaces defined in this library. |
64
+ | @segment | model properties, operation parameters | Syntax:<br> `@segment(segmentString)` <br><br>Note:<br>`@segment` defines the preceding path segment for a `@path` parameter in auto-generated routes. The first argument should be a string that will be inserted into the operation route before the path parameter's name field. For example: <br> `op getUser(@path @segment("users") userId: string): User` <br> will produce the route `/users/{userId}`. |
65
+ | @segmentOf | models | Syntax:<br> `@segment(segmentString)` <br><br>Note:<br>`@segmentOf` returns the URL segment of a given model if it has `@segment` and `@key` decorator. |
66
+ | @segmentSeparator | model properties, operation parameters, or operations | Syntax:<br> `@segmentSeparator(separatorString)` <br><br>Note:<br> `@segmentSeparator` defines the separator string that is inserted between the target's `@segment` and the preceding route path in auto-generated routes. <br> The first argument should be a string that will be inserted into the operation route before the target's `@segment` value. Can be a string of any length. Defaults to `/`. |
67
+ | @actionSeparator | model properties, operation parameters, or operations | Syntax:<br> `@actionSeparator(separatorString)` <br><br>Note:<br> `@actionSeparator` defines the separator string that is inserted before the action name in auto-generated routes for actions. |
68
+ | @autoRoute | operations | Syntax:<br> `@autoRoute()` <br><br>Note:<br>`@autoRoute` enables automatic route generation for an operation, namespace, or interface. <br> When applied to an operation, it automatically generates the operation's route based on path parameter metadata. When applied to a namespace or interface, it causes all operations under that scope to have auto-generated routes. |
69
+
70
+ ## Interfaces
71
+
72
+ These standard interfaces defines resource operations in basic building blocks that you can expose on the resources. You can use `extends` to compose the operations to meet the exact needs of your resource APIs.
73
+
74
+ For example, for below `Widget` model
75
+
76
+ ```
77
+ @resource("widgets")
78
+ model Widget {
79
+ @key id: string;
80
+ name: string;
81
+ }
82
+ ```
83
+
84
+ - `Widget` resource supports full CRUDL operations.
85
+
86
+ ```TypeSpec
87
+ interface WidgetService extends Resource.ResourceOperations<Widget, Error>;
88
+ ```
89
+
90
+ - `Widget` resource supports only CRD operations.
91
+
92
+ ```TypeSpec
93
+ interface WidgetService
94
+ extends Resource.ResourceRead<Widget, Error>,
95
+ Resource.ResourceCreate<Widget, Error>,
96
+ Resource.ResourceDelete<Widget, Error> {
97
+ }
98
+ ```
99
+
100
+ -
101
+
102
+ | Interfaces | Notes |
103
+ | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
104
+ | ResourceRead&lt;TResource, TError> | Resource GET operation |
105
+ | ResourceCreateOrUpdate&lt;TResource, TError> | Resource PUT operation |
106
+ | ResourceCreate&lt;TResource, TError> | Resource POST operation |
107
+ | ResourceUpdate&lt;TResource, TError> | Resource PATCH operation |
108
+ | ResourceDelete&lt;TResource, TError> | Resource DEL operation |
109
+ | ResourceList&lt;TResource, TError> | Resource LIST operation which is a GET operation from a parent resource. |
110
+ | ResourceInstanceOperations&lt;TResource, TError> | Combines resource GET + PATCH + DEL operations |
111
+ | ResourceCollectionOperations&lt;TResource, TError> | Combines resource POST + LIST operations |
112
+ | ResourceOperations&lt;TResource, TError> | Combines resource instance and collection operations. Includes GET + PATCH + DEL + POST + LIST |
113
+ | SingletonResourceRead&lt;TSingleton, TResource, TError> | Singleton resource GET operation. |
114
+ | SingletonResourceUpdate&lt;TSingleton, TResource, TError> | Singleton resource PATCH operation. |
115
+ | SingletonResourceOperations&lt;TSingleton, TResource, TError> | Combines resource GET + PATCH operations |
116
+ | ExtensionResourceRead&lt;TExtension, TResource, TError> | Extension resource GET operation. |
117
+ | ExtensionResourceCreateOrUpdate&lt;TExtension, TResource, TError> | Extension resource PUT operation |
118
+ | ExtensionResourceCreate&lt;TExtension, TResource, TError> | Extension resource POST operation |
119
+ | ExtensionResourceUpdate&lt;TExtension, TResource, TError> | Extension resource PATCH operation |
120
+ | ExtensionResourceDelete&lt;TExtension, TResource, TError> | Extension resource GET operation |
121
+ | ExtensionResourceList&lt;TExtension, TResource, TError> | Extension resource LIST operation which is a GET operation from a parent resource. |
122
+ | ExtensionResourceInstanceOperations&lt;TExtension, TResource, TError> | Combines extension resource GET + PATCH + DEL operations. |
123
+ | ExtensionResourceCollectionOperations&lt;TExtension, TResource, TError> | Combines extension resource POST + LIST operations. |
124
+ | ExtensionResourceOperations&lt;TExtension, TResource, TError> | Combines extension resource instance and collection operations. Includes GET + PATCH + DEL + POST + LIST operations. |
125
+
126
+ ## See also
127
+
128
+ - [REST example](https://cadlplayground.z22.web.core.windows.net/?c=aW1wb3J0ICJAY2FkbC1sYW5nL3Jlc3QiOwoKQHNlcnZpY2VUaXRsZSgiV2lkZ2V0IFPGFSIpCm5hbWVzcGFjZSBEZW1vxxg7Cgp1c2luZyBDYWRsLkh0dHA7zBFSZXN0OwoKbW9kZWwgx1J7CiAgQGtleSBpZDogc3RyaW5nOwogIHdlaWdodDogaW50MzLEEWNvbG9yOiAicmVkIiB8ICJibHVlIjsKfQoKQGVycm9yx1ZFxAzFVWNvZGXLQG1lc3NhZ2XKZH0KCmludGVyZuQAxOYAjecAxiBleHRlbmRzIFJlc291cmNl5AC5xQlPcGVyYXRpb25zPMYyLMZxPsVyQOQA0EByb3V0ZSgiY3VzdG9tR2V0IikgyQwoKTrHa%2BQAgA%3D%3D):
129
+ - [TypeSpec Getting Started](https://github.com/microsoft/typespec#getting-started)
130
+ - [TypeSpec Website](https://microsoft.github.io/typespec)
131
+
132
+ ```
133
+
134
+ ```
@@ -0,0 +1,5 @@
1
+ export declare const namespace = "TypeSpec.Rest";
2
+ export * from "./resource.js";
3
+ export * from "./rest.js";
4
+ export * from "./validate.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,kBAAkB,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ export const namespace = "TypeSpec.Rest";
2
+ export * from "./resource.js";
3
+ export * from "./rest.js";
4
+ export * from "./validate.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,eAAe,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { DecoratorContext, Type } from "@typespec/compiler";
2
+ export declare const namespace = "TypeSpec.Rest.Private";
3
+ export declare function $validateHasKey(context: DecoratorContext, target: Type, value: Type): void;
4
+ export declare function $validateIsError(context: DecoratorContext, target: Type, value: Type): void;
5
+ //# sourceMappingURL=internal-decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-decorators.d.ts","sourceRoot":"","sources":["../../src/internal-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,IAAI,EAEL,MAAM,oBAAoB,CAAC;AAI5B,eAAO,MAAM,SAAS,0BAA0B,CAAC;AAIjD,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,QAgBnF;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,QAgBpF"}
@@ -0,0 +1,43 @@
1
+ import { isErrorModel, validateDecoratorParamType, } from "@typespec/compiler";
2
+ import { createStateSymbol, reportDiagnostic } from "./lib.js";
3
+ import { getResourceTypeKey } from "./resource.js";
4
+ export const namespace = "TypeSpec.Rest.Private";
5
+ const validatedMissingKey = createStateSymbol("validatedMissing");
6
+ // Workaround for the lack of template constraints https://github.com/microsoft/typespec/issues/377
7
+ export function $validateHasKey(context, target, value) {
8
+ if (!validateDecoratorParamType(context.program, target, value, "Model")) {
9
+ return;
10
+ }
11
+ if (context.program.stateSet(validatedMissingKey).has(value)) {
12
+ return;
13
+ }
14
+ const resourceKey = getResourceTypeKey(context.program, value);
15
+ if (resourceKey === undefined) {
16
+ reportDiagnostic(context.program, {
17
+ code: "resource-missing-key",
18
+ format: { modelName: value.name },
19
+ target: value,
20
+ });
21
+ context.program.stateSet(validatedMissingKey).add(value);
22
+ }
23
+ }
24
+ const validatedErrorKey = createStateSymbol("validatedError");
25
+ // Workaround for the lack of template constraints https://github.com/microsoft/typespec/issues/377
26
+ export function $validateIsError(context, target, value) {
27
+ if (!validateDecoratorParamType(context.program, target, value, "Model")) {
28
+ return;
29
+ }
30
+ if (context.program.stateSet(validatedErrorKey).has(value)) {
31
+ return;
32
+ }
33
+ const isError = isErrorModel(context.program, value);
34
+ if (!isError) {
35
+ reportDiagnostic(context.program, {
36
+ code: "resource-missing-error",
37
+ format: { modelName: value.name },
38
+ target: value,
39
+ });
40
+ context.program.stateSet(validatedErrorKey).add(value);
41
+ }
42
+ }
43
+ //# sourceMappingURL=internal-decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-decorators.js","sourceRoot":"","sources":["../../src/internal-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EAEZ,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,CAAC,MAAM,SAAS,GAAG,uBAAuB,CAAC;AAEjD,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAClE,mGAAmG;AACnG,MAAM,UAAU,eAAe,CAAC,OAAyB,EAAE,MAAY,EAAE,KAAW;IAClF,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE;QACxE,OAAO;KACR;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QAC5D,OAAO;KACR;IACD,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/D,IAAI,WAAW,KAAK,SAAS,EAAE;QAC7B,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE;YAChC,IAAI,EAAE,sBAAsB;YAC5B,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE;YACjC,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KAC1D;AACH,CAAC;AAED,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;AAC9D,mGAAmG;AACnG,MAAM,UAAU,gBAAgB,CAAC,OAAyB,EAAE,MAAY,EAAE,KAAW;IACnF,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE;QACxE,OAAO;KACR;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QAC1D,OAAO;KACR;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE;QACZ,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE;YAChC,IAAI,EAAE,wBAAwB;YAC9B,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE;YACjC,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;KACxD;AACH,CAAC"}
@@ -0,0 +1,84 @@
1
+ declare const restLib: import("@typespec/compiler").TypeSpecLibrary<{
2
+ "not-key-type": {
3
+ readonly default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)";
4
+ };
5
+ "resource-missing-key": {
6
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
7
+ };
8
+ "resource-missing-error": {
9
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
10
+ };
11
+ "duplicate-key": {
12
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName"]>;
13
+ };
14
+ "duplicate-parent-key": {
15
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName", "keyName"]>;
16
+ };
17
+ }, Record<string, any>>;
18
+ declare const reportDiagnostic: <C extends "not-key-type" | "resource-missing-key" | "resource-missing-error" | "duplicate-key" | "duplicate-parent-key", M extends keyof {
19
+ "not-key-type": {
20
+ readonly default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)";
21
+ };
22
+ "resource-missing-key": {
23
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
24
+ };
25
+ "resource-missing-error": {
26
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
27
+ };
28
+ "duplicate-key": {
29
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName"]>;
30
+ };
31
+ "duplicate-parent-key": {
32
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName", "keyName"]>;
33
+ };
34
+ }[C]>(program: import("@typespec/compiler").Program, diag: import("@typespec/compiler").DiagnosticReport<{
35
+ "not-key-type": {
36
+ readonly default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)";
37
+ };
38
+ "resource-missing-key": {
39
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
40
+ };
41
+ "resource-missing-error": {
42
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
43
+ };
44
+ "duplicate-key": {
45
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName"]>;
46
+ };
47
+ "duplicate-parent-key": {
48
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName", "keyName"]>;
49
+ };
50
+ }, C, M>) => void, createDiagnostic: <C extends "not-key-type" | "resource-missing-key" | "resource-missing-error" | "duplicate-key" | "duplicate-parent-key", M extends keyof {
51
+ "not-key-type": {
52
+ readonly default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)";
53
+ };
54
+ "resource-missing-key": {
55
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
56
+ };
57
+ "resource-missing-error": {
58
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
59
+ };
60
+ "duplicate-key": {
61
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName"]>;
62
+ };
63
+ "duplicate-parent-key": {
64
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName", "keyName"]>;
65
+ };
66
+ }[C]>(diag: import("@typespec/compiler").DiagnosticReport<{
67
+ "not-key-type": {
68
+ readonly default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)";
69
+ };
70
+ "resource-missing-key": {
71
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
72
+ };
73
+ "resource-missing-error": {
74
+ readonly default: import("@typespec/compiler").CallableMessage<["modelName"]>;
75
+ };
76
+ "duplicate-key": {
77
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName"]>;
78
+ };
79
+ "duplicate-parent-key": {
80
+ readonly default: import("@typespec/compiler").CallableMessage<["resourceName", "keyName"]>;
81
+ };
82
+ }, C, M>) => import("@typespec/compiler").Diagnostic, createStateSymbol: (name: string) => symbol;
83
+ export { restLib, reportDiagnostic, createDiagnostic, createStateSymbol };
84
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAsCA,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;uBAAuC,CAAC;AACrD,QAAA,MAAQ,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAAE,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAAE,iBAAiB,0BAAY,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { createTypeSpecLibrary, paramMessage } from "@typespec/compiler";
2
+ const libDefinition = {
3
+ name: "@typespec/rest",
4
+ diagnostics: {
5
+ "not-key-type": {
6
+ severity: "error",
7
+ messages: {
8
+ default: "Cannot copy keys from a non-key type (KeysOf<T> or ParentKeysOf<T>)",
9
+ },
10
+ },
11
+ "resource-missing-key": {
12
+ severity: "error",
13
+ messages: {
14
+ default: paramMessage `Type '${"modelName"}' is used as a resource and therefore must have a key. Use @key to designate a property as the key.`,
15
+ },
16
+ },
17
+ "resource-missing-error": {
18
+ severity: "error",
19
+ messages: {
20
+ default: paramMessage `Type '${"modelName"}' is used as an error and therefore must have the @error decorator applied.`,
21
+ },
22
+ },
23
+ "duplicate-key": {
24
+ severity: "error",
25
+ messages: {
26
+ default: paramMessage `More than one key found on model type ${"resourceName"}`,
27
+ },
28
+ },
29
+ "duplicate-parent-key": {
30
+ severity: "error",
31
+ messages: {
32
+ default: paramMessage `Resource type '${"resourceName"}' has a key property named '${"keyName"}' which conflicts with the key name of a parent or child resource.`,
33
+ },
34
+ },
35
+ },
36
+ };
37
+ const restLib = createTypeSpecLibrary(libDefinition);
38
+ const { reportDiagnostic, createDiagnostic, createStateSymbol } = restLib;
39
+ export { restLib, reportDiagnostic, createDiagnostic, createStateSymbol };
40
+ //# 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,aAAa,GAAG;IACpB,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE;QACX,cAAc,EAAE;YACd,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,qEAAqE;aAC/E;SACF;QACD,sBAAsB,EAAE;YACtB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,YAAY,CAAA,SAAS,WAAW,qGAAqG;aAC/I;SACF;QACD,wBAAwB,EAAE;YACxB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,YAAY,CAAA,SAAS,WAAW,6EAA6E;aACvH;SACF;QACD,eAAe,EAAE;YACf,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,YAAY,CAAA,yCAAyC,cAAc,EAAE;aAC/E;SACF;QACD,sBAAsB,EAAE;YACtB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE;gBACR,OAAO,EAAE,YAAY,CAAA,kBAAkB,cAAc,+BAA+B,SAAS,oEAAoE;aAClK;SACF;KACF;CACO,CAAC;AAEX,MAAM,OAAO,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;AACrD,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { DecoratorContext, Model, ModelProperty, Program, Type } from "@typespec/compiler";
2
+ export interface ResourceKey {
3
+ resourceType: Model;
4
+ keyProperty: ModelProperty;
5
+ }
6
+ export declare function setResourceTypeKey(program: Program, resourceType: Model, keyProperty: ModelProperty): void;
7
+ export declare function getResourceTypeKey(program: Program, resourceType: Model): ResourceKey | undefined;
8
+ export declare function $resourceTypeForKeyParam(context: DecoratorContext, entity: Type, resourceType: Type): void;
9
+ export declare function getResourceTypeForKeyParam(program: Program, param: ModelProperty): Model | undefined;
10
+ export declare function $copyResourceKeyParameters(context: DecoratorContext, entity: Type, filter?: string): void;
11
+ export declare function getParentResource(program: Program, resourceType: Model): Model | undefined;
12
+ /**
13
+ * `@parentResource` marks a model with a reference to its parent resource type
14
+ *
15
+ * The first argument should be a reference to a model type which will be treated as the parent
16
+ * type of the target model type. This will cause the `@key` properties of all parent types of
17
+ * the target type to show up in operations of the `Resource*<T>` interfaces defined in this library.
18
+ *
19
+ * `@parentResource` can only be applied to models.
20
+ */
21
+ export declare function $parentResource(context: DecoratorContext, entity: Type, parentType: Type): void;
22
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAIhB,KAAK,EACL,aAAa,EACb,OAAO,EACP,IAAI,EAEL,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,aAAa,CAAC;CAC5B;AAKD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,KAAK,EACnB,WAAW,EAAE,aAAa,GACzB,IAAI,CAKN;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS,CA+BjG;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,IAAI,EACZ,YAAY,EAAE,IAAI,QAOnB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,aAAa,GACnB,KAAK,GAAG,SAAS,CAEnB;AA6CD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,IAAI,EACZ,MAAM,CAAC,EAAE,MAAM,QAmChB;AAGD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAE1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,QAOxF"}
@@ -0,0 +1,140 @@
1
+ import { $visibility, getKeyName, isErrorType, isKey, validateDecoratorTarget, } from "@typespec/compiler";
2
+ import { $path } from "@typespec/http";
3
+ import { createStateSymbol, reportDiagnostic } from "./lib.js";
4
+ const resourceKeysKey = createStateSymbol("resourceKeys");
5
+ const resourceTypeForKeyParamKey = createStateSymbol("resourceTypeForKeyParam");
6
+ export function setResourceTypeKey(program, resourceType, keyProperty) {
7
+ program.stateMap(resourceKeysKey).set(resourceType, {
8
+ resourceType,
9
+ keyProperty,
10
+ });
11
+ }
12
+ export function getResourceTypeKey(program, resourceType) {
13
+ // Look up the key first
14
+ let resourceKey = program.stateMap(resourceKeysKey).get(resourceType);
15
+ if (resourceKey) {
16
+ return resourceKey;
17
+ }
18
+ // Try to find it in the resource type
19
+ resourceType.properties.forEach((p) => {
20
+ if (isKey(program, p)) {
21
+ if (resourceKey) {
22
+ reportDiagnostic(program, {
23
+ code: "duplicate-key",
24
+ format: {
25
+ resourceName: resourceType.name,
26
+ },
27
+ target: p,
28
+ });
29
+ }
30
+ else {
31
+ resourceKey = {
32
+ resourceType,
33
+ keyProperty: p,
34
+ };
35
+ // Cache the key for future queries
36
+ setResourceTypeKey(program, resourceType, resourceKey.keyProperty);
37
+ }
38
+ }
39
+ });
40
+ return resourceKey;
41
+ }
42
+ export function $resourceTypeForKeyParam(context, entity, resourceType) {
43
+ if (!validateDecoratorTarget(context, entity, "@resourceTypeForKeyParam", "ModelProperty")) {
44
+ return;
45
+ }
46
+ context.program.stateMap(resourceTypeForKeyParamKey).set(entity, resourceType);
47
+ }
48
+ export function getResourceTypeForKeyParam(program, param) {
49
+ return program.stateMap(resourceTypeForKeyParamKey).get(param);
50
+ }
51
+ function cloneKeyProperties(context, target, resourceType) {
52
+ const { program } = context;
53
+ // Add parent keys first
54
+ const parentType = getParentResource(program, resourceType);
55
+ if (parentType) {
56
+ cloneKeyProperties(context, target, parentType);
57
+ }
58
+ const resourceKey = getResourceTypeKey(program, resourceType);
59
+ if (resourceKey) {
60
+ const { keyProperty } = resourceKey;
61
+ const keyName = getKeyName(program, keyProperty);
62
+ const decorators = [
63
+ // Filter out the @visibility decorator because it might affect metadata
64
+ // filtering. NOTE: Check for name equality instead of function equality
65
+ // to deal with multiple copies of core being used.
66
+ ...keyProperty.decorators.filter((d) => d.decorator.name !== $visibility.name),
67
+ {
68
+ decorator: $path,
69
+ args: [],
70
+ },
71
+ {
72
+ decorator: $resourceTypeForKeyParam,
73
+ args: [{ node: target.node, value: resourceType }],
74
+ },
75
+ ];
76
+ // Clone the key property and ensure that an optional key property doesn't
77
+ // become an optional path parameter
78
+ const newProp = program.checker.cloneType(keyProperty, {
79
+ name: keyName,
80
+ decorators,
81
+ optional: false,
82
+ model: target,
83
+ sourceProperty: undefined,
84
+ });
85
+ // Add the key property to the target type
86
+ target.properties.set(keyName, newProp);
87
+ }
88
+ }
89
+ export function $copyResourceKeyParameters(context, entity, filter) {
90
+ if (!validateDecoratorTarget(context, entity, "@copyResourceKeyParameters", "Model")) {
91
+ return;
92
+ }
93
+ const reportNoKeyError = () => reportDiagnostic(context.program, {
94
+ code: "not-key-type",
95
+ target: entity,
96
+ });
97
+ const templateArguments = entity.templateArguments;
98
+ if (!templateArguments || templateArguments.length !== 1) {
99
+ return reportNoKeyError();
100
+ }
101
+ if (templateArguments[0].kind !== "Model") {
102
+ if (isErrorType(templateArguments[0])) {
103
+ return;
104
+ }
105
+ return reportNoKeyError();
106
+ }
107
+ const resourceType = templateArguments[0];
108
+ if (filter === "parent") {
109
+ // Only copy keys of the parent type if there is one
110
+ const parentType = getParentResource(context.program, resourceType);
111
+ if (parentType) {
112
+ cloneKeyProperties(context, entity, parentType);
113
+ }
114
+ }
115
+ else {
116
+ // Copy keys of the resource type and all parents
117
+ cloneKeyProperties(context, entity, resourceType);
118
+ }
119
+ }
120
+ const parentResourceTypesKey = createStateSymbol("parentResourceTypes");
121
+ export function getParentResource(program, resourceType) {
122
+ return program.stateMap(parentResourceTypesKey).get(resourceType);
123
+ }
124
+ /**
125
+ * `@parentResource` marks a model with a reference to its parent resource type
126
+ *
127
+ * The first argument should be a reference to a model type which will be treated as the parent
128
+ * type of the target model type. This will cause the `@key` properties of all parent types of
129
+ * the target type to show up in operations of the `Resource*<T>` interfaces defined in this library.
130
+ *
131
+ * `@parentResource` can only be applied to models.
132
+ */
133
+ export function $parentResource(context, entity, parentType) {
134
+ if (!validateDecoratorTarget(context, parentType, "@parentResource", "Model")) {
135
+ return;
136
+ }
137
+ const { program } = context;
138
+ program.stateMap(parentResourceTypesKey).set(entity, parentType);
139
+ }
140
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/resource.ts"],"names":[],"mappings":"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"}