in packages/typespec-go/src/tcgcadapter/clients.ts [580:692]
private adaptResponseEnvelope(sdkMethod: tcgc.SdkServiceMethod<tcgc.SdkHttpOperation>, method: go.Method): go.ResponseEnvelope {
// TODO: add Envelope suffix if name collides with existing type
let prefix = method.client.name;
if (this.opts['single-client']) {
prefix = '';
}
let respEnvName = `${prefix}${method.name}Response`;
if (sdkMethod.access === 'internal') {
respEnvName = uncapitalize(respEnvName);
}
const respEnv = new go.ResponseEnvelope(respEnvName, {summary: createResponseEnvelopeDescription(respEnvName, this.getMethodNameForDocComment(method))}, method);
this.ta.codeModel.responseEnvelopes.push(respEnv);
// add any headers
const addedHeaders = new Set<string>();
for (const httpResp of sdkMethod.operation.responses) {
for (const httpHeader of httpResp.headers) {
if (addedHeaders.has(httpHeader.serializedName)) {
continue;
} else if (go.isLROMethod(method) && httpHeader.serializedName.match(/Azure-AsyncOperation|Location|Operation-Location|Retry-After/i)) {
// we omit the LRO polling headers as they aren't useful on the response envelope
continue;
}
// TODO: x-ms-header-collection-prefix
const headerResp = new go.HeaderResponse(ensureNameCase(httpHeader.serializedName), this.adaptHeaderType(httpHeader.type, false), httpHeader.serializedName, isTypePassedByValue(httpHeader.type));
headerResp.docs.summary = httpHeader.summary;
headerResp.docs.description = httpHeader.doc;
respEnv.headers.push(headerResp);
addedHeaders.add(httpHeader.serializedName);
}
}
let sdkResponseType = sdkMethod.response.type;
// since HEAD requests don't return a type, we must check this before checking sdkResponseType
if (method.httpMethod === 'head' && this.opts['head-as-boolean'] === true) {
respEnv.result = new go.HeadAsBooleanResult('Success');
respEnv.result.docs.summary = 'Success indicates if the operation succeeded or failed.';
}
if (!sdkResponseType) {
// method doesn't return a type, so we're done
return respEnv;
}
// for paged methods, tcgc models the method response type as an Array<T>.
// however, we want the synthesized paged response envelope as that's what Go returns.
if (sdkMethod.kind === 'paging') {
// grab the paged response envelope type from the first response
sdkResponseType = values(sdkMethod.operation.responses).first()!.type!;
}
// we have a response type, determine the content type
let contentType: go.BodyFormat = 'binary';
if (sdkMethod.kind === 'lro') {
// we can't grovel through the operation responses for LROs as some of them
// return only headers, thus have no content type. while it's highly likely
// to only ever be JSON, this will be broken for LROs that return text/plain
// or a binary response. the former seems unlikely, the latter though...??
// TODO: https://github.com/Azure/typespec-azure/issues/535
contentType = 'JSON';
} else {
let foundResp = false;
for (const httpResp of sdkMethod.operation.responses) {
if (!httpResp.type || !httpResp.defaultContentType || httpResp.type.kind !== sdkResponseType.kind) {
continue;
}
contentType = this.adaptContentType(httpResp.defaultContentType);
foundResp = true;
break;
}
if (!foundResp) {
throw new AdapterError('InternalError', `didn't find HTTP response for kind ${sdkResponseType.kind} in method ${method.name}`, sdkResponseType.__raw?.node ?? NoTarget);
}
}
if (contentType === 'binary') {
respEnv.result = new go.BinaryResult('Body', 'binary');
respEnv.result.docs.summary = 'Body contains the streaming response.';
return respEnv;
} else if (sdkResponseType.kind === 'model') {
let modelType: go.ModelType | undefined;
const modelName = ensureNameCase(sdkResponseType.name).toUpperCase();
for (const model of this.ta.codeModel.models) {
if (model.name.toUpperCase() === modelName) {
modelType = model;
break;
}
}
if (!modelType) {
throw new AdapterError('InternalError', `didn't find model type name ${sdkResponseType.name} for response envelope ${respEnv.name}`, sdkResponseType.__raw?.node ?? NoTarget);
}
if (go.isPolymorphicType(modelType)) {
respEnv.result = new go.PolymorphicResult(modelType.interface);
} else {
if (contentType !== 'JSON' && contentType !== 'XML') {
throw new AdapterError('InternalError', `unexpected content type ${contentType} for model ${modelType.name}`, NoTarget);
}
respEnv.result = new go.ModelResult(modelType, contentType);
}
respEnv.result.docs.summary = sdkResponseType.summary;
respEnv.result.docs.description = sdkResponseType.doc;
} else {
const resultType = this.ta.getPossibleType(sdkResponseType, false, false);
if (go.isInterfaceType(resultType) || go.isLiteralValue(resultType) || go.isModelType(resultType) || go.isPolymorphicType(resultType) || go.isQualifiedType(resultType)) {
throw new AdapterError('InternalError', `invalid monomorphic result type ${go.getTypeDeclaration(resultType)}`, sdkResponseType.__raw?.node ?? NoTarget);
}
respEnv.result = new go.MonomorphicResult(this.recursiveTypeName(sdkResponseType, false), contentType, resultType, isTypePassedByValue(sdkResponseType));
}
return respEnv;
}