UNPKG

@microsoft.azure/autorest.incubator

Version:
155 lines (154 loc) 9.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const http_operation_1 = require("../common/code-model/http-operation"); const schema_1 = require("../common/code-model/schema"); const dictionary_1 = require("../common/dictionary"); const process_code_model_1 = require("../common/process-code-model"); const autorest_extension_base_1 = require("@microsoft.azure/autorest-extension-base"); const known_format_1 = require("../remodeler/known-format"); const media_types_1 = require("../common/media-types"); exports.HeaderProperty = 'HeaderProperty'; var HeaderPropertyType; (function (HeaderPropertyType) { HeaderPropertyType["Header"] = "Header"; HeaderPropertyType["HeaderAndBody"] = "HeaderAndBody"; })(HeaderPropertyType = exports.HeaderPropertyType || (exports.HeaderPropertyType = {})); // Universal version - // tweaks the code model to adjust things so that the code will generate better. async function process(service) { return process_code_model_1.processCodeModel(tweakModel, service); } exports.process = process; async function tweakModel(model, service) { /* REMOVE THIS -- not handled here anymore // consolodate compatible response types. for (const operation of values(model.http.operations)) { // TODO: mimetypes might start with the mimetype and have extra stuff after // this should be fixed if it happens. // if an operation response has a application/json and text/json, remove the text/json and add that mime type to the list of 'accepts' for (const response of values(operation.responses)) { const content = response.content; if (content['application/json'] && content['text/json']) { content['application/json'].accepts.push('text/json'); delete content['text/json']; service.Message({ Channel: Channel.Debug, Text: `operation '${operation.details.default.name}' lists both "application/json" and "text/json" -- these are being combined.` }); } } } */ // if an operation has a response that has a schema with string/binary we should make the response application/octet-stream for (const operation of dictionary_1.values(model.http.operations)) { for (const { key: responseCode, value: responses } of dictionary_1.items(operation.responses_new)) { for (const response of responses) { if (response.schema) { if (response.schema.type === schema_1.JsonType.String && response.schema.format === known_format_1.StringFormat.Binary) { response.mimeTypes = [media_types_1.KnownMediaType.Stream]; } } } } } if (await service.GetValue('use-storage-pipeline')) { // we're going to create new models for the reponse headers ? } else { // if an operation has a body parameter with string/binary, we should make the request application/octet-stream // === Header Schemas === // go thru the operations, find responses that have header values, and add a property to the schemas that are returned with those values for (const operation of dictionary_1.values(model.http.operations)) { for (const { key: mediaType, value: responses } of dictionary_1.items(operation.responses_new)) { for (const response of responses) { // for a given response, find the possible models that can be returned from the service for (const header of dictionary_1.items(response.headers)) { if (!response.schema) { // no response schema? can we fake one? service.Message({ Channel: autorest_extension_base_1.Channel.Debug, Text: `${header.key} is in ${operation.details.default.name} but there is no response model` }); } // if the method response has a schema and it's an object, we're going to add our properties to the schema object. // yes, this means that the reponse model may have properties that are undefined if the server doesn't send back the header // and other operations might add other headers that are not the same. // if the method's response is a primitive value (string, boolean, null, number) or an array, we can't modify that type obviously // in which case, we're going to add a header // work with schemas that have objects only. if (schema_1.isSchemaObject(response.schema)) { const property = response.schema.properties[header.key]; if (!property) { service.Message({ Channel: autorest_extension_base_1.Channel.Debug, Text: `Adding header property ${header.key} to model ${response.schema.details.default.name}` }); // create a property for the header value const newProperty = new schema_1.Property(header.key, { schema: header.value.schema, description: header.value.description }); // mark it that it's a header-only property newProperty.details.default[exports.HeaderProperty] = HeaderPropertyType.Header; // add it to this model. response.schema.properties[header.key] = newProperty; } else { // there is a property with this name already. // was this previously declared as a header only property? if (!property.details[exports.HeaderProperty]) { service.Message({ Channel: autorest_extension_base_1.Channel.Debug, Text: `Property ${header.key} in model ${response.schema.details.name} can also come from the header.` }); // no.. There is duplication between header and body property. Probably because of etags. // tell it to be a header-and-body property. property.details.default[exports.HeaderProperty] = HeaderPropertyType.HeaderAndBody; } } } } } } } } // remove well-known header parameters from operations and add mark the operation has supporting that feature for (const operation of dictionary_1.values(model.http.operations)) { // move well-known hearder parameters into details, and we can process them in the generator how we please. operation.details.default.headerparameters = dictionary_1.values(operation.parameters).linq.where(p => p.in === http_operation_1.ParameterLocation.Header && ['?????'].includes(p.name)).linq.toArray(); // operation.parameters = dictionary_1.values(operation.parameters).linq.where(p => !(p.in === http_operation_1.ParameterLocation.Header && ['?????'].includes(p.name))).linq.toArray(); } // identify models that are polymorphic in nature for (const schema of dictionary_1.values(model.schemas)) { // if this actual type is polymorphic, make sure we know that. if (schema.discriminator) { schema.details.default.isPolymorphic = true; } // make sure that all our polymorphic parents have a reference to this type. for (const parent of schema_1.getPolymorphicBases(schema)) { parent.details.polymorphicChildren = parent.details.polymorphicChildren || new Array(); parent.details.polymorphicChildren.push(schema); } } // identify parameters that are constants for (const operation of dictionary_1.values(model.http.operations)) { for (const parameter of dictionary_1.values(operation.parameters)) { if (parameter.schema.enum.length === 1) { // parameters with an enum single value are constants parameter.details.default.constantValue = parameter.schema.enum[0]; } if (parameter.name === 'api-version') { // only set it if it hasn't been set yet. if (!parameter.details.default.constantValue) { // api-version constant parameter pulls value from the model/info/version parameter.details.default.constantValue = model.info.version; } if (!parameter.details.default.constantValue) { // um... api-version didn't have an enum, and we didn't get from model.info.version. // that's not cool. service.Message({ Channel: autorest_extension_base_1.Channel.Error, Text: `Parameter 'api-version' doesn't have a single enum-value, and model.info.version is '${model.info.version}' ` }); } } } } for (const operation of dictionary_1.values(model.http.operations)) { for (const { key: responseCode, value: responses } of dictionary_1.items(operation.responses_new)) { for (const response of dictionary_1.values(responses)) { if (responseCode === 'default' || response.extensions['x-ms-error-response'] === true) { response.details.default.isErrorResponse = true; } } } } return model; } //# sourceMappingURL=tweak-model.js.map