@azure-tools/rlc-common 1.0.0-beta.1
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/.rush/temp/package-deps_build.json +45 -0
- package/.rush/temp/shrinkwrap-deps.json +72 -0
- package/CHANGELOG.md +3 -0
- package/dist/buildClient.js +198 -0
- package/dist/buildClient.js.map +1 -0
- package/dist/buildClientDefinitions.js +160 -0
- package/dist/buildClientDefinitions.js.map +1 -0
- package/dist/buildIndexFile.js +150 -0
- package/dist/buildIndexFile.js.map +1 -0
- package/dist/buildIsUnexpectedHelper.js +219 -0
- package/dist/buildIsUnexpectedHelper.js.map +1 -0
- package/dist/buildMethodShortcuts.js +50 -0
- package/dist/buildMethodShortcuts.js.map +1 -0
- package/dist/buildObjectTypes.js +250 -0
- package/dist/buildObjectTypes.js.map +1 -0
- package/dist/buildPaginateHelper.js +30 -0
- package/dist/buildPaginateHelper.js.map +1 -0
- package/dist/buildParameterTypes.js +287 -0
- package/dist/buildParameterTypes.js.map +1 -0
- package/dist/buildPollingHelper.js +21 -0
- package/dist/buildPollingHelper.js.map +1 -0
- package/dist/buildResponseTypes.js +122 -0
- package/dist/buildResponseTypes.js.map +1 -0
- package/dist/buildSchemaType.js +44 -0
- package/dist/buildSchemaType.js.map +1 -0
- package/dist/buildTopLevelIndexFile.js +45 -0
- package/dist/buildTopLevelIndexFile.js.map +1 -0
- package/dist/helpers/nameConstructors.js +41 -0
- package/dist/helpers/nameConstructors.js.map +1 -0
- package/dist/helpers/nameUtils.js +196 -0
- package/dist/helpers/nameUtils.js.map +1 -0
- package/dist/helpers/operationHelpers.js +83 -0
- package/dist/helpers/operationHelpers.js.map +1 -0
- package/dist/helpers/schemaHelpers.js +27 -0
- package/dist/helpers/schemaHelpers.js.map +1 -0
- package/dist/helpers/shortcutMethods.js +46 -0
- package/dist/helpers/shortcutMethods.js.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.js +18 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/metadata/buildApiExtractorConfig.js +56 -0
- package/dist/metadata/buildApiExtractorConfig.js.map +1 -0
- package/dist/metadata/buildESLintConfig.js +33 -0
- package/dist/metadata/buildESLintConfig.js.map +1 -0
- package/dist/metadata/buildLicenseFile.js +41 -0
- package/dist/metadata/buildLicenseFile.js.map +1 -0
- package/dist/metadata/buildPackageFile.js +232 -0
- package/dist/metadata/buildPackageFile.js.map +1 -0
- package/dist/metadata/buildReadmeFile.js +170 -0
- package/dist/metadata/buildReadmeFile.js.map +1 -0
- package/dist/metadata/buildRollupConfig.js +144 -0
- package/dist/metadata/buildRollupConfig.js.map +1 -0
- package/dist/metadata/buildTsConfig.js +72 -0
- package/dist/metadata/buildTsConfig.js.map +1 -0
- package/dist/package.json +1 -0
- package/dist/static/paginateContent.js +214 -0
- package/dist/static/paginateContent.js.map +1 -0
- package/dist/static/pollingContent.js +78 -0
- package/dist/static/pollingContent.js.map +1 -0
- package/dist/test/buildEnvFile.js +31 -0
- package/dist/test/buildEnvFile.js.map +1 -0
- package/dist/test/buildKarmaConfig.js +19 -0
- package/dist/test/buildKarmaConfig.js.map +1 -0
- package/dist/test/buildRecordedClient.js +22 -0
- package/dist/test/buildRecordedClient.js.map +1 -0
- package/dist/test/buildSampleTest.js +19 -0
- package/dist/test/buildSampleTest.js.map +1 -0
- package/dist/test/template.js +192 -0
- package/dist/test/template.js.map +1 -0
- package/dist-esm/buildClient.js +191 -0
- package/dist-esm/buildClient.js.map +1 -0
- package/dist-esm/buildClientDefinitions.js +155 -0
- package/dist-esm/buildClientDefinitions.js.map +1 -0
- package/dist-esm/buildIndexFile.js +145 -0
- package/dist-esm/buildIndexFile.js.map +1 -0
- package/dist-esm/buildIsUnexpectedHelper.js +215 -0
- package/dist-esm/buildIsUnexpectedHelper.js.map +1 -0
- package/dist-esm/buildMethodShortcuts.js +46 -0
- package/dist-esm/buildMethodShortcuts.js.map +1 -0
- package/dist-esm/buildObjectTypes.js +249 -0
- package/dist-esm/buildObjectTypes.js.map +1 -0
- package/dist-esm/buildPaginateHelper.js +26 -0
- package/dist-esm/buildPaginateHelper.js.map +1 -0
- package/dist-esm/buildParameterTypes.js +288 -0
- package/dist-esm/buildParameterTypes.js.map +1 -0
- package/dist-esm/buildPollingHelper.js +17 -0
- package/dist-esm/buildPollingHelper.js.map +1 -0
- package/dist-esm/buildResponseTypes.js +127 -0
- package/dist-esm/buildResponseTypes.js.map +1 -0
- package/dist-esm/buildSchemaType.js +39 -0
- package/dist-esm/buildSchemaType.js.map +1 -0
- package/dist-esm/buildTopLevelIndexFile.js +41 -0
- package/dist-esm/buildTopLevelIndexFile.js.map +1 -0
- package/dist-esm/helpers/nameConstructors.js +34 -0
- package/dist-esm/helpers/nameConstructors.js.map +1 -0
- package/dist-esm/helpers/nameUtils.js +187 -0
- package/dist-esm/helpers/nameUtils.js.map +1 -0
- package/dist-esm/helpers/operationHelpers.js +72 -0
- package/dist-esm/helpers/operationHelpers.js.map +1 -0
- package/dist-esm/helpers/schemaHelpers.js +21 -0
- package/dist-esm/helpers/schemaHelpers.js.map +1 -0
- package/dist-esm/helpers/shortcutMethods.js +42 -0
- package/dist-esm/helpers/shortcutMethods.js.map +1 -0
- package/dist-esm/index.js +28 -0
- package/dist-esm/index.js.map +1 -0
- package/dist-esm/interfaces.js +15 -0
- package/dist-esm/interfaces.js.map +1 -0
- package/dist-esm/metadata/buildApiExtractorConfig.js +51 -0
- package/dist-esm/metadata/buildApiExtractorConfig.js.map +1 -0
- package/dist-esm/metadata/buildESLintConfig.js +28 -0
- package/dist-esm/metadata/buildESLintConfig.js.map +1 -0
- package/dist-esm/metadata/buildLicenseFile.js +36 -0
- package/dist-esm/metadata/buildLicenseFile.js.map +1 -0
- package/dist-esm/metadata/buildPackageFile.js +234 -0
- package/dist-esm/metadata/buildPackageFile.js.map +1 -0
- package/dist-esm/metadata/buildReadmeFile.js +167 -0
- package/dist-esm/metadata/buildReadmeFile.js.map +1 -0
- package/dist-esm/metadata/buildRollupConfig.js +139 -0
- package/dist-esm/metadata/buildRollupConfig.js.map +1 -0
- package/dist-esm/metadata/buildTsConfig.js +67 -0
- package/dist-esm/metadata/buildTsConfig.js.map +1 -0
- package/dist-esm/package.json +1 -0
- package/dist-esm/static/paginateContent.js +211 -0
- package/dist-esm/static/paginateContent.js.map +1 -0
- package/dist-esm/static/pollingContent.js +75 -0
- package/dist-esm/static/pollingContent.js.map +1 -0
- package/dist-esm/test/buildEnvFile.js +24 -0
- package/dist-esm/test/buildEnvFile.js.map +1 -0
- package/dist-esm/test/buildKarmaConfig.js +14 -0
- package/dist-esm/test/buildKarmaConfig.js.map +1 -0
- package/dist-esm/test/buildRecordedClient.js +17 -0
- package/dist-esm/test/buildRecordedClient.js.map +1 -0
- package/dist-esm/test/buildSampleTest.js +14 -0
- package/dist-esm/test/buildSampleTest.js.map +1 -0
- package/dist-esm/test/template.js +189 -0
- package/dist-esm/test/template.js.map +1 -0
- package/package.json +40 -0
- package/publishPackage.js +11 -0
- package/rlc-common.build.log +2 -0
- package/src/buildClient.ts +251 -0
- package/src/buildClientDefinitions.ts +231 -0
- package/src/buildIndexFile.ts +172 -0
- package/src/buildIsUnexpectedHelper.ts +240 -0
- package/src/buildMethodShortcuts.ts +75 -0
- package/src/buildObjectTypes.ts +393 -0
- package/src/buildPaginateHelper.ts +33 -0
- package/src/buildParameterTypes.ts +435 -0
- package/src/buildPollingHelper.ts +18 -0
- package/src/buildResponseTypes.ts +169 -0
- package/src/buildSchemaType.ts +56 -0
- package/src/buildTopLevelIndexFile.ts +46 -0
- package/src/helpers/nameConstructors.ts +93 -0
- package/src/helpers/nameUtils.ts +227 -0
- package/src/helpers/operationHelpers.ts +103 -0
- package/src/helpers/schemaHelpers.ts +25 -0
- package/src/helpers/shortcutMethods.ts +60 -0
- package/src/index.ts +28 -0
- package/src/interfaces.ts +212 -0
- package/src/metadata/buildApiExtractorConfig.ts +59 -0
- package/src/metadata/buildESLintConfig.ts +34 -0
- package/src/metadata/buildLicenseFile.ts +39 -0
- package/src/metadata/buildPackageFile.ts +271 -0
- package/src/metadata/buildReadmeFile.ts +231 -0
- package/src/metadata/buildRollupConfig.ts +147 -0
- package/src/metadata/buildTsConfig.ts +79 -0
- package/src/static/paginateContent.ts +210 -0
- package/src/static/pollingContent.ts +74 -0
- package/src/test/buildEnvFile.ts +26 -0
- package/src/test/buildKarmaConfig.ts +15 -0
- package/src/test/buildRecordedClient.ts +18 -0
- package/src/test/buildSampleTest.ts +15 -0
- package/src/test/template.ts +192 -0
- package/tsconfig-cjs.json +9 -0
- package/tsconfig-common.json +13 -0
- package/tsconfig.json +13 -0
- package/types/buildClient.d.ts +2 -0
- package/types/buildClientDefinitions.d.ts +5 -0
- package/types/buildIndexFile.d.ts +5 -0
- package/types/buildIsUnexpectedHelper.d.ts +5 -0
- package/types/buildMethodShortcuts.d.ts +4 -0
- package/types/buildObjectTypes.d.ts +14 -0
- package/types/buildPaginateHelper.d.ts +5 -0
- package/types/buildParameterTypes.d.ts +5 -0
- package/types/buildPollingHelper.d.ts +5 -0
- package/types/buildResponseTypes.d.ts +5 -0
- package/types/buildSchemaType.d.ts +19 -0
- package/types/buildTopLevelIndexFile.d.ts +5 -0
- package/types/helpers/nameConstructors.d.ts +28 -0
- package/types/helpers/nameUtils.d.ts +25 -0
- package/types/helpers/operationHelpers.d.ts +9 -0
- package/types/helpers/schemaHelpers.d.ts +4 -0
- package/types/helpers/shortcutMethods.d.ts +3 -0
- package/types/index.d.ts +25 -0
- package/types/interfaces.d.ts +186 -0
- package/types/metadata/buildApiExtractorConfig.d.ts +5 -0
- package/types/metadata/buildESLintConfig.d.ts +5 -0
- package/types/metadata/buildLicenseFile.d.ts +5 -0
- package/types/metadata/buildPackageFile.d.ts +5 -0
- package/types/metadata/buildReadmeFile.d.ts +5 -0
- package/types/metadata/buildRollupConfig.d.ts +5 -0
- package/types/metadata/buildTsConfig.d.ts +5 -0
- package/types/static/paginateContent.d.ts +1 -0
- package/types/static/pollingContent.d.ts +1 -0
- package/types/test/buildEnvFile.d.ts +9 -0
- package/types/test/buildKarmaConfig.d.ts +5 -0
- package/types/test/buildRecordedClient.d.ts +5 -0
- package/types/test/buildSampleTest.d.ts +5 -0
- package/types/test/template.d.ts +5 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
InterfaceDeclarationStructure,
|
|
6
|
+
Project,
|
|
7
|
+
PropertySignatureStructure,
|
|
8
|
+
SourceFile,
|
|
9
|
+
StructureKind
|
|
10
|
+
} from "ts-morph";
|
|
11
|
+
import * as path from "path";
|
|
12
|
+
import {
|
|
13
|
+
ImportKind,
|
|
14
|
+
ParameterMetadata,
|
|
15
|
+
ParameterMetadatas,
|
|
16
|
+
RLCModel,
|
|
17
|
+
Schema
|
|
18
|
+
} from "./interfaces.js";
|
|
19
|
+
import { NameType, normalizeName } from "./helpers/nameUtils.js";
|
|
20
|
+
import {
|
|
21
|
+
getParameterBaseName,
|
|
22
|
+
getParameterTypeName
|
|
23
|
+
} from "./helpers/nameConstructors.js";
|
|
24
|
+
|
|
25
|
+
export function buildParameterTypes(model: RLCModel) {
|
|
26
|
+
const project = new Project();
|
|
27
|
+
const srcPath = model.srcPath;
|
|
28
|
+
const filePath = path.join(srcPath, `parameters.ts`);
|
|
29
|
+
const parametersFile = project.createSourceFile(filePath, undefined, {
|
|
30
|
+
overwrite: true
|
|
31
|
+
});
|
|
32
|
+
let hasHeaders = false;
|
|
33
|
+
|
|
34
|
+
if (!model.parameters) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
for (const requestParameter of model.parameters) {
|
|
38
|
+
const baseParameterName = getParameterBaseName(
|
|
39
|
+
requestParameter.operationGroup,
|
|
40
|
+
requestParameter.operationName
|
|
41
|
+
);
|
|
42
|
+
const requestCount = requestParameter?.parameters?.length ?? 0;
|
|
43
|
+
const topParamName = getParameterTypeName(baseParameterName);
|
|
44
|
+
const subParamNames: string[] = [];
|
|
45
|
+
|
|
46
|
+
// We need to loop the requests. An operation with multiple requests means that
|
|
47
|
+
// the operation can get different values for content-type and each value may
|
|
48
|
+
// have a different type associated to it.
|
|
49
|
+
for (let i = 0; i < requestCount; i++) {
|
|
50
|
+
const parameter = requestParameter.parameters[i];
|
|
51
|
+
const internalReferences = new Set<string>();
|
|
52
|
+
// In case we have more than one request to model we need to add a suffix to differentiate
|
|
53
|
+
const nameSuffix = i > 0 ? `${i}` : "";
|
|
54
|
+
const parameterInterfaceName =
|
|
55
|
+
requestCount > 1
|
|
56
|
+
? `${baseParameterName}RequestParameters${nameSuffix}`
|
|
57
|
+
: topParamName;
|
|
58
|
+
const queryParameterDefinitions = buildQueryParameterDefinition(
|
|
59
|
+
parameter,
|
|
60
|
+
baseParameterName,
|
|
61
|
+
internalReferences,
|
|
62
|
+
i
|
|
63
|
+
);
|
|
64
|
+
const pathParameterDefinitions = buildPathParameterDefinitions(
|
|
65
|
+
parameter,
|
|
66
|
+
baseParameterName,
|
|
67
|
+
parametersFile,
|
|
68
|
+
internalReferences,
|
|
69
|
+
i
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const headerParameterDefinitions = buildHeaderParameterDefinitions(
|
|
73
|
+
parameter,
|
|
74
|
+
baseParameterName,
|
|
75
|
+
parametersFile,
|
|
76
|
+
internalReferences,
|
|
77
|
+
i
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const contentTypeParameterDefinition =
|
|
81
|
+
buildContentTypeParametersDefinition(
|
|
82
|
+
parameter,
|
|
83
|
+
baseParameterName,
|
|
84
|
+
internalReferences,
|
|
85
|
+
i
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const bodyParameterDefinition = buildBodyParametersDefinition(
|
|
89
|
+
parameter,
|
|
90
|
+
baseParameterName,
|
|
91
|
+
internalReferences,
|
|
92
|
+
i
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Add interfaces for body and query parameters
|
|
96
|
+
parametersFile.addInterfaces([
|
|
97
|
+
...(bodyParameterDefinition ?? []),
|
|
98
|
+
...(queryParameterDefinitions ?? []),
|
|
99
|
+
...(pathParameterDefinitions ? [pathParameterDefinitions] : []),
|
|
100
|
+
...(headerParameterDefinitions ? [headerParameterDefinitions] : []),
|
|
101
|
+
...(contentTypeParameterDefinition
|
|
102
|
+
? [contentTypeParameterDefinition]
|
|
103
|
+
: [])
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
// Add Operation parameters type alias which is composed of the types we generated above
|
|
107
|
+
// plus the common type RequestParameters
|
|
108
|
+
parametersFile.addTypeAlias({
|
|
109
|
+
name: parameterInterfaceName,
|
|
110
|
+
isExported: true,
|
|
111
|
+
type: [...internalReferences, "RequestParameters"].join(" & ")
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
subParamNames.push(parameterInterfaceName);
|
|
115
|
+
|
|
116
|
+
if (headerParameterDefinitions !== undefined) {
|
|
117
|
+
hasHeaders = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Add Operation parameters type alias which is composed of the types we generated above
|
|
121
|
+
// plus the common type RequestParameters
|
|
122
|
+
if (requestCount > 1) {
|
|
123
|
+
parametersFile.addTypeAlias({
|
|
124
|
+
name: topParamName,
|
|
125
|
+
isExported: true,
|
|
126
|
+
type: [...subParamNames].join(" | ")
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (hasHeaders) {
|
|
132
|
+
parametersFile.addImportDeclarations([
|
|
133
|
+
{
|
|
134
|
+
namedImports: ["RawHttpHeadersInput"],
|
|
135
|
+
moduleSpecifier: "@azure/core-rest-pipeline"
|
|
136
|
+
}
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
parametersFile.addImportDeclarations([
|
|
140
|
+
{
|
|
141
|
+
namedImports: ["RequestParameters"],
|
|
142
|
+
moduleSpecifier: "@azure-rest/core-client"
|
|
143
|
+
}
|
|
144
|
+
]);
|
|
145
|
+
if (model.importSet?.has(ImportKind.ParameterInput)) {
|
|
146
|
+
parametersFile.addImportDeclarations([
|
|
147
|
+
{
|
|
148
|
+
namedImports: [
|
|
149
|
+
...Array.from(model.importSet?.get(ImportKind.ParameterInput) || [])
|
|
150
|
+
],
|
|
151
|
+
moduleSpecifier: "./models"
|
|
152
|
+
}
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
return { path: filePath, content: parametersFile.getFullText() };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function buildQueryParameterDefinition(
|
|
159
|
+
parameters: ParameterMetadatas,
|
|
160
|
+
baseName: string,
|
|
161
|
+
internalReferences: Set<string>,
|
|
162
|
+
requestIndex: number
|
|
163
|
+
): InterfaceDeclarationStructure[] | undefined {
|
|
164
|
+
const queryParameters = (parameters?.parameters || []).filter(
|
|
165
|
+
(p) => p.type === "query"
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
if (!queryParameters.length) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
173
|
+
const queryParameterInterfaceName = `${baseName}QueryParam${nameSuffix}`;
|
|
174
|
+
const queryParameterPropertiesName = `${baseName}QueryParamProperties`;
|
|
175
|
+
|
|
176
|
+
// Get the property signature for each query parameter
|
|
177
|
+
const propertiesDefinition = queryParameters.map((qp) =>
|
|
178
|
+
getPropertyFromSchema(qp.param)
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const hasRequiredParameters = propertiesDefinition.some(
|
|
182
|
+
(p) => !p.hasQuestionToken
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const propertiesInterface: InterfaceDeclarationStructure = {
|
|
186
|
+
kind: StructureKind.Interface,
|
|
187
|
+
isExported: true,
|
|
188
|
+
name: queryParameterPropertiesName,
|
|
189
|
+
properties: propertiesDefinition
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const parameterInterface: InterfaceDeclarationStructure = {
|
|
193
|
+
kind: StructureKind.Interface,
|
|
194
|
+
isExported: true,
|
|
195
|
+
name: queryParameterInterfaceName,
|
|
196
|
+
properties: [
|
|
197
|
+
{
|
|
198
|
+
name: "queryParameters",
|
|
199
|
+
type: queryParameterPropertiesName,
|
|
200
|
+
// Mark as optional if there are no required parameters
|
|
201
|
+
hasQuestionToken: !hasRequiredParameters
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Mark the queryParameter interface for importing
|
|
207
|
+
internalReferences.add(queryParameterInterfaceName);
|
|
208
|
+
|
|
209
|
+
return [propertiesInterface, parameterInterface];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getPropertyFromSchema(schema: Schema): PropertySignatureStructure {
|
|
213
|
+
const description = schema.description;
|
|
214
|
+
return {
|
|
215
|
+
name: schema.name,
|
|
216
|
+
...(description && { docs: [{ description }] }),
|
|
217
|
+
type: schema.type,
|
|
218
|
+
hasQuestionToken: !Boolean(schema.required),
|
|
219
|
+
kind: StructureKind.PropertySignature
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function buildPathParameterDefinitions(
|
|
224
|
+
parameters: ParameterMetadatas,
|
|
225
|
+
baseName: string,
|
|
226
|
+
parametersFile: SourceFile,
|
|
227
|
+
internalReferences: Set<string>,
|
|
228
|
+
requestIndex: number
|
|
229
|
+
): InterfaceDeclarationStructure | undefined {
|
|
230
|
+
const pathParameters = (parameters.parameters || []).filter(
|
|
231
|
+
(p) => p.type === "path"
|
|
232
|
+
);
|
|
233
|
+
if (!pathParameters.length) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
238
|
+
const pathParameterInterfaceName = `${baseName}PathParam${nameSuffix}`;
|
|
239
|
+
|
|
240
|
+
const pathInterface = getPathInterfaceDefinition(pathParameters, baseName);
|
|
241
|
+
|
|
242
|
+
if (pathInterface) {
|
|
243
|
+
parametersFile.addInterface(pathInterface);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
internalReferences.add(pathParameterInterfaceName);
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
isExported: true,
|
|
250
|
+
kind: StructureKind.Interface,
|
|
251
|
+
name: pathParameterInterfaceName,
|
|
252
|
+
properties: [
|
|
253
|
+
{
|
|
254
|
+
name: "pathParameters",
|
|
255
|
+
type: `${baseName}PathParameters`,
|
|
256
|
+
kind: StructureKind.PropertySignature
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function getPathInterfaceDefinition(
|
|
263
|
+
pathParameters: ParameterMetadata[],
|
|
264
|
+
baseName: string
|
|
265
|
+
): undefined | InterfaceDeclarationStructure {
|
|
266
|
+
const pathInterfaceName = `${baseName}PathParameters`;
|
|
267
|
+
return {
|
|
268
|
+
kind: StructureKind.Interface,
|
|
269
|
+
isExported: true,
|
|
270
|
+
name: pathInterfaceName,
|
|
271
|
+
properties: pathParameters.map((p: ParameterMetadata) =>
|
|
272
|
+
getPropertyFromSchema(p.param)
|
|
273
|
+
)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function buildHeaderParameterDefinitions(
|
|
278
|
+
parameters: ParameterMetadatas,
|
|
279
|
+
baseName: string,
|
|
280
|
+
parametersFile: SourceFile,
|
|
281
|
+
internalReferences: Set<string>,
|
|
282
|
+
requestIndex: number
|
|
283
|
+
): InterfaceDeclarationStructure | undefined {
|
|
284
|
+
const headerParameters = (parameters.parameters || []).filter(
|
|
285
|
+
(p) => p.type === "header" && p.name !== "contentType"
|
|
286
|
+
);
|
|
287
|
+
if (!headerParameters.length) {
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
292
|
+
const headerParameterInterfaceName = `${baseName}HeaderParam${nameSuffix}`;
|
|
293
|
+
|
|
294
|
+
const headersInterface = getRequestHeaderInterfaceDefinition(
|
|
295
|
+
headerParameters,
|
|
296
|
+
baseName
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
if (headersInterface) {
|
|
300
|
+
parametersFile.addInterface(headersInterface);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
internalReferences.add(headerParameterInterfaceName);
|
|
304
|
+
|
|
305
|
+
return {
|
|
306
|
+
isExported: true,
|
|
307
|
+
kind: StructureKind.Interface,
|
|
308
|
+
name: headerParameterInterfaceName,
|
|
309
|
+
properties: [
|
|
310
|
+
{
|
|
311
|
+
name: "headers",
|
|
312
|
+
type: `RawHttpHeadersInput & ${baseName}Headers`,
|
|
313
|
+
kind: StructureKind.PropertySignature
|
|
314
|
+
}
|
|
315
|
+
]
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function getRequestHeaderInterfaceDefinition(
|
|
320
|
+
headerParameters: ParameterMetadata[],
|
|
321
|
+
baseName: string
|
|
322
|
+
): undefined | InterfaceDeclarationStructure {
|
|
323
|
+
const headersInterfaceName = `${baseName}Headers`;
|
|
324
|
+
return {
|
|
325
|
+
kind: StructureKind.Interface,
|
|
326
|
+
isExported: true,
|
|
327
|
+
name: headersInterfaceName,
|
|
328
|
+
properties: headerParameters.map((h: ParameterMetadata) =>
|
|
329
|
+
getPropertyFromSchema(h.param)
|
|
330
|
+
)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function buildContentTypeParametersDefinition(
|
|
335
|
+
parameters: ParameterMetadatas,
|
|
336
|
+
baseName: string,
|
|
337
|
+
internalReferences: Set<string>,
|
|
338
|
+
requestIndex: number
|
|
339
|
+
): InterfaceDeclarationStructure | undefined {
|
|
340
|
+
const mediaTypeParameters = (parameters.parameters || []).filter(
|
|
341
|
+
(p) => p.type === "header" && p.name === "contentType"
|
|
342
|
+
);
|
|
343
|
+
if (!mediaTypeParameters.length) {
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
348
|
+
const mediaTypesParameterInterfaceName = `${baseName}MediaTypesParam${nameSuffix}`;
|
|
349
|
+
|
|
350
|
+
// Mark the queryParameter interface for importing
|
|
351
|
+
internalReferences.add(mediaTypesParameterInterfaceName);
|
|
352
|
+
const mediaParam = mediaTypeParameters[0].param;
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
isExported: true,
|
|
356
|
+
kind: StructureKind.Interface,
|
|
357
|
+
name: mediaTypesParameterInterfaceName,
|
|
358
|
+
properties: [getPropertyFromSchema(mediaParam)]
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function buildBodyParametersDefinition(
|
|
363
|
+
parameters: ParameterMetadatas,
|
|
364
|
+
baseName: string,
|
|
365
|
+
internalReferences: Set<string>,
|
|
366
|
+
requestIndex: number
|
|
367
|
+
): InterfaceDeclarationStructure[] {
|
|
368
|
+
const bodyParameters = parameters.body;
|
|
369
|
+
if (
|
|
370
|
+
!bodyParameters ||
|
|
371
|
+
!bodyParameters?.body ||
|
|
372
|
+
!bodyParameters?.body.length
|
|
373
|
+
) {
|
|
374
|
+
return [];
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
378
|
+
const bodyParameterInterfaceName = `${baseName}BodyParam${nameSuffix}`;
|
|
379
|
+
internalReferences.add(bodyParameterInterfaceName);
|
|
380
|
+
|
|
381
|
+
// In case of formData we'd get multiple properties in body marked as partialBody
|
|
382
|
+
if (bodyParameters.isPartialBody) {
|
|
383
|
+
let allOptionalParts = true;
|
|
384
|
+
const propertiesDefinitions: PropertySignatureStructure[] = [];
|
|
385
|
+
for (const param of bodyParameters.body) {
|
|
386
|
+
if (param.required) {
|
|
387
|
+
allOptionalParts = false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
propertiesDefinitions.push(getPropertyFromSchema(param));
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const formBodyName = `${baseName}FormBody`;
|
|
394
|
+
const formBodyInterface: InterfaceDeclarationStructure = {
|
|
395
|
+
isExported: true,
|
|
396
|
+
kind: StructureKind.Interface,
|
|
397
|
+
name: formBodyName,
|
|
398
|
+
properties: propertiesDefinitions
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
return [
|
|
402
|
+
{
|
|
403
|
+
isExported: true,
|
|
404
|
+
kind: StructureKind.Interface,
|
|
405
|
+
name: bodyParameterInterfaceName,
|
|
406
|
+
properties: [
|
|
407
|
+
{
|
|
408
|
+
name: "body",
|
|
409
|
+
type: formBodyName,
|
|
410
|
+
hasQuestionToken: allOptionalParts
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
formBodyInterface
|
|
415
|
+
];
|
|
416
|
+
} else {
|
|
417
|
+
const bodySignature = getPropertyFromSchema(bodyParameters.body[0]);
|
|
418
|
+
|
|
419
|
+
return [
|
|
420
|
+
{
|
|
421
|
+
isExported: true,
|
|
422
|
+
kind: StructureKind.Interface,
|
|
423
|
+
name: bodyParameterInterfaceName,
|
|
424
|
+
properties: [
|
|
425
|
+
{
|
|
426
|
+
docs: bodySignature.docs,
|
|
427
|
+
name: "body",
|
|
428
|
+
type: bodySignature.type,
|
|
429
|
+
hasQuestionToken: bodySignature.hasQuestionToken
|
|
430
|
+
}
|
|
431
|
+
]
|
|
432
|
+
}
|
|
433
|
+
];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RLCModel } from "./interfaces.js";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
// @ts-ignore: to fix the handlebars issue
|
|
4
|
+
import hbs from "handlebars";
|
|
5
|
+
import { hasPollingOperations } from "./helpers/operationHelpers.js";
|
|
6
|
+
import { pollingContent } from "./static/pollingContent.js";
|
|
7
|
+
|
|
8
|
+
export function buildPollingHelper(model: RLCModel) {
|
|
9
|
+
if (!hasPollingOperations(model)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const readmeFileContents = hbs.compile(pollingContent, { noEscape: true });
|
|
13
|
+
const { srcPath } = model;
|
|
14
|
+
return {
|
|
15
|
+
path: path.join(srcPath, "pollingHelper.ts"),
|
|
16
|
+
content: readmeFileContents({})
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
InterfaceDeclarationStructure,
|
|
6
|
+
OptionalKind,
|
|
7
|
+
Project,
|
|
8
|
+
PropertySignatureStructure,
|
|
9
|
+
StructureKind
|
|
10
|
+
} from "ts-morph";
|
|
11
|
+
import {
|
|
12
|
+
ImportKind,
|
|
13
|
+
ResponseHeaderSchema,
|
|
14
|
+
ResponseMetadata,
|
|
15
|
+
RLCModel
|
|
16
|
+
} from "./interfaces.js";
|
|
17
|
+
import * as path from "path";
|
|
18
|
+
import {
|
|
19
|
+
getResponseBaseName,
|
|
20
|
+
getResponseTypeName
|
|
21
|
+
} from "./helpers/nameConstructors.js";
|
|
22
|
+
|
|
23
|
+
export function buildResponseTypes(model: RLCModel) {
|
|
24
|
+
const project = new Project();
|
|
25
|
+
const srcPath = model.srcPath;
|
|
26
|
+
const filePath = path.join(srcPath, `responses.ts`);
|
|
27
|
+
const responsesFile = project.createSourceFile(filePath, undefined, {
|
|
28
|
+
overwrite: true
|
|
29
|
+
});
|
|
30
|
+
// Set used to track down which models need to be imported
|
|
31
|
+
// Track if we need to import RawHttpHeaders
|
|
32
|
+
let hasHeaders = false;
|
|
33
|
+
if (!model.responses) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
for (const operationResponse of model.responses) {
|
|
37
|
+
for (const response of operationResponse.responses) {
|
|
38
|
+
// Building the response type base name
|
|
39
|
+
const baseResponseName = getResponseBaseName(
|
|
40
|
+
operationResponse.operationGroup,
|
|
41
|
+
operationResponse.operationName,
|
|
42
|
+
response.statusCode
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// Build the response header
|
|
46
|
+
const headersInterface: InterfaceDeclarationStructure | undefined =
|
|
47
|
+
getResponseHeaderInterfaceDefinition(response, baseResponseName);
|
|
48
|
+
if (headersInterface) {
|
|
49
|
+
hasHeaders = true;
|
|
50
|
+
responsesFile.addInterface(headersInterface);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Get the information to build the Response Interface
|
|
54
|
+
const responseTypeName = getResponseTypeName(baseResponseName);
|
|
55
|
+
const responseProperties = getResponseInterfaceProperties(
|
|
56
|
+
response,
|
|
57
|
+
headersInterface?.name
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const responseInterfaceDefinition: OptionalKind<InterfaceDeclarationStructure> =
|
|
61
|
+
{
|
|
62
|
+
name: responseTypeName,
|
|
63
|
+
properties: responseProperties,
|
|
64
|
+
isExported: true,
|
|
65
|
+
extends: ["HttpResponse"]
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Only add a description if one was provided in the Swagger
|
|
69
|
+
// otherwise skip to avoid having empty TSDoc lines
|
|
70
|
+
if (response.description) {
|
|
71
|
+
responseInterfaceDefinition.docs = [
|
|
72
|
+
{ description: response.description }
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Add the response interface to the responses file
|
|
77
|
+
responsesFile.addInterface(responseInterfaceDefinition);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (hasHeaders) {
|
|
82
|
+
responsesFile.addImportDeclarations([
|
|
83
|
+
{
|
|
84
|
+
namedImports: ["RawHttpHeaders"],
|
|
85
|
+
moduleSpecifier: "@azure/core-rest-pipeline"
|
|
86
|
+
}
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
responsesFile.addImportDeclarations([
|
|
90
|
+
{
|
|
91
|
+
namedImports: ["HttpResponse"],
|
|
92
|
+
moduleSpecifier: "@azure-rest/core-client"
|
|
93
|
+
}
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
if (model.importSet?.has(ImportKind.ResponseOutput)) {
|
|
97
|
+
responsesFile.addImportDeclarations([
|
|
98
|
+
{
|
|
99
|
+
namedImports: [
|
|
100
|
+
...Array.from(model.importSet.get(ImportKind.ResponseOutput) || [])
|
|
101
|
+
],
|
|
102
|
+
moduleSpecifier: "./outputModels"
|
|
103
|
+
}
|
|
104
|
+
]);
|
|
105
|
+
}
|
|
106
|
+
return { path: filePath, content: responsesFile.getFullText() };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getResponseHeaderInterfaceDefinition(
|
|
110
|
+
response: ResponseMetadata,
|
|
111
|
+
baseName: string
|
|
112
|
+
): undefined | InterfaceDeclarationStructure {
|
|
113
|
+
// Check if there are any required headers
|
|
114
|
+
if (!response.headers) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const headersInterfaceName = `${baseName}Headers`;
|
|
118
|
+
return {
|
|
119
|
+
kind: StructureKind.Interface,
|
|
120
|
+
isExported: true,
|
|
121
|
+
name: headersInterfaceName,
|
|
122
|
+
properties: response?.headers.map((h: ResponseHeaderSchema) => {
|
|
123
|
+
const description = h.description;
|
|
124
|
+
return {
|
|
125
|
+
name: h.name,
|
|
126
|
+
...(description && { docs: [{ description }] }),
|
|
127
|
+
type: h.type,
|
|
128
|
+
hasQuestionToken: !Boolean(h.required)
|
|
129
|
+
};
|
|
130
|
+
})
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Gets the properties that need to be part of the response interface
|
|
136
|
+
*/
|
|
137
|
+
function getResponseInterfaceProperties(
|
|
138
|
+
response: ResponseMetadata,
|
|
139
|
+
headersInterfaceName?: string
|
|
140
|
+
) {
|
|
141
|
+
const statusCode = response.statusCode;
|
|
142
|
+
const responseProperties: PropertySignatureStructure[] = [
|
|
143
|
+
{
|
|
144
|
+
name: "status",
|
|
145
|
+
type: statusCode === "default" ? `string` : `"${statusCode}"`,
|
|
146
|
+
kind: StructureKind.PropertySignature
|
|
147
|
+
}
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
if (response.body) {
|
|
151
|
+
const description = response.body.description;
|
|
152
|
+
responseProperties.push({
|
|
153
|
+
name: "body",
|
|
154
|
+
type: response.body.type,
|
|
155
|
+
kind: StructureKind.PropertySignature,
|
|
156
|
+
...(description && { docs: [{ description }] })
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (headersInterfaceName) {
|
|
161
|
+
responseProperties.push({
|
|
162
|
+
name: "headers",
|
|
163
|
+
type: `RawHttpHeaders & ${headersInterfaceName}`,
|
|
164
|
+
kind: StructureKind.PropertySignature
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return responseProperties;
|
|
169
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { Project } from "ts-morph";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import {
|
|
7
|
+
buildObjectInterfaces,
|
|
8
|
+
buildPolymorphicAliases
|
|
9
|
+
} from "./buildObjectTypes.js";
|
|
10
|
+
import { RLCModel, SchemaContext } from "./interfaces.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generates types to represent schema definitions in the swagger
|
|
14
|
+
*/
|
|
15
|
+
export function buildSchemaTypes(model: RLCModel) {
|
|
16
|
+
const { srcPath } = model;
|
|
17
|
+
const project = new Project();
|
|
18
|
+
let filePath = path.join(srcPath, `models.ts`);
|
|
19
|
+
const inputModelFile = generateModelFiles(model, project, filePath, [
|
|
20
|
+
SchemaContext.Input
|
|
21
|
+
]);
|
|
22
|
+
filePath = path.join(srcPath, `outputModels.ts`);
|
|
23
|
+
const outputModelFile = generateModelFiles(model, project, filePath, [
|
|
24
|
+
SchemaContext.Output,
|
|
25
|
+
SchemaContext.Exception
|
|
26
|
+
]);
|
|
27
|
+
return { inputModelFile, outputModelFile };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function generateModelFiles(
|
|
31
|
+
model: RLCModel,
|
|
32
|
+
project: Project,
|
|
33
|
+
filePath: string,
|
|
34
|
+
schemaContext: SchemaContext[]
|
|
35
|
+
) {
|
|
36
|
+
// Track models that need to be imported
|
|
37
|
+
const importedModels = new Set<string>();
|
|
38
|
+
|
|
39
|
+
const objectsDefinitions = buildObjectInterfaces(
|
|
40
|
+
model,
|
|
41
|
+
importedModels,
|
|
42
|
+
schemaContext
|
|
43
|
+
);
|
|
44
|
+
const objectTypeAliases = buildPolymorphicAliases(model, schemaContext);
|
|
45
|
+
|
|
46
|
+
if (objectTypeAliases.length || objectsDefinitions.length) {
|
|
47
|
+
const modelsFile = project.createSourceFile(filePath, undefined, {
|
|
48
|
+
overwrite: true
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
modelsFile.addInterfaces(objectsDefinitions);
|
|
52
|
+
modelsFile.addTypeAliases(objectTypeAliases);
|
|
53
|
+
return { path: filePath, content: modelsFile.getFullText() };
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|