@azure-tools/typespec-azure-resource-manager 0.27.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 +346 -0
- package/dist/src/common-types.d.ts +8 -0
- package/dist/src/common-types.d.ts.map +1 -0
- package/dist/src/common-types.js +14 -0
- package/dist/src/common-types.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/internal.d.ts +44 -0
- package/dist/src/internal.d.ts.map +1 -0
- package/dist/src/internal.js +142 -0
- package/dist/src/internal.js.map +1 -0
- package/dist/src/lib.d.ts +615 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +250 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/linter.d.ts +3 -0
- package/dist/src/linter.d.ts.map +1 -0
- package/dist/src/linter.js +42 -0
- package/dist/src/linter.js.map +1 -0
- package/dist/src/namespace.d.ts +16 -0
- package/dist/src/namespace.d.ts.map +1 -0
- package/dist/src/namespace.js +106 -0
- package/dist/src/namespace.js.map +1 -0
- package/dist/src/operations.d.ts +36 -0
- package/dist/src/operations.d.ts.map +1 -0
- package/dist/src/operations.js +186 -0
- package/dist/src/operations.js.map +1 -0
- package/dist/src/resource.d.ts +81 -0
- package/dist/src/resource.d.ts.map +1 -0
- package/dist/src/resource.js +358 -0
- package/dist/src/resource.js.map +1 -0
- package/dist/src/rules/arm-resource-action-no-segment.d.ts +2 -0
- package/dist/src/rules/arm-resource-action-no-segment.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-action-no-segment.js +31 -0
- package/dist/src/rules/arm-resource-action-no-segment.js.map +1 -0
- package/dist/src/rules/arm-resource-invalid-chars.d.ts +2 -0
- package/dist/src/rules/arm-resource-invalid-chars.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-invalid-chars.js +61 -0
- package/dist/src/rules/arm-resource-invalid-chars.js.map +1 -0
- package/dist/src/rules/arm-resource-invalid-version-format.d.ts +2 -0
- package/dist/src/rules/arm-resource-invalid-version-format.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-invalid-version-format.js +48 -0
- package/dist/src/rules/arm-resource-invalid-version-format.js.map +1 -0
- package/dist/src/rules/arm-resource-operations.d.ts +2 -0
- package/dist/src/rules/arm-resource-operations.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-operations.js +70 -0
- package/dist/src/rules/arm-resource-operations.js.map +1 -0
- package/dist/src/rules/arm-resource-properties.d.ts +2 -0
- package/dist/src/rules/arm-resource-properties.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-properties.js +55 -0
- package/dist/src/rules/arm-resource-properties.js.map +1 -0
- package/dist/src/rules/arm-resource-provisioning-state-rule.d.ts +2 -0
- package/dist/src/rules/arm-resource-provisioning-state-rule.d.ts.map +1 -0
- package/dist/src/rules/arm-resource-provisioning-state-rule.js +62 -0
- package/dist/src/rules/arm-resource-provisioning-state-rule.js.map +1 -0
- package/dist/src/rules/beyond-nesting-levels.d.ts +5 -0
- package/dist/src/rules/beyond-nesting-levels.d.ts.map +1 -0
- package/dist/src/rules/beyond-nesting-levels.js +37 -0
- package/dist/src/rules/beyond-nesting-levels.js.map +1 -0
- package/dist/src/rules/core-operations.d.ts +2 -0
- package/dist/src/rules/core-operations.d.ts.map +1 -0
- package/dist/src/rules/core-operations.js +181 -0
- package/dist/src/rules/core-operations.js.map +1 -0
- package/dist/src/rules/delete-operation.d.ts +5 -0
- package/dist/src/rules/delete-operation.d.ts.map +1 -0
- package/dist/src/rules/delete-operation.js +28 -0
- package/dist/src/rules/delete-operation.js.map +1 -0
- package/dist/src/rules/envelope-properties.d.ts +5 -0
- package/dist/src/rules/envelope-properties.d.ts.map +1 -0
- package/dist/src/rules/envelope-properties.js +62 -0
- package/dist/src/rules/envelope-properties.js.map +1 -0
- package/dist/src/rules/list-operation.d.ts +5 -0
- package/dist/src/rules/list-operation.d.ts.map +1 -0
- package/dist/src/rules/list-operation.js +35 -0
- package/dist/src/rules/list-operation.js.map +1 -0
- package/dist/src/rules/no-response-body.d.ts +5 -0
- package/dist/src/rules/no-response-body.d.ts.map +1 -0
- package/dist/src/rules/no-response-body.js +27 -0
- package/dist/src/rules/no-response-body.js.map +1 -0
- package/dist/src/rules/operations-interface-missing.d.ts +5 -0
- package/dist/src/rules/operations-interface-missing.d.ts.map +1 -0
- package/dist/src/rules/operations-interface-missing.js +37 -0
- package/dist/src/rules/operations-interface-missing.js.map +1 -0
- package/dist/src/rules/resource-name.d.ts +5 -0
- package/dist/src/rules/resource-name.d.ts.map +1 -0
- package/dist/src/rules/resource-name.js +47 -0
- package/dist/src/rules/resource-name.js.map +1 -0
- package/dist/src/rules/retry-after.d.ts +5 -0
- package/dist/src/rules/retry-after.d.ts.map +1 -0
- package/dist/src/rules/retry-after.js +31 -0
- package/dist/src/rules/retry-after.js.map +1 -0
- package/dist/src/rules/unsupported-types.d.ts +5 -0
- package/dist/src/rules/unsupported-types.d.ts.map +1 -0
- package/dist/src/rules/unsupported-types.js +39 -0
- package/dist/src/rules/unsupported-types.js.map +1 -0
- package/dist/src/rules/utils.d.ts +18 -0
- package/dist/src/rules/utils.d.ts.map +1 -0
- package/dist/src/rules/utils.js +77 -0
- package/dist/src/rules/utils.js.map +1 -0
- package/dist/src/testing/index.d.ts +3 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +24 -0
- package/dist/src/testing/index.js.map +1 -0
- package/lib/arm.foundations.tsp +465 -0
- package/lib/arm.tsp +31 -0
- package/lib/decorators.tsp +87 -0
- package/lib/interfaces.tsp +287 -0
- package/lib/models.tsp +203 -0
- package/lib/operations.tsp +260 -0
- package/lib/parameters.tsp +126 -0
- package/lib/responses.tsp +47 -0
- package/package.json +85 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { getEffectiveModelType, getProperty, isErrorType, SyntaxKind, } from "@typespec/compiler";
|
|
2
|
+
import { getOperationVerb, isBody, isHeader, isPathParam, isQueryParam, } from "@typespec/http";
|
|
3
|
+
import { createRule } from "@typespec/lint";
|
|
4
|
+
import { getAction } from "@typespec/rest";
|
|
5
|
+
import { isArmOperationsListInterface } from "../internal.js";
|
|
6
|
+
import { reportDiagnostic } from "../lib.js";
|
|
7
|
+
import { getArmResource } from "../resource.js";
|
|
8
|
+
import { getNamespaceName, getSourceModel, isInternalTypeSpec, isTemplatedInterfaceOperation, } from "./utils.js";
|
|
9
|
+
export const coreOperationsRule = createRule({
|
|
10
|
+
name: "core-operations",
|
|
11
|
+
create({ program }) {
|
|
12
|
+
return {
|
|
13
|
+
operation: (operation) => {
|
|
14
|
+
if (!isInternalTypeSpec(program, operation)) {
|
|
15
|
+
const actionType = getAction(program, operation);
|
|
16
|
+
const verb = getOperationVerb(program, operation);
|
|
17
|
+
if (actionType !== undefined && verb !== "post") {
|
|
18
|
+
reportDiagnostic(program, {
|
|
19
|
+
code: "arm-resource-invalid-action-verb",
|
|
20
|
+
target: operation,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (!isTemplatedInterfaceOperation(operation) &&
|
|
24
|
+
(!operation.node.parent || operation.node.parent.kind !== SyntaxKind.InterfaceStatement)) {
|
|
25
|
+
reportDiagnostic(program, {
|
|
26
|
+
code: "arm-resource-operation-outside-interface",
|
|
27
|
+
target: operation,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const parameters = operation.parameters;
|
|
31
|
+
if (parameters === undefined ||
|
|
32
|
+
parameters === null ||
|
|
33
|
+
!hasApiParameter(program, parameters)) {
|
|
34
|
+
reportDiagnostic(program, {
|
|
35
|
+
code: "arm-resource-operation-missing-api-version",
|
|
36
|
+
target: operation,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (verb) {
|
|
40
|
+
const requiredDecorators = resourceOperationDecorators[verb];
|
|
41
|
+
if ((requiredDecorators === null || requiredDecorators === void 0 ? void 0 : requiredDecorators.length) > 0) {
|
|
42
|
+
const decorator = operation.decorators.find((d) => requiredDecorators.indexOf(d.decorator.name) >= 0);
|
|
43
|
+
if (!decorator) {
|
|
44
|
+
reportDiagnostic(program, {
|
|
45
|
+
code: "arm-resource-operation-missing-decorator",
|
|
46
|
+
target: operation,
|
|
47
|
+
format: {
|
|
48
|
+
verb: verb.toUpperCase(),
|
|
49
|
+
decorator: requiredDecorators.map((d) => `@${d.substring(1)}`).join(" or "),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (verb === "patch") {
|
|
56
|
+
const resourceType = getResourceModel(program, operation);
|
|
57
|
+
if (resourceType) {
|
|
58
|
+
checkPatchModel(program, operation, resourceType);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
interface: (context) => {
|
|
64
|
+
if (!isInternalTypeSpec(program, context) &&
|
|
65
|
+
!isArmOperationsListInterface(program, context)) {
|
|
66
|
+
if (!context.decorators.some((d) => d.decorator.name === "$armResourceOperations")) {
|
|
67
|
+
reportDiagnostic(program, {
|
|
68
|
+
code: "arm-resource-interface-requires-decorator",
|
|
69
|
+
target: context,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const resourceOperationDecorators = {
|
|
78
|
+
put: ["$armResourceCreateOrUpdate"],
|
|
79
|
+
get: ["$armResourceRead", "$armResourceList"],
|
|
80
|
+
patch: ["$armResourceUpdate"],
|
|
81
|
+
delete: ["$armResourceDelete"],
|
|
82
|
+
post: ["$armResourceAction"],
|
|
83
|
+
head: [],
|
|
84
|
+
};
|
|
85
|
+
function checkPatchModel(program, operation, resourceType) {
|
|
86
|
+
const patchModel = getPatchModel(program, operation);
|
|
87
|
+
if (patchModel === undefined) {
|
|
88
|
+
reportDiagnostic(program, {
|
|
89
|
+
code: "arm-resource-invalid-patch-model",
|
|
90
|
+
target: operation,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else if (resourceType.properties.has("tags") &&
|
|
94
|
+
!patchModel.some((p) => p.name === "tags" && p.type.kind === "Model")) {
|
|
95
|
+
reportDiagnostic(program, {
|
|
96
|
+
code: "arm-resource-patch-missing-tags",
|
|
97
|
+
target: operation,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const resourceProperties = resourceType.properties.get("properties");
|
|
102
|
+
const badProperties = [];
|
|
103
|
+
for (const property of patchModel) {
|
|
104
|
+
const sourceModel = getSourceModel(property);
|
|
105
|
+
if (sourceModel === undefined || !getArmResource(program, sourceModel)) {
|
|
106
|
+
if (!getProperty(resourceType, property.name) &&
|
|
107
|
+
(resourceProperties === undefined ||
|
|
108
|
+
resourceProperties.type.kind !== "Model" ||
|
|
109
|
+
!getProperty(resourceProperties.type, property.name))) {
|
|
110
|
+
badProperties.push(property);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (badProperties.length > 0)
|
|
115
|
+
reportDiagnostic(program, {
|
|
116
|
+
code: "arm-resource-patch-model-superset",
|
|
117
|
+
format: {
|
|
118
|
+
name: badProperties.flatMap((t) => t.name).join(", "),
|
|
119
|
+
resourceModel: resourceType.name,
|
|
120
|
+
},
|
|
121
|
+
target: operation,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function isApiParameter(program, property) {
|
|
126
|
+
if (property.type.kind !== "Scalar")
|
|
127
|
+
return false;
|
|
128
|
+
if (!property.sourceProperty)
|
|
129
|
+
return false;
|
|
130
|
+
const sourceModel = getSourceModel(property.sourceProperty);
|
|
131
|
+
if (sourceModel === undefined)
|
|
132
|
+
return false;
|
|
133
|
+
return (sourceModel.name === "ApiVersionParameter" &&
|
|
134
|
+
getNamespaceName(program, sourceModel) === "Azure.ResourceManager");
|
|
135
|
+
}
|
|
136
|
+
function hasApiParameter(program, model) {
|
|
137
|
+
if (model.properties === undefined || model.properties.size === 0)
|
|
138
|
+
return false;
|
|
139
|
+
const apiVersionParams = [...model.properties.values()].filter((i) => isApiParameter(program, i));
|
|
140
|
+
return apiVersionParams !== null && apiVersionParams.length === 1;
|
|
141
|
+
}
|
|
142
|
+
function getResourceModel(program, operation) {
|
|
143
|
+
const returnType = operation.returnType;
|
|
144
|
+
if (returnType.kind === "Union") {
|
|
145
|
+
for (const variant of returnType.variants.values()) {
|
|
146
|
+
if (!isErrorType(variant.type) && variant.type.kind === "Model") {
|
|
147
|
+
const modelCandidate = getEffectiveModelType(program, variant.type);
|
|
148
|
+
if (getArmResource(program, modelCandidate)) {
|
|
149
|
+
return modelCandidate;
|
|
150
|
+
}
|
|
151
|
+
if (modelCandidate.templateArguments !== undefined) {
|
|
152
|
+
for (const arg of modelCandidate.templateArguments) {
|
|
153
|
+
if (arg.kind === "Model" && getArmResource(program, arg)) {
|
|
154
|
+
return arg;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
function getPatchModel(program, operation) {
|
|
164
|
+
const bodyProperties = [];
|
|
165
|
+
const patchModel = getEffectiveModelType(program, operation.parameters);
|
|
166
|
+
for (const [_, property] of patchModel.properties) {
|
|
167
|
+
if (isHeader(program, property) ||
|
|
168
|
+
isQueryParam(program, property) ||
|
|
169
|
+
isPathParam(program, property))
|
|
170
|
+
continue;
|
|
171
|
+
if (isBody(program, property) && property.type.kind === "Scalar")
|
|
172
|
+
return undefined;
|
|
173
|
+
bodyProperties.push(property);
|
|
174
|
+
}
|
|
175
|
+
if (bodyProperties.length === 0)
|
|
176
|
+
return undefined;
|
|
177
|
+
if (bodyProperties.length === 1 && bodyProperties[0].type.kind === "Model")
|
|
178
|
+
return [...bodyProperties[0].type.properties.values()];
|
|
179
|
+
return bodyProperties;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=core-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-operations.js","sourceRoot":"","sources":["../../../src/rules/core-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-operation.d.ts","sourceRoot":"","sources":["../../../src/rules/delete-operation.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,eAAO,MAAM,0BAA0B,mCAqBrC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createRule } from "@typespec/lint";
|
|
2
|
+
import { reportDiagnostic } from "../lib.js";
|
|
3
|
+
import { getArmResources } from "../resource.js";
|
|
4
|
+
import { getInterface } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* verify an resource should have delete operation
|
|
7
|
+
*/
|
|
8
|
+
export const deleteOperationMissingRule = createRule({
|
|
9
|
+
name: "delete-operation-missing",
|
|
10
|
+
create({ program }) {
|
|
11
|
+
return {
|
|
12
|
+
model: (model) => {
|
|
13
|
+
const resources = getArmResources(program);
|
|
14
|
+
const armResource = resources.find((re) => re.typespecType === model);
|
|
15
|
+
if (armResource &&
|
|
16
|
+
armResource.operations.lifecycle.createOrUpdate &&
|
|
17
|
+
!armResource.operations.lifecycle.delete) {
|
|
18
|
+
const resourceInterface = getInterface(armResource);
|
|
19
|
+
reportDiagnostic(program, {
|
|
20
|
+
code: "no-resource-delete-operation",
|
|
21
|
+
target: resourceInterface || model,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=delete-operation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-operation.js","sourceRoot":"","sources":["../../../src/rules/delete-operation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,UAAU,CAAC;IACnD,IAAI,EAAE,0BAA0B;IAChC,MAAM,CAAC,EAAE,OAAO,EAAE;QAChB,OAAO;YACL,KAAK,EAAE,CAAC,KAAY,EAAE,EAAE;gBACtB,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC;gBACtE,IACE,WAAW;oBACX,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc;oBAC/C,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,EACxC;oBACA,MAAM,iBAAiB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;oBACpD,gBAAgB,CAAC,OAAO,EAAE;wBACxB,IAAI,EAAE,8BAA8B;wBACpC,MAAM,EAAE,iBAAiB,IAAI,KAAK;qBACnC,CAAC,CAAC;iBACJ;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-properties.d.ts","sourceRoot":"","sources":["../../../src/rules/envelope-properties.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,eAAO,MAAM,sBAAsB,mCAsDjC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getProperty } from "@typespec/compiler";
|
|
2
|
+
import { createRule } from "@typespec/lint";
|
|
3
|
+
import { reportDiagnostic } from "../lib.js";
|
|
4
|
+
import { getArmResources } from "../resource.js";
|
|
5
|
+
import { getProperties } from "./utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* verify the 'identity' property should be present in the update resource properties.
|
|
8
|
+
*/
|
|
9
|
+
export const envelopPropertiesRules = createRule({
|
|
10
|
+
name: "envelope-properties",
|
|
11
|
+
create({ program }) {
|
|
12
|
+
const patchEnvelopeProperties = ["identity", "managedBy", "plan", "sku", "tags"];
|
|
13
|
+
return {
|
|
14
|
+
model: (model) => {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const resources = getArmResources(program);
|
|
17
|
+
const armResource = resources.find((re) => re.typespecType === model);
|
|
18
|
+
if (armResource &&
|
|
19
|
+
armResource.operations.lifecycle.update &&
|
|
20
|
+
armResource.operations.lifecycle.createOrUpdate) {
|
|
21
|
+
const updateOperationProperties = armResource.operations.lifecycle.update.httpOperation.parameters.bodyType;
|
|
22
|
+
if ((updateOperationProperties === null || updateOperationProperties === void 0 ? void 0 : updateOperationProperties.kind) === "Model") {
|
|
23
|
+
if (getProperties(updateOperationProperties).length < 1) {
|
|
24
|
+
reportDiagnostic(program, {
|
|
25
|
+
code: "empty-updateable-properties",
|
|
26
|
+
target: model,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const updateablePropertiesBag = getProperty(updateOperationProperties, "properties");
|
|
30
|
+
if ((updateablePropertiesBag === null || updateablePropertiesBag === void 0 ? void 0 : updateablePropertiesBag.type.kind) === "Model" &&
|
|
31
|
+
getProperties(updateablePropertiesBag.type).length === 0) {
|
|
32
|
+
reportDiagnostic(program, {
|
|
33
|
+
code: "empty-updateable-properties",
|
|
34
|
+
target: (_b = (_a = model.properties.get("properties")) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : model,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const missingProperties = [];
|
|
39
|
+
for (const property of patchEnvelopeProperties) {
|
|
40
|
+
if (!checkForPatchProperty(property, model, updateOperationProperties)) {
|
|
41
|
+
missingProperties.push(property);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (missingProperties.length > 0) {
|
|
45
|
+
reportDiagnostic(program, {
|
|
46
|
+
code: "patch-envelope",
|
|
47
|
+
format: { resourceName: model.name, propertyName: missingProperties.join(", ") },
|
|
48
|
+
target: (updateOperationProperties === null || updateOperationProperties === void 0 ? void 0 : updateOperationProperties.kind) === "Model"
|
|
49
|
+
? updateOperationProperties
|
|
50
|
+
: armResource.operations.lifecycle.update.operation,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
function checkForPatchProperty(propertyName, resourceModel, patchModel) {
|
|
59
|
+
return (getProperty(resourceModel, propertyName) === undefined ||
|
|
60
|
+
((patchModel === null || patchModel === void 0 ? void 0 : patchModel.kind) === "Model" && getProperty(patchModel, propertyName) !== undefined));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=envelope-properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-properties.js","sourceRoot":"","sources":["../../../src/rules/envelope-properties.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-operation.d.ts","sourceRoot":"","sources":["../../../src/rules/list-operation.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,eAAO,MAAM,sBAAsB,mCA0BjC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createRule } from "@typespec/lint";
|
|
2
|
+
import { reportDiagnostic } from "../lib.js";
|
|
3
|
+
import { getArmResources, getResourceBaseType, ResourceBaseType } from "../resource.js";
|
|
4
|
+
import { getInterface } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* verify tenant and extension resources do not define list by subscription
|
|
7
|
+
*/
|
|
8
|
+
export const listBySubscriptionRule = createRule({
|
|
9
|
+
name: "improper-subscription-list-operation",
|
|
10
|
+
create() {
|
|
11
|
+
return {
|
|
12
|
+
root: (program) => {
|
|
13
|
+
const resources = getArmResources(program);
|
|
14
|
+
for (const armResource of resources) {
|
|
15
|
+
if (armResource && armResource.operations.lists) {
|
|
16
|
+
const baseType = getResourceBaseType(program, armResource.typespecType);
|
|
17
|
+
if (baseType === ResourceBaseType.Extension || baseType === ResourceBaseType.Tenant) {
|
|
18
|
+
for (const listOperationName of Object.keys(armResource.operations.lists)) {
|
|
19
|
+
const listOperation = armResource.operations.lists[listOperationName];
|
|
20
|
+
if (listOperation.path.includes("{subscriptionId}")) {
|
|
21
|
+
const resourceInterface = getInterface(armResource);
|
|
22
|
+
reportDiagnostic(program, {
|
|
23
|
+
code: "improper-subscription-list-operation",
|
|
24
|
+
target: resourceInterface !== null && resourceInterface !== void 0 ? resourceInterface : armResource.typespecType,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=list-operation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-operation.js","sourceRoot":"","sources":["../../../src/rules/list-operation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAC;IAC/C,IAAI,EAAE,sCAAsC;IAC5C,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,CAAC,OAAgB,EAAE,EAAE;gBACzB,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC3C,KAAK,MAAM,WAAW,IAAI,SAAS,EAAE;oBACnC,IAAI,WAAW,IAAI,WAAW,CAAC,UAAU,CAAC,KAAK,EAAE;wBAC/C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;wBACxE,IAAI,QAAQ,KAAK,gBAAgB,CAAC,SAAS,IAAI,QAAQ,KAAK,gBAAgB,CAAC,MAAM,EAAE;4BACnF,KAAK,MAAM,iBAAiB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;gCACzE,MAAM,aAAa,GAAG,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;gCACtE,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;oCACnD,MAAM,iBAAiB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;oCACpD,gBAAgB,CAAC,OAAO,EAAE;wCACxB,IAAI,EAAE,sCAAsC;wCAC5C,MAAM,EAAE,iBAAiB,aAAjB,iBAAiB,cAAjB,iBAAiB,GAAI,WAAW,CAAC,YAAY;qCACtD,CAAC,CAAC;iCACJ;6BACF;yBACF;qBACF;iBACF;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-response-body.d.ts","sourceRoot":"","sources":["../../../src/rules/no-response-body.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,eAAO,MAAM,cAAc,mCAoBzB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getResponsesForOperation } from "@typespec/http";
|
|
2
|
+
import { createRule } from "@typespec/lint";
|
|
3
|
+
import { reportDiagnostic } from "../lib.js";
|
|
4
|
+
import { isTemplatedInterfaceOperation } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* verify an operation returns 202 should not contains response body.
|
|
7
|
+
*/
|
|
8
|
+
export const noResponseBody = createRule({
|
|
9
|
+
name: "no-response-body",
|
|
10
|
+
create({ program }) {
|
|
11
|
+
return {
|
|
12
|
+
operation: (op) => {
|
|
13
|
+
if (isTemplatedInterfaceOperation(op)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const responses = getResponsesForOperation(program, op)[0].find((v) => v.statusCode === "202");
|
|
17
|
+
if (responses && responses.responses.some((v) => v.body)) {
|
|
18
|
+
reportDiagnostic(program, {
|
|
19
|
+
code: "no-response-body",
|
|
20
|
+
target: op,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=no-response-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-response-body.js","sourceRoot":"","sources":["../../../src/rules/no-response-body.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACvC,IAAI,EAAE,kBAAkB;IACxB,MAAM,CAAC,EAAE,OAAO,EAAE;QAChB,OAAO;YACL,SAAS,EAAE,CAAC,EAAa,EAAE,EAAE;gBAC3B,IAAI,6BAA6B,CAAC,EAAE,CAAC,EAAE;oBACrC,OAAO;iBACR;gBACD,MAAM,SAAS,GAAG,wBAAwB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC7D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,KAAK,CAC9B,CAAC;gBACF,IAAI,SAAS,IAAI,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;oBACxD,gBAAgB,CAAC,OAAO,EAAE;wBACxB,IAAI,EAAE,kBAAkB;wBACxB,MAAM,EAAE,EAAE;qBACX,CAAC,CAAC;iBACJ;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-interface-missing.d.ts","sourceRoot":"","sources":["../../../src/rules/operations-interface-missing.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,eAAO,MAAM,8BAA8B,mCA4BzC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isService } from "@typespec/compiler";
|
|
2
|
+
import { createRule } from "@typespec/lint";
|
|
3
|
+
import { isArmOperationsListInterface } from "../internal.js";
|
|
4
|
+
import { reportDiagnostic } from "../lib.js";
|
|
5
|
+
import { getArmProviderNamespace } from "../namespace.js";
|
|
6
|
+
/**
|
|
7
|
+
* verify that the Arm Operations interface is included.
|
|
8
|
+
*/
|
|
9
|
+
export const operationsInterfaceMissingRule = createRule({
|
|
10
|
+
name: "operations-interface-missing",
|
|
11
|
+
create({ program }) {
|
|
12
|
+
return {
|
|
13
|
+
namespace: (namespace) => {
|
|
14
|
+
if (!isService(program, namespace)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const providerName = getArmProviderNamespace(program, namespace);
|
|
18
|
+
if (!providerName) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const item of namespace.interfaces.values()) {
|
|
22
|
+
if (isArmOperationsListInterface(program, item)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
reportDiagnostic(program, {
|
|
27
|
+
code: "missing-operations-endpoint",
|
|
28
|
+
format: {
|
|
29
|
+
namespace: namespace.name,
|
|
30
|
+
},
|
|
31
|
+
target: namespace,
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=operations-interface-missing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-interface-missing.js","sourceRoot":"","sources":["../../../src/rules/operations-interface-missing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,UAAU,CAAC;IACvD,IAAI,EAAE,8BAA8B;IACpC,MAAM,CAAC,EAAE,OAAO,EAAE;QAChB,OAAO;YACL,SAAS,EAAE,CAAC,SAAS,EAAE,EAAE;gBACvB,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE;oBAClC,OAAO;iBACR;gBAED,MAAM,YAAY,GAAG,uBAAuB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;gBACjE,IAAI,CAAC,YAAY,EAAE;oBACjB,OAAO;iBACR;gBACD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE;oBAChD,IAAI,4BAA4B,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;wBAC/C,OAAO;qBACR;iBACF;gBACD,gBAAgB,CAAC,OAAO,EAAE;oBACxB,IAAI,EAAE,6BAA6B;oBACnC,MAAM,EAAE;wBACN,SAAS,EAAE,SAAS,CAAC,IAAI;qBAC1B;oBACD,MAAM,EAAE,SAAS;iBAClB,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-name.d.ts","sourceRoot":"","sources":["../../../src/rules/resource-name.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,eAAO,MAAM,gBAAgB,mCA0C3B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getProperty, getVisibility, } from "@typespec/compiler";
|
|
2
|
+
import * as http from "@typespec/http";
|
|
3
|
+
import { createRule } from "@typespec/lint";
|
|
4
|
+
import { reportDiagnostic } from "../lib.js";
|
|
5
|
+
import { getArmResources } from "../resource.js";
|
|
6
|
+
/**
|
|
7
|
+
* The resource 'name' field should be marked with 'read' visibility and an @path decorator.
|
|
8
|
+
*/
|
|
9
|
+
export const resourceNameRule = createRule({
|
|
10
|
+
name: "resource-name",
|
|
11
|
+
create({ program }) {
|
|
12
|
+
return {
|
|
13
|
+
model: (model) => {
|
|
14
|
+
const resources = getArmResources(program);
|
|
15
|
+
const armResource = resources.find((re) => re.typespecType === model);
|
|
16
|
+
if (armResource) {
|
|
17
|
+
if (!checkResourceModelName(model.name)) {
|
|
18
|
+
reportDiagnostic(program, {
|
|
19
|
+
code: "arm-resource-name-invalid-chars",
|
|
20
|
+
target: model,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// check that the name property is properly attributed
|
|
24
|
+
const name = getProperty(model, "name");
|
|
25
|
+
if (name && checkResourceName(name)) {
|
|
26
|
+
reportDiagnostic(program, {
|
|
27
|
+
code: "resource-name",
|
|
28
|
+
target: name,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function checkResourceName(nameProp) {
|
|
33
|
+
const visibilities = getVisibility(program, nameProp);
|
|
34
|
+
return (!http.isPathParam(program, nameProp) ||
|
|
35
|
+
!visibilities ||
|
|
36
|
+
visibilities.length !== 1 ||
|
|
37
|
+
visibilities[0] !== "read");
|
|
38
|
+
}
|
|
39
|
+
function checkResourceModelName(name) {
|
|
40
|
+
const matches = name.match(/^[A-Z][0-9A-Za-z]+$/);
|
|
41
|
+
return matches !== null && matches.length === 1;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=resource-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-name.js","sourceRoot":"","sources":["../../../src/rules/resource-name.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,GAId,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;IACzC,IAAI,EAAE,eAAe;IACrB,MAAM,CAAC,EAAE,OAAO,EAAE;QAChB,OAAO;YACL,KAAK,EAAE,CAAC,KAAY,EAAE,EAAE;gBACtB,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;gBAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC;gBAEtE,IAAI,WAAW,EAAE;oBACf,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;wBACvC,gBAAgB,CAAC,OAAO,EAAE;4BACxB,IAAI,EAAE,iCAAiC;4BACvC,MAAM,EAAE,KAAK;yBACd,CAAC,CAAC;qBACJ;oBACD,sDAAsD;oBACtD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;oBACxC,IAAI,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE;wBACnC,gBAAgB,CAAC,OAAO,EAAE;4BACxB,IAAI,EAAE,eAAe;4BACrB,MAAM,EAAE,IAAI;yBACb,CAAC,CAAC;qBACJ;iBACF;gBAED,SAAS,iBAAiB,CAAC,QAAuB;oBAChD,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;oBACtD,OAAO,CACL,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;wBACpC,CAAC,YAAY;wBACb,YAAY,CAAC,MAAM,KAAK,CAAC;wBACzB,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAC3B,CAAC;gBACJ,CAAC;gBAED,SAAS,sBAAsB,CAAC,IAAY;oBAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAClD,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-after.d.ts","sourceRoot":"","sources":["../../../src/rules/retry-after.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,eAAO,MAAM,cAAc,mCAkBzB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getResponsesForOperation } from "@typespec/http";
|
|
2
|
+
import { createRule } from "@typespec/lint";
|
|
3
|
+
import { getExtensions } from "@typespec/openapi";
|
|
4
|
+
import { reportDiagnostic } from "../lib.js";
|
|
5
|
+
import { isTemplatedInterfaceOperation } from "./utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* verify if retry-after header appears in response body .
|
|
8
|
+
*/
|
|
9
|
+
export const retryAfterRule = createRule({
|
|
10
|
+
name: "retry-after",
|
|
11
|
+
create({ program }) {
|
|
12
|
+
return {
|
|
13
|
+
operation: (op) => {
|
|
14
|
+
if (isTemplatedInterfaceOperation(op)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const isLRO = getExtensions(program, op).has("x-ms-long-running-operation");
|
|
18
|
+
if (isLRO && !hasRetryAfterHeader(program, op)) {
|
|
19
|
+
reportDiagnostic(program, {
|
|
20
|
+
code: "retry-after",
|
|
21
|
+
target: op,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
function hasRetryAfterHeader(program, op) {
|
|
29
|
+
return !!getResponsesForOperation(program, op)[0].find((re) => re.responses.find((res) => { var _a; return (_a = res.headers) === null || _a === void 0 ? void 0 : _a["Retry-After"]; }));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=retry-after.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-after.js","sourceRoot":"","sources":["../../../src/rules/retry-after.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACvC,IAAI,EAAE,aAAa;IACnB,MAAM,CAAC,EAAE,OAAO,EAAE;QAChB,OAAO;YACL,SAAS,EAAE,CAAC,EAAa,EAAE,EAAE;gBAC3B,IAAI,6BAA6B,CAAC,EAAE,CAAC,EAAE;oBACrC,OAAO;iBACR;gBACD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;gBAC5E,IAAI,KAAK,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE;oBAC9C,gBAAgB,CAAC,OAAO,EAAE;wBACxB,IAAI,EAAE,aAAa;wBACnB,MAAM,EAAE,EAAE;qBACX,CAAC,CAAC;iBACJ;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,mBAAmB,CAAC,OAAgB,EAAE,EAAa;IAC1D,OAAO,CAAC,CAAC,wBAAwB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAC5D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,WAAC,OAAA,MAAA,GAAG,CAAC,OAAO,0CAAG,aAAa,CAAC,CAAA,EAAA,CAAC,CACzD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unsupported-types.d.ts","sourceRoot":"","sources":["../../../src/rules/unsupported-types.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,mBAAmB,mCAgC9B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createRule } from "@typespec/lint";
|
|
2
|
+
import { reportDiagnostic } from "../lib.js";
|
|
3
|
+
const UnsupportedIntrinsicModel = new Set(["int8", "int16", "uint8", "uint16", "uint32", "uint64"]);
|
|
4
|
+
/**
|
|
5
|
+
* Validation related to versioning.
|
|
6
|
+
*/
|
|
7
|
+
export const unsupportedTypeRule = createRule({
|
|
8
|
+
name: "unsupported-types",
|
|
9
|
+
create({ program }) {
|
|
10
|
+
return {
|
|
11
|
+
modelProperty: (property) => {
|
|
12
|
+
checkUnsupportedType(property.type, property);
|
|
13
|
+
},
|
|
14
|
+
operation: (op) => {
|
|
15
|
+
checkUnsupportedType(op.returnType, op);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
function checkUnsupportedType(type, target) {
|
|
19
|
+
if (type.kind !== "Scalar" && type.kind !== "Model") {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (type.kind === "Scalar") {
|
|
23
|
+
if (UnsupportedIntrinsicModel.has(type.name)) {
|
|
24
|
+
reportDiagnostic(program, {
|
|
25
|
+
code: "unsupported-type",
|
|
26
|
+
format: { typeName: type.name },
|
|
27
|
+
target,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (type.templateArguments) {
|
|
32
|
+
for (const templateArg of type.templateArguments) {
|
|
33
|
+
checkUnsupportedType(templateArg, target);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=unsupported-types.js.map
|