@autorest/powershell
Version:
AutoRest PowerShell Cmdlet Generator
180 lines • 11.3 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.tweakModelAzurePluginV2 = exports.tweakModel = void 0;
const linq_1 = require("@azure-tools/linq");
const model_state_1 = require("../utils/model-state");
const codemodel_1 = require("@autorest/codemodel");
const codegen_1 = require("@azure-tools/codegen");
const xmsPageable = 'x-ms-pageable';
async function tweakModel(state) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
const model = state.model;
// service.message{ Channel: Channel.Debug, Text: "THIS IS THE AZURE TWEAKER" });
// TODO:
// look at models, and extract out any case that has an IRESOURCE, IPROXYRESOURCE, etc.
// and use the common versions of those models.
// Is the result marked x-ms-pagable?
// identify the next link (null means just get the results as an array)
// if nextLinkName is null, then it won't actually page, but we'd like to unroll the contents anyway.
for (const group of (0, linq_1.values)(model.operationGroups)) {
for (const operation of (0, linq_1.values)(group.operations)) {
if (operation.extensions && operation.extensions[xmsPageable]) {
// it's marked pagable.
operation.language.default.pageable = {
responseType: 'pageable',
nextLinkName: operation.extensions[xmsPageable].nextLinkName || undefined,
itemName: operation.extensions[xmsPageable].itemName || 'value',
operationName: operation.extensions[xmsPageable].operationName || `${operation.language.default.name}Next`,
};
continue;
}
// let's just check to see if it looks like it's supposed to be a collection
for (const response of (0, linq_1.values)(operation.responses)) {
// does the response have a schema?
// TODO: check schema
if (getSchema(response)) {
const schema = getSchema(response);
// is this just an array response?
if (schema.type === codemodel_1.SchemaType.Array) {
operation.language.default.pageable = {
responseType: 'array',
};
continue;
}
// if it returns an object, let's see what's inside...
if (schema.type === codemodel_1.SchemaType.Object) {
const objSchema = schema;
// does it have a single member that is an array (ie, value : [...])
if ((0, linq_1.length)(objSchema.properties) === 1 && !objSchema.parents) {
const property = (_a = objSchema.properties) === null || _a === void 0 ? void 0 : _a[0];
if (property) {
if (property.schema.type === codemodel_1.SchemaType.Array) {
// nested array!
operation.language.default.pageable = {
responseType: 'nested-array',
itemName: property.serializedName,
};
}
continue;
}
}
// xichen: If response schema has only 2 properties and one of it is nextLink, the other is array
// does it kinda look like a x-ms-pagable (value/nextlink?)
if ((0, linq_1.length)(objSchema.properties) === 2 && !objSchema.parents) {
const hasNextLink = (_b = objSchema.properties) === null || _b === void 0 ? void 0 : _b.some((prop) => prop.serializedName === 'nextLink');
if (hasNextLink) {
const property = (_c = objSchema.properties) === null || _c === void 0 ? void 0 : _c.find((prop) => prop.serializedName !== 'nextLink');
if (property) {
if (property.schema.type === codemodel_1.SchemaType.Array) {
// nested array!
operation.language.default.pageable = {
responseType: 'nested-array',
itemName: property.serializedName,
nextLinkName: 'nextLink'
};
}
continue;
}
}
}
}
}
}
}
}
// make sure that all operations with lro have an options block.
for (const group of (0, linq_1.values)(model.operationGroups)) {
for (const operation of (0, linq_1.values)(group.operations)) {
if (operation.extensions && operation.extensions['x-ms-long-running-operation']) {
operation.language.default.asjob = true;
operation.language.default.lro = operation.extensions['x-ms-long-running-operation-options'] || {
'final-state-via': 'default'
};
// LRO 201 and 202 responses are handled internally, so remove any 201/202 responses in the operation
operation.responses = (operation.responses).filter(each => { var _a, _b; return ((_a = each.protocol.http) === null || _a === void 0 ? void 0 : _a.statusCodes[0]) !== '201' && ((_b = each.protocol.http) === null || _b === void 0 ? void 0 : _b.statusCodes[0]) !== '202'; });
//delete operation.responses['201'];
//delete operation.responses['202'];
// for lro deletion, we need to add the 200 response if it's not already there.
if (operation.requests && (((_d = operation.requests[0].protocol.http) === null || _d === void 0 ? void 0 : _d.method) === 'delete' || ((_e = operation.requests[0].protocol.http) === null || _e === void 0 ? void 0 : _e.method) === 'post')) {
if (!operation.responses.find(each => { var _a; return ((_a = each.protocol.http) === null || _a === void 0 ? void 0 : _a.statusCodes[0]) === '200'; })) {
const response = new codemodel_1.Response();
response.protocol.http = (_f = response.protocol.http) !== null && _f !== void 0 ? _f : new codemodel_1.Protocol();
response.protocol.http.statusCodes = ['200'];
operation.responses.push(response);
}
}
}
}
}
// xichen: Cannot find 'x-ms-metadata' from swagger repo. Are we still using it?
// Api Version parameter handling for Azure.
// if there is only a single api-version for the operation, let's just make it a constant
// otherwise, we need to make it selectable, but default to the 'latest' version there is.
for (const group of (0, linq_1.values)(model.operationGroups)) {
for (const operation of (0, linq_1.values)(group.operations)) {
const apiVersions = operation.apiVersions;
for (const parameter of (0, linq_1.values)(operation.parameters)) {
if (parameter.language.default.serializedName === 'api-version') {
// only set it if it hasn't been set yet.
// if (parameter.details.default.constantValue) {
//continue;
//}
if (apiVersions) {
// set the constant value to the first one
if ((0, linq_1.length)(apiVersions) === 1) {
parameter.language.default.constantValue = apiVersions[0].version;
continue;
}
// otherwise, the parameter can't have a constant value
parameter.language.default.constantValue = undefined;
// mark it so that we can add profile support in the method generation
parameter.language.default.apiversion = true;
}
}
}
}
}
// when make-sub-resources-byreference is specified, mark models with a writable id as byref.
if (await state.getValue('azure', false) && await state.getValue('make-sub-resources-byreference', false)) {
for (const schema of (0, linq_1.values)((_g = model.schemas.objects) !== null && _g !== void 0 ? _g : [])) {
// find schemas that have an 'id' and are not readonly
if ((0, linq_1.values)((0, codemodel_1.getAllProperties)(schema)).any(prop => prop.serializedName === 'id' && !prop.language.default.readOnly)) {
// look thru the operations, and the PUT methods
for (const group of model.operationGroups) {
for (const op of (0, linq_1.values)(group.operations)) {
for (const request of (_h = op.requests) !== null && _h !== void 0 ? _h : []) {
if (((_j = request.protocol.http) === null || _j === void 0 ? void 0 : _j.method) === 'put') {
for (const response of (_k = op.responses) !== null && _k !== void 0 ? _k : []) {
// see if any of the responses have the same schema as we are looking for
if (getSchema(response) === schema) {
// tell it not to inline that
schema.language.default.byReference = true;
break;
}
}
break;
}
}
}
}
}
}
}
return model;
}
exports.tweakModel = tweakModel;
function getSchema(response) {
return response.schema;
}
// Azure version -
// Additional tweaks the code model to adjust things so that the code will generate better.
async function tweakModelAzurePluginV2(service) {
const state = await new model_state_1.ModelState(service).init();
await service.writeFile({ filename: 'code-model-v4-tweakcodemodelazure-v2.yaml', content: (0, codegen_1.serialize)(await tweakModel(state)), sourceMap: undefined, artifactType: 'code-model-v4' });
}
exports.tweakModelAzurePluginV2 = tweakModelAzurePluginV2;
//# sourceMappingURL=plugin-tweak-model-azure-v2.js.map
;