@autorest/typescript 6.0.0-alpha.16.20220105.1 → 6.0.0-alpha.16.20220119.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/dist/src/autorestSession.d.ts +1 -0
- package/dist/src/autorestSession.d.ts.map +1 -1
- package/dist/src/autorestSession.js.map +1 -1
- package/dist/src/generators/indexGenerator.d.ts.map +1 -1
- package/dist/src/generators/indexGenerator.js +66 -3
- package/dist/src/generators/indexGenerator.js.map +1 -1
- package/dist/src/generators/static/packageFileGenerator.js +6 -0
- package/dist/src/generators/static/packageFileGenerator.js.map +1 -1
- package/dist/src/restLevelClient/generateClient.d.ts +1 -1
- package/dist/src/restLevelClient/generateClient.d.ts.map +1 -1
- package/dist/src/restLevelClient/generateClient.js +23 -193
- package/dist/src/restLevelClient/generateClient.js.map +1 -1
- package/dist/src/restLevelClient/generateClientDefinition.d.ts +6 -0
- package/dist/src/restLevelClient/generateClientDefinition.d.ts.map +1 -0
- package/dist/src/restLevelClient/generateClientDefinition.js +228 -0
- package/dist/src/restLevelClient/generateClientDefinition.js.map +1 -0
- package/dist/src/restLevelClient/generatePagingHelper.d.ts.map +1 -1
- package/dist/src/restLevelClient/generatePagingHelper.js +2 -1
- package/dist/src/restLevelClient/generatePagingHelper.js.map +1 -1
- package/dist/src/restLevelClient/generateParameterTypes.d.ts.map +1 -1
- package/dist/src/restLevelClient/generateParameterTypes.js +51 -1
- package/dist/src/restLevelClient/generateParameterTypes.js.map +1 -1
- package/dist/src/restLevelClient/generatePollingHelper.d.ts.map +1 -1
- package/dist/src/restLevelClient/generatePollingHelper.js +3 -1
- package/dist/src/restLevelClient/generatePollingHelper.js.map +1 -1
- package/dist/src/restLevelClient/generateResponseTypes.d.ts.map +1 -1
- package/dist/src/restLevelClient/generateResponseTypes.js +4 -1
- package/dist/src/restLevelClient/generateResponseTypes.js.map +1 -1
- package/dist/src/restLevelClient/generateRestLevel.d.ts.map +1 -1
- package/dist/src/restLevelClient/generateRestLevel.js +5 -1
- package/dist/src/restLevelClient/generateRestLevel.js.map +1 -1
- package/dist/src/restLevelClient/generateSchemaTypes.d.ts.map +1 -1
- package/dist/src/restLevelClient/generateSchemaTypes.js +5 -2
- package/dist/src/restLevelClient/generateSchemaTypes.js.map +1 -1
- package/dist/src/restLevelClient/generateTopLevelIndexFile.d.ts +4 -0
- package/dist/src/restLevelClient/generateTopLevelIndexFile.d.ts.map +1 -0
- package/dist/src/restLevelClient/generateTopLevelIndexFile.js +41 -0
- package/dist/src/restLevelClient/generateTopLevelIndexFile.js.map +1 -0
- package/dist/src/utils/autorestOptions.d.ts.map +1 -1
- package/dist/src/utils/autorestOptions.js +8 -0
- package/dist/src/utils/autorestOptions.js.map +1 -1
- package/package.json +2 -2
- package/src/autorestSession.ts +1 -0
- package/src/generators/indexGenerator.ts +75 -4
- package/src/generators/static/packageFileGenerator.ts +6 -0
- package/src/restLevelClient/generateClient.ts +25 -276
- package/src/restLevelClient/generateClientDefinition.ts +325 -0
- package/src/restLevelClient/generatePagingHelper.ts +3 -2
- package/src/restLevelClient/generateParameterTypes.ts +91 -2
- package/src/restLevelClient/generatePollingHelper.ts +3 -1
- package/src/restLevelClient/generateResponseTypes.ts +4 -1
- package/src/restLevelClient/generateRestLevel.ts +8 -2
- package/src/restLevelClient/generateSchemaTypes.ts +5 -3
- package/src/restLevelClient/generateTopLevelIndexFile.ts +41 -0
- package/src/utils/autorestOptions.ts +9 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CodeModel,
|
|
3
|
+
Operation,
|
|
4
|
+
ParameterLocation,
|
|
5
|
+
ImplementationLocation
|
|
6
|
+
} from "@autorest/codemodel";
|
|
7
|
+
|
|
8
|
+
import { getResponseTypeName } from "./operationHelpers";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
CallSignatureDeclarationStructure,
|
|
12
|
+
Project,
|
|
13
|
+
SourceFile,
|
|
14
|
+
StructureKind,
|
|
15
|
+
Writers
|
|
16
|
+
} from "ts-morph";
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
|
|
19
|
+
import { getAutorestOptions, getSession } from "../autorestSession";
|
|
20
|
+
import { transformBaseUrl } from "../transforms/urlTransforms";
|
|
21
|
+
import { NameType, normalizeName } from "../utils/nameUtils";
|
|
22
|
+
import { getLanguageMetadata } from "../utils/languageHelpers";
|
|
23
|
+
import {
|
|
24
|
+
buildMethodDefinitions,
|
|
25
|
+
getOperationParameters,
|
|
26
|
+
getPathParamDefinitions
|
|
27
|
+
} from "./helpers/operationHelpers";
|
|
28
|
+
import { generateMethodShortcuts } from "./generateMethodShortcuts";
|
|
29
|
+
import { Methods, PathParameter, Paths } from "./interfaces";
|
|
30
|
+
export let pathDictionary: Paths = {};
|
|
31
|
+
|
|
32
|
+
export function generatePathFirstClient(model: CodeModel, project: Project) {
|
|
33
|
+
const name = normalizeName(
|
|
34
|
+
getLanguageMetadata(model.language).name,
|
|
35
|
+
NameType.File
|
|
36
|
+
);
|
|
37
|
+
const { srcPath } = getAutorestOptions();
|
|
38
|
+
const clientFile = project.createSourceFile(path.join(srcPath, `clientDefinitions.ts`), undefined, {
|
|
39
|
+
overwrite: true
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Get all paths
|
|
43
|
+
const importedParameters = new Set<string>();
|
|
44
|
+
const importedResponses = new Set<string>();
|
|
45
|
+
pathDictionary = {};
|
|
46
|
+
for (const operationGroup of model.operationGroups) {
|
|
47
|
+
for (const operation of operationGroup.operations) {
|
|
48
|
+
const operationName = getLanguageMetadata(operation.language).name;
|
|
49
|
+
const operationDescription = getLanguageMetadata(operation.language)
|
|
50
|
+
.description;
|
|
51
|
+
const pathParameters: PathParameter[] =
|
|
52
|
+
operation.parameters
|
|
53
|
+
?.filter(p => p.protocol.http?.in === ParameterLocation.Path)
|
|
54
|
+
.map(p => {
|
|
55
|
+
const languageMetadata = getLanguageMetadata(p.language);
|
|
56
|
+
return {
|
|
57
|
+
name: languageMetadata.serializedName || languageMetadata.name,
|
|
58
|
+
schema: p.schema,
|
|
59
|
+
description: languageMetadata.description
|
|
60
|
+
};
|
|
61
|
+
}) || [];
|
|
62
|
+
const path: string = operation.requests?.[0].protocol.http?.path;
|
|
63
|
+
pathParameters.sort(function compare(a: PathParameter, b: PathParameter) {
|
|
64
|
+
return path.indexOf(a.name) - path.indexOf(b.name);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
for (const request of operation.requests || []) {
|
|
68
|
+
const path: string = (request.protocol.http?.path as string) || "";
|
|
69
|
+
const method = request.protocol.http?.method;
|
|
70
|
+
|
|
71
|
+
if (path && method) {
|
|
72
|
+
if (!pathDictionary[path]) {
|
|
73
|
+
pathDictionary[path] = {
|
|
74
|
+
pathParameters,
|
|
75
|
+
methods: {},
|
|
76
|
+
name: operationName
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const hasOptionalOptions = !hasRequiredOptions(operation);
|
|
80
|
+
|
|
81
|
+
const newMethod = {
|
|
82
|
+
description: operationDescription,
|
|
83
|
+
optionsName: getOperationOptionsType(operation, importedParameters),
|
|
84
|
+
hasOptionalOptions,
|
|
85
|
+
returnType: `Promise<${getOperationReturnType(
|
|
86
|
+
operation,
|
|
87
|
+
importedResponses
|
|
88
|
+
)}>`
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (pathDictionary[path].methods[`${method}`]) {
|
|
92
|
+
pathDictionary[path].methods[`${method}`].push(newMethod);
|
|
93
|
+
} else {
|
|
94
|
+
pathDictionary[path].methods[`${method}`] = [newMethod];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
writeShortcutInterface(model, pathDictionary, clientFile);
|
|
102
|
+
clientFile.addInterface({
|
|
103
|
+
name: "Routes",
|
|
104
|
+
isExported: true,
|
|
105
|
+
callSignatures: getPathFirstRoutesInterfaceDefinition(
|
|
106
|
+
pathDictionary,
|
|
107
|
+
clientFile
|
|
108
|
+
)
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const clientName = getLanguageMetadata(model.language).name;
|
|
112
|
+
const uriParameter = getClientUriParameter();
|
|
113
|
+
|
|
114
|
+
const { addCredentials, credentialKeyHeaderName } = getAutorestOptions();
|
|
115
|
+
const credentialTypes = addCredentials ? ["TokenCredential"] : [];
|
|
116
|
+
|
|
117
|
+
if (credentialKeyHeaderName) {
|
|
118
|
+
credentialTypes.push("KeyCredential");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const clientIterfaceName = `${clientName}RestClient`;
|
|
122
|
+
|
|
123
|
+
const { rlcShortcut } = getAutorestOptions();
|
|
124
|
+
|
|
125
|
+
let shortcutElements = !rlcShortcut
|
|
126
|
+
? []
|
|
127
|
+
: model.operationGroups.map(og => {
|
|
128
|
+
const groupName = og.language.default.name;
|
|
129
|
+
const name = normalizeName(groupName, NameType.Property);
|
|
130
|
+
const interfaceName = normalizeName(
|
|
131
|
+
`${name}Operations`,
|
|
132
|
+
NameType.Interface
|
|
133
|
+
);
|
|
134
|
+
return { name, type: interfaceName };
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// There may be operations without an operation group, those shortcut
|
|
138
|
+
// methods need to be handled differently.
|
|
139
|
+
const shortcutsInOperationGroup = shortcutElements.filter(s => s.name);
|
|
140
|
+
|
|
141
|
+
clientFile.addTypeAlias({
|
|
142
|
+
isExported: true,
|
|
143
|
+
name: clientIterfaceName,
|
|
144
|
+
type: Writers.intersectionType(
|
|
145
|
+
"Client",
|
|
146
|
+
Writers.objectType({
|
|
147
|
+
properties: [
|
|
148
|
+
{ name: "path", type: "Routes" },
|
|
149
|
+
...shortcutsInOperationGroup
|
|
150
|
+
]
|
|
151
|
+
}),
|
|
152
|
+
// If the length of shortcutMethods in operation group and all shortcutMethods
|
|
153
|
+
// is the same, then we don't have any operations at the client level
|
|
154
|
+
// Otherwise we need to make the client interface name an union with the
|
|
155
|
+
// definition of all client level shortcut methods
|
|
156
|
+
...(shortcutsInOperationGroup.length !== shortcutElements.length
|
|
157
|
+
? [`ClientOperations`]
|
|
158
|
+
: [])
|
|
159
|
+
)
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (importedParameters.size) {
|
|
163
|
+
clientFile.addImportDeclaration({
|
|
164
|
+
namedImports: [...importedParameters],
|
|
165
|
+
moduleSpecifier: "./parameters"
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (importedResponses.size) {
|
|
170
|
+
clientFile.addImportDeclaration({
|
|
171
|
+
namedImports: [...importedResponses],
|
|
172
|
+
moduleSpecifier: "./responses"
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
clientFile.addImportDeclarations([
|
|
177
|
+
{
|
|
178
|
+
namedImports: ["Client"],
|
|
179
|
+
moduleSpecifier: "@azure-rest/core-client"
|
|
180
|
+
}
|
|
181
|
+
]);
|
|
182
|
+
|
|
183
|
+
clientFile.addImportDeclarations([
|
|
184
|
+
{
|
|
185
|
+
namedImports: credentialTypes,
|
|
186
|
+
moduleSpecifier: "@azure/core-auth"
|
|
187
|
+
}
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function writeShortcutInterface(
|
|
192
|
+
model: CodeModel,
|
|
193
|
+
pathDictionary: Paths,
|
|
194
|
+
clientFile: SourceFile
|
|
195
|
+
) {
|
|
196
|
+
const { rlcShortcut } = getAutorestOptions();
|
|
197
|
+
if (!rlcShortcut) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Create a map of Operation group descriptions
|
|
202
|
+
const descriptions = model.operationGroups.reduce((map, current) => {
|
|
203
|
+
const { name, description } = current.language.default;
|
|
204
|
+
map.set(name, description);
|
|
205
|
+
|
|
206
|
+
return map;
|
|
207
|
+
}, new Map<string, string>());
|
|
208
|
+
|
|
209
|
+
const shortcuts = generateMethodShortcuts(model, pathDictionary);
|
|
210
|
+
|
|
211
|
+
for (const group of Object.keys(shortcuts)) {
|
|
212
|
+
const groupName = normalizeName(group, NameType.Interface) || "Client";
|
|
213
|
+
const groupOperations = shortcuts[group];
|
|
214
|
+
|
|
215
|
+
clientFile.addInterface({
|
|
216
|
+
docs: [
|
|
217
|
+
descriptions.get(group) ||
|
|
218
|
+
`Contains operations for ${groupName} operations`
|
|
219
|
+
],
|
|
220
|
+
name: `${groupName}Operations`,
|
|
221
|
+
isExported: true,
|
|
222
|
+
methods: groupOperations
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function hasRequiredOptions(operation: Operation) {
|
|
228
|
+
return getOperationParameters(operation)
|
|
229
|
+
.filter(p => p.implementation === ImplementationLocation.Method)
|
|
230
|
+
.filter(p => ["query", "body", "headers"].includes(p.protocol.http?.in))
|
|
231
|
+
.some(p => p.required);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function getOperationOptionsType(
|
|
235
|
+
operation: Operation,
|
|
236
|
+
importedParameters = new Set<string>()
|
|
237
|
+
) {
|
|
238
|
+
const paramsName = `${
|
|
239
|
+
getLanguageMetadata(operation.language).name
|
|
240
|
+
}Parameters`;
|
|
241
|
+
importedParameters.add(paramsName);
|
|
242
|
+
|
|
243
|
+
return paramsName;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getOperationReturnType(
|
|
247
|
+
operation: Operation,
|
|
248
|
+
importedResponses = new Set<string>()
|
|
249
|
+
) {
|
|
250
|
+
let returnType: string = "HttpResponse";
|
|
251
|
+
if (operation.responses && operation.responses.length) {
|
|
252
|
+
const responses = [...operation.responses, ...(operation.exceptions || [])];
|
|
253
|
+
|
|
254
|
+
const responseTypes = responses
|
|
255
|
+
.filter(
|
|
256
|
+
r => r.protocol.http?.statusCodes && r.protocol.http?.statusCodes.length
|
|
257
|
+
)
|
|
258
|
+
.map(r => {
|
|
259
|
+
const responseName = getResponseTypeName(operation, r);
|
|
260
|
+
importedResponses.add(responseName);
|
|
261
|
+
return responseName;
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
if (responseTypes.length) {
|
|
265
|
+
returnType = responseTypes.join(" | ");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return returnType;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function getPathFirstRoutesInterfaceDefinition(
|
|
273
|
+
paths: Paths,
|
|
274
|
+
sourcefile: SourceFile
|
|
275
|
+
): CallSignatureDeclarationStructure[] {
|
|
276
|
+
const signatures: CallSignatureDeclarationStructure[] = [];
|
|
277
|
+
for (const key of Object.keys(paths)) {
|
|
278
|
+
generatePathFirstRouteMethodsDefinition(
|
|
279
|
+
paths[key].name,
|
|
280
|
+
paths[key].methods,
|
|
281
|
+
sourcefile
|
|
282
|
+
);
|
|
283
|
+
const pathParams = paths[key].pathParameters;
|
|
284
|
+
signatures.push({
|
|
285
|
+
docs: [
|
|
286
|
+
`Resource for '${key
|
|
287
|
+
.replace(/}/g, "\\}")
|
|
288
|
+
.replace(
|
|
289
|
+
/{/g,
|
|
290
|
+
"\\{"
|
|
291
|
+
)}' has methods for the following verbs: ${Object.keys(
|
|
292
|
+
paths[key].methods
|
|
293
|
+
).join(", ")}`
|
|
294
|
+
],
|
|
295
|
+
parameters: [
|
|
296
|
+
{ name: "path", type: `"${key}"` },
|
|
297
|
+
...getPathParamDefinitions(pathParams)
|
|
298
|
+
],
|
|
299
|
+
returnType: paths[key].name,
|
|
300
|
+
kind: StructureKind.CallSignature
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return signatures;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function getClientUriParameter() {
|
|
307
|
+
const { model } = getSession();
|
|
308
|
+
const { parameterName } = transformBaseUrl(model);
|
|
309
|
+
return parameterName;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function generatePathFirstRouteMethodsDefinition(
|
|
313
|
+
operationName: string,
|
|
314
|
+
methods: Methods,
|
|
315
|
+
file: SourceFile
|
|
316
|
+
): void {
|
|
317
|
+
const methodDefinitions = buildMethodDefinitions(methods);
|
|
318
|
+
|
|
319
|
+
file.addInterface({
|
|
320
|
+
methods: methodDefinitions,
|
|
321
|
+
name: operationName,
|
|
322
|
+
isExported: true
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
|
-
import { getSession } from "../autorestSession";
|
|
2
|
+
import { getAutorestOptions, getSession } from "../autorestSession";
|
|
3
3
|
import { extractPaginationDetails } from "../utils/extractPaginationDetails";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import * as hbs from "handlebars";
|
|
@@ -29,9 +29,10 @@ export function generatePagingHelper(project: Project) {
|
|
|
29
29
|
return `"${value}"`;
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
const { srcPath } = getAutorestOptions();
|
|
32
33
|
const readmeFileContents = hbs.compile(file, { noEscape: true });
|
|
33
34
|
project.createSourceFile(
|
|
34
|
-
"
|
|
35
|
+
path.join(srcPath, "paginateHelper.ts"),
|
|
35
36
|
readmeFileContents(pagingInfo),
|
|
36
37
|
{
|
|
37
38
|
overwrite: true
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
Operation,
|
|
4
4
|
Parameter,
|
|
5
5
|
SchemaContext,
|
|
6
|
-
Request as OperationRequest
|
|
6
|
+
Request as OperationRequest,
|
|
7
|
+
ParameterLocation
|
|
7
8
|
} from "@autorest/codemodel";
|
|
8
9
|
import {
|
|
9
10
|
InterfaceDeclarationStructure,
|
|
@@ -12,12 +13,14 @@ import {
|
|
|
12
13
|
SourceFile,
|
|
13
14
|
StructureKind
|
|
14
15
|
} from "ts-morph";
|
|
16
|
+
import * as path from 'path';
|
|
15
17
|
import { getLanguageMetadata } from "../utils/languageHelpers";
|
|
16
18
|
import { NameType, normalizeName } from "../utils/nameUtils";
|
|
17
19
|
import { getPropertySignature } from "./getPropertySignature";
|
|
18
20
|
import { primitiveSchemaToType } from "./schemaHelpers";
|
|
19
21
|
import { getOperationParameters } from "./helpers/operationHelpers";
|
|
20
22
|
import { hasInputModels } from "./helpers/modelHelpers";
|
|
23
|
+
import { getAutorestOptions } from "../autorestSession";
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
26
|
* Generates the interfaces describing each operation parameters
|
|
@@ -26,8 +29,9 @@ export function generateParameterInterfaces(
|
|
|
26
29
|
model: CodeModel,
|
|
27
30
|
project: Project
|
|
28
31
|
) {
|
|
32
|
+
const { srcPath } = getAutorestOptions();
|
|
29
33
|
const parametersFile = project.createSourceFile(
|
|
30
|
-
`
|
|
34
|
+
path.join(srcPath, `parameters.ts`),
|
|
31
35
|
undefined,
|
|
32
36
|
{
|
|
33
37
|
overwrite: true
|
|
@@ -74,6 +78,15 @@ export function generateParameterInterfaces(
|
|
|
74
78
|
|
|
75
79
|
const request = operation.requests ? operation.requests[i] : undefined;
|
|
76
80
|
|
|
81
|
+
const pathParameterDefinitions = buildPathParameterDefinitions(
|
|
82
|
+
operationName,
|
|
83
|
+
parameters,
|
|
84
|
+
model,
|
|
85
|
+
parametersFile,
|
|
86
|
+
internalReferences,
|
|
87
|
+
i
|
|
88
|
+
)
|
|
89
|
+
|
|
77
90
|
const headerParameterDefinitions = buildHeaderParameterDefinitions(
|
|
78
91
|
operationName,
|
|
79
92
|
parameters,
|
|
@@ -102,6 +115,7 @@ export function generateParameterInterfaces(
|
|
|
102
115
|
parametersFile.addInterfaces([
|
|
103
116
|
...(bodyParameterDefinition ?? []),
|
|
104
117
|
...(queryParameterDefinitions ?? []),
|
|
118
|
+
...(pathParameterDefinitions ? [pathParameterDefinitions]: []),
|
|
105
119
|
...(headerParameterDefinitions ? [headerParameterDefinitions] : []),
|
|
106
120
|
...(contentTypeParameterDefinition
|
|
107
121
|
? [contentTypeParameterDefinition]
|
|
@@ -233,6 +247,81 @@ function buildHeaderParameterDefinitions(
|
|
|
233
247
|
};
|
|
234
248
|
}
|
|
235
249
|
|
|
250
|
+
function getPathInterfaceDefinition(
|
|
251
|
+
parameters: Parameter[],
|
|
252
|
+
baseName: string,
|
|
253
|
+
model: CodeModel
|
|
254
|
+
): undefined | InterfaceDeclarationStructure {
|
|
255
|
+
// Check if there are any path parameters
|
|
256
|
+
const pathParameters = parameters.filter(
|
|
257
|
+
p => p.protocol.http?.in === ParameterLocation.Uri && model.globalParameters?.indexOf(p) === -1
|
|
258
|
+
);
|
|
259
|
+
if (!pathParameters.length) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
const pathInterfaceName = `${baseName}PathParameters`;
|
|
263
|
+
return {
|
|
264
|
+
kind: StructureKind.Interface,
|
|
265
|
+
isExported: true,
|
|
266
|
+
name: pathInterfaceName,
|
|
267
|
+
properties: pathParameters.map((h: Parameter) => {
|
|
268
|
+
const description = getLanguageMetadata(h.language).description;
|
|
269
|
+
return {
|
|
270
|
+
name: `"${getLanguageMetadata(h.language).serializedName}"`,
|
|
271
|
+
...(description && { docs: [{ description }] }),
|
|
272
|
+
type: primitiveSchemaToType(h.schema, [
|
|
273
|
+
SchemaContext.Input,
|
|
274
|
+
SchemaContext.Exception
|
|
275
|
+
]),
|
|
276
|
+
hasQuestionToken: !h.required
|
|
277
|
+
};
|
|
278
|
+
})
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function buildPathParameterDefinitions(
|
|
283
|
+
operationName: string,
|
|
284
|
+
parameters: Parameter[],
|
|
285
|
+
model: CodeModel,
|
|
286
|
+
parametersFile: SourceFile,
|
|
287
|
+
internalReferences: Set<string>,
|
|
288
|
+
requestIndex: number
|
|
289
|
+
): InterfaceDeclarationStructure | undefined {
|
|
290
|
+
const pathParameters = parameters.filter(
|
|
291
|
+
p => p.protocol.http?.in === ParameterLocation.Uri && model.globalParameters?.indexOf(p) === -1
|
|
292
|
+
);
|
|
293
|
+
if (!pathParameters.length) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
|
|
298
|
+
const pathParameterInterfaceName = `${operationName}PathParam${nameSuffix}`;
|
|
299
|
+
|
|
300
|
+
const pathInterface = getPathInterfaceDefinition(
|
|
301
|
+
pathParameters,
|
|
302
|
+
operationName,
|
|
303
|
+
model
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
if (pathInterface) {
|
|
307
|
+
parametersFile.addInterface(pathInterface);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
internalReferences.add(pathParameterInterfaceName);
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
isExported: true,
|
|
314
|
+
kind: StructureKind.Interface,
|
|
315
|
+
name: pathParameterInterfaceName,
|
|
316
|
+
properties: [
|
|
317
|
+
{
|
|
318
|
+
name: "pathParameters",
|
|
319
|
+
type: `${operationName}PathParameters`,
|
|
320
|
+
kind: StructureKind.PropertySignature
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
};
|
|
324
|
+
}
|
|
236
325
|
/**
|
|
237
326
|
* Gets the interface definition for an operation bodyParameters
|
|
238
327
|
*/
|
|
@@ -2,6 +2,7 @@ import { readFileSync } from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as hbs from "handlebars";
|
|
4
4
|
import { Project } from "ts-morph";
|
|
5
|
+
import { getAutorestOptions } from "../autorestSession";
|
|
5
6
|
|
|
6
7
|
export function generatePollingHelper(project: Project) {
|
|
7
8
|
let file: string = "";
|
|
@@ -11,7 +12,8 @@ export function generatePollingHelper(project: Project) {
|
|
|
11
12
|
});
|
|
12
13
|
|
|
13
14
|
const readmeFileContents = hbs.compile(file, { noEscape: true });
|
|
14
|
-
|
|
15
|
+
const { srcPath } = getAutorestOptions();
|
|
16
|
+
project.createSourceFile(path.join(srcPath, "pollingHelper.ts"), readmeFileContents({}), {
|
|
15
17
|
overwrite: true
|
|
16
18
|
});
|
|
17
19
|
}
|
|
@@ -22,10 +22,13 @@ import { NameType, normalizeName } from "../utils/nameUtils";
|
|
|
22
22
|
import { getElementType, getFormatDocs, primitiveSchemaToType } from "./schemaHelpers";
|
|
23
23
|
import { getLanguageMetadata } from "../utils/languageHelpers";
|
|
24
24
|
import { hasOutputModels } from "./helpers/modelHelpers";
|
|
25
|
+
import { getAutorestOptions } from "../autorestSession";
|
|
26
|
+
import * as path from 'path';
|
|
25
27
|
|
|
26
28
|
export function generateResponseInterfaces(model: CodeModel, project: Project) {
|
|
29
|
+
const { srcPath } = getAutorestOptions();
|
|
27
30
|
const responsesFile = project.createSourceFile(
|
|
28
|
-
`
|
|
31
|
+
path.join(srcPath, `responses.ts`),
|
|
29
32
|
undefined,
|
|
30
33
|
{
|
|
31
34
|
overwrite: true
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getHost, getSession } from "../autorestSession";
|
|
1
|
+
import { getAutorestOptions, getHost, getSession } from "../autorestSession";
|
|
2
2
|
import { Project, IndentationText } from "ts-morph";
|
|
3
3
|
import { generatePackageJson } from "../generators/static/packageFileGenerator";
|
|
4
4
|
import { generateLicenseFile } from "../generators/static/licenseFileGenerator";
|
|
@@ -10,10 +10,12 @@ import { generateSchemaTypes } from "./generateSchemaTypes";
|
|
|
10
10
|
import { format } from "prettier";
|
|
11
11
|
import { prettierJSONOptions, prettierTypeScriptOptions } from "./config";
|
|
12
12
|
import { generateParameterInterfaces } from "./generateParameterTypes";
|
|
13
|
-
import { generatePathFirstClient } from "./
|
|
13
|
+
import { generatePathFirstClient } from "./generateClientDefinition";
|
|
14
|
+
import { generateClient } from './generateClient';
|
|
14
15
|
import { generateIndexFile } from "../generators/indexGenerator";
|
|
15
16
|
import { generatePagingHelper } from "./generatePagingHelper";
|
|
16
17
|
import { generatePollingHelper } from "./generatePollingHelper";
|
|
18
|
+
import { generateTopLevelIndexFile } from './generateTopLevelIndexFile';
|
|
17
19
|
import { hasPagingOperations } from "../utils/extractPaginationDetails";
|
|
18
20
|
import { hasPollingOperations } from "./helpers/hasPollingOperations";
|
|
19
21
|
import { generateKarmaConfigFile } from "../generators/static/karmaConfigFileGenerator";
|
|
@@ -21,6 +23,7 @@ import { generateEnvFile } from "../generators/test/envFileGenerator";
|
|
|
21
23
|
import { generateEnvBrowserFile } from "../generators/test/envBrowserFileGenerator";
|
|
22
24
|
import { generateRecordedClientFile } from "../generators/test/recordedClientFileGenerator";
|
|
23
25
|
import { generateSampleTestFile } from "../generators/test/sampleTestGenerator";
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
28
|
* Generates a Rest Level Client library
|
|
26
29
|
*/
|
|
@@ -59,7 +62,10 @@ export async function generateRestLevelClient() {
|
|
|
59
62
|
generateSchemaTypes(model, project);
|
|
60
63
|
generateParameterInterfaces(model, project);
|
|
61
64
|
generatePathFirstClient(model, project);
|
|
65
|
+
generateClient(model, project);
|
|
62
66
|
generateIndexFile(project);
|
|
67
|
+
|
|
68
|
+
generateTopLevelIndexFile(model, project);
|
|
63
69
|
|
|
64
70
|
// Save the source files to the virtual filesystem
|
|
65
71
|
project.saveSync();
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { CodeModel, SchemaContext } from "@autorest/codemodel";
|
|
2
2
|
import { Project } from "ts-morph";
|
|
3
|
+
import * as path from 'path';
|
|
3
4
|
import {
|
|
4
5
|
buildObjectInterfaces,
|
|
5
6
|
buildPolymorphicAliases
|
|
6
7
|
} from "./generateObjectTypes";
|
|
8
|
+
import { getAutorestOptions } from "../autorestSession";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Generates types to represent schema definitions in the swagger
|
|
@@ -18,10 +20,10 @@ export function generateSchemaTypes(model: CodeModel, project: Project) {
|
|
|
18
20
|
const objectTypeAliases = buildPolymorphicAliases(model, [
|
|
19
21
|
SchemaContext.Input
|
|
20
22
|
]);
|
|
21
|
-
|
|
23
|
+
const { srcPath } = getAutorestOptions();
|
|
22
24
|
if (objectTypeAliases.length || objectsDefinitions.length) {
|
|
23
25
|
const inputModelsFile = project.createSourceFile(
|
|
24
|
-
`
|
|
26
|
+
path.join(srcPath, `models.ts`),
|
|
25
27
|
undefined,
|
|
26
28
|
{
|
|
27
29
|
overwrite: true
|
|
@@ -42,7 +44,7 @@ export function generateSchemaTypes(model: CodeModel, project: Project) {
|
|
|
42
44
|
|
|
43
45
|
if (outputObjectTypeAliases.length || outputObjectsDefinitions.length) {
|
|
44
46
|
const outputModelsFile = project.createSourceFile(
|
|
45
|
-
`
|
|
47
|
+
path.join(srcPath, `outputModels.ts`),
|
|
46
48
|
undefined,
|
|
47
49
|
{
|
|
48
50
|
overwrite: true
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Project } from 'ts-morph';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { getAutorestOptions } from '../autorestSession';
|
|
4
|
+
import { CodeModel } from '@autorest/codemodel';
|
|
5
|
+
import { NameType, normalizeName } from '../utils/nameUtils';
|
|
6
|
+
|
|
7
|
+
const batchOutputFolder: [string, string, string][] = [];
|
|
8
|
+
|
|
9
|
+
export function generateTopLevelIndexFile(model: CodeModel, project: Project) {
|
|
10
|
+
const { batch, srcPath } = getAutorestOptions();
|
|
11
|
+
if (srcPath) {
|
|
12
|
+
const clientName = model.language.default.name;
|
|
13
|
+
const moduleName = normalizeName(clientName, NameType.File);
|
|
14
|
+
const relativePath = srcPath.replace('/src', '');
|
|
15
|
+
batchOutputFolder.push([relativePath, clientName, moduleName]);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (batch && batch.length > 1 && batchOutputFolder.length === batch.length) {
|
|
19
|
+
const { srcPath } = getAutorestOptions();
|
|
20
|
+
const fileDirectory= path.join(srcPath as string, '../../');
|
|
21
|
+
const file = project.createSourceFile('/src/index.ts', undefined, {
|
|
22
|
+
overwrite: true
|
|
23
|
+
});
|
|
24
|
+
file.moveToDirectory(fileDirectory);
|
|
25
|
+
const allModules: string[] = [];
|
|
26
|
+
batchOutputFolder.forEach(item => {
|
|
27
|
+
file.addImportDeclaration({
|
|
28
|
+
namespaceImport: item[1],
|
|
29
|
+
moduleSpecifier: `${item[0]}`
|
|
30
|
+
});
|
|
31
|
+
file.addExportDeclaration({
|
|
32
|
+
moduleSpecifier: `${item[0]}/${item[2]}`,
|
|
33
|
+
namedExports: [`${item[1]} as ${item[1]}Client`]
|
|
34
|
+
})
|
|
35
|
+
allModules.push(item[1]);
|
|
36
|
+
});
|
|
37
|
+
file.addExportDeclaration({
|
|
38
|
+
namedExports: [...allModules]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -33,6 +33,7 @@ export async function extractAutorestOptions(): Promise<AutorestOptions> {
|
|
|
33
33
|
const headAsBoolean = await getHeadAsBoolean(host);
|
|
34
34
|
const isTestPackage = await getIsTestPackage(host);
|
|
35
35
|
const generateTest = await getGenerateTest(host);
|
|
36
|
+
const batch = await getBatch(host);
|
|
36
37
|
const generateSample = await getGenerateSample(host);
|
|
37
38
|
|
|
38
39
|
return {
|
|
@@ -59,6 +60,7 @@ export async function extractAutorestOptions(): Promise<AutorestOptions> {
|
|
|
59
60
|
headAsBoolean,
|
|
60
61
|
isTestPackage,
|
|
61
62
|
generateTest,
|
|
63
|
+
batch,
|
|
62
64
|
generateSample
|
|
63
65
|
};
|
|
64
66
|
}
|
|
@@ -284,3 +286,10 @@ async function getAzureOutputDirectoryPath(
|
|
|
284
286
|
? outputDirectoryRelativePath
|
|
285
287
|
: undefined;
|
|
286
288
|
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
async function getBatch(host: AutorestExtensionHost): Promise<[string, any][] | undefined> {
|
|
292
|
+
const batch = await host.getValue<[string, any][]>('batch');
|
|
293
|
+
return batch;
|
|
294
|
+
|
|
295
|
+
}
|