packages/codemodel.go/src/result.ts (181 lines of code) (raw):
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as client from './client.js';
import { CodeModelError } from './errors.js';
import * as param from './param.js';
import * as type from './type.js';
export type ResultType = AnyResult | BinaryResult | HeadAsBooleanResult | MonomorphicResult | PolymorphicResult | ModelResult;
// ResponseEnvelope is the type returned from a client method
export interface ResponseEnvelope {
name: string;
docs: type.Docs;
// for operations that return no body (e.g. a 204) this will be undefined.
result?: ResultType;
// any modeled response headers
headers: Array<HeaderResponse | HeaderMapResponse>;
method: client.Method | client.LROMethod | client.PageableMethod | client.LROPageableMethod;
}
export type ResultFormat = 'JSON' | 'XML' | 'Text';
// AnyResult is for endpoints that return a different schema based on the HTTP status code.
export interface AnyResult {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
// maps an HTTP status code to a result type.
// status codes that don't return a schema will be absent.
httpStatusCodeType: Record<number, type.PossibleType>;
// the format in which the result is returned
format: ResultFormat;
byValue: true;
}
// TODO: would this ever be anything else?
export type BinaryResultFormat = 'binary';
// BinaryResult is for responses that return the streaming response (i.e. the http.Response.Body)
export interface BinaryResult {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
binaryFormat: BinaryResultFormat;
byValue: true;
}
// HeadAsBooleanResult is for responses to HTTP HEAD requests that treat the HTTP status code as success/failure
export interface HeadAsBooleanResult {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
headAsBoolean: true;
byValue: true;
}
export type MonomorphicResultType = type.BytesType | type.ConstantType | type.MapType | type.PrimitiveType | type.SliceType | type.TimeType;
// MonomorphicResult includes scalar results (ints, bools) or maps/slices of scalars/InterfaceTypes/ModelTypes.
// maps/slices can be recursive and/or combinatorial (e.g. map[string][]*sometype)
export interface MonomorphicResult {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
monomorphicType: MonomorphicResultType;
// the format in which the result is returned
format: ResultFormat;
byValue: boolean;
xml?: type.XMLInfo;
}
// PolymorphicResult is for discriminated types.
// The type is anonymously embedded in the response envelope.
export interface PolymorphicResult {
docs: type.Docs;
interfaceType: type.InterfaceType;
// the format in which the result is returned.
// only JSON is supported for polymorphic types.
format: 'JSON';
}
export type ModelResultFormat = 'JSON' | 'XML';
// ModelResult is a standard schema response.
// The type is anonymously embedded in the response envelope.
export interface ModelResult {
docs: type.Docs;
modelType: type.ModelType;
// the format in which the result is returned
format: ModelResultFormat;
}
export function isAnyResult(resultType: ResultType): resultType is AnyResult {
return (<AnyResult>resultType).httpStatusCodeType !== undefined;
}
export function isBinaryResult(resultType: ResultType): resultType is BinaryResult {
return (<BinaryResult>resultType).binaryFormat !== undefined;
}
export function isHeadAsBooleanResult(resultType: ResultType): resultType is HeadAsBooleanResult {
return (<HeadAsBooleanResult>resultType).headAsBoolean !== undefined;
}
export function isHeaderMapResponse(resp: HeaderResponse | HeaderMapResponse): resp is HeaderMapResponse {
return (<HeaderMapResponse>resp).collectionPrefix !== undefined;
}
export function isMonomorphicResult(resultType: ResultType): resultType is MonomorphicResult {
return (<MonomorphicResult>resultType).monomorphicType !== undefined;
}
export function isPolymorphicResult(resultType: ResultType): resultType is PolymorphicResult {
return (<PolymorphicResult>resultType).interfaceType !== undefined;
}
export function isModelResult(resultType: ResultType): resultType is ModelResult {
return (<ModelResult>resultType).modelType !== undefined;
}
export function getResultPossibleType(resultType: ResultType): type.PossibleType {
if (isAnyResult(resultType)) {
return new type.PrimitiveType('any');
} else if (isBinaryResult(resultType)) {
return new type.QualifiedType('ReadCloser', 'io');
} else if (isHeadAsBooleanResult(resultType)) {
return new type.PrimitiveType('bool');
} else if (isMonomorphicResult(resultType)) {
return resultType.monomorphicType;
} else if (isPolymorphicResult(resultType)) {
return resultType.interfaceType;
} else if (isModelResult(resultType)) {
return resultType.modelType;
} else {
throw new CodeModelError(`unhandled result type ${resultType}`);
}
}
export interface HeaderResponse {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
type: param.HeaderType;
byValue: boolean;
// the name of the header sent over the wire
headerName: string;
}
// this is a special type to support x-ms-header-collection-prefix (i.e. storage)
export interface HeaderMapResponse {
// the name of the field within the response envelope
fieldName: string;
docs: type.Docs;
type: type.MapType;
byValue: boolean;
// the name of the header sent over the wire
headerName: string;
collectionPrefix: string;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
export class ResponseEnvelope implements ResponseEnvelope {
constructor(name: string, docs: type.Docs, forMethod: client.Method) {
this.docs = docs;
this.headers = new Array<HeaderResponse | HeaderMapResponse>();
this.method = forMethod;
this.name = name;
}
}
export class HeaderResponse implements HeaderResponse {
constructor(fieldName: string, type: param.HeaderType, headerName: string, byValue: boolean) {
this.fieldName = fieldName;
this.type = type;
this.byValue = byValue;
this.headerName = headerName;
this.docs = {};
}
}
export class HeaderMapResponse implements HeaderMapResponse {
constructor(fieldName: string, type: type.MapType, collectionPrefix: string, headerName: string, byValue: boolean) {
this.fieldName = fieldName;
this.type = type;
this.collectionPrefix = collectionPrefix;
this.byValue = byValue;
this.headerName = headerName;
this.docs = {};
}
}
export class AnyResult implements AnyResult {
constructor(fieldName: string, format: ResultFormat, resultTypes: Record<number, type.PossibleType>) {
this.fieldName = fieldName;
this.format = format;
this.httpStatusCodeType = resultTypes;
this.byValue = true;
this.docs = {};
}
}
export class BinaryResult implements BinaryResult {
constructor(fieldName: string, format: BinaryResultFormat) {
this.fieldName = fieldName;
this.binaryFormat = format;
this.byValue = true;
this.docs = {};
}
}
export class HeadAsBooleanResult implements HeadAsBooleanResult {
constructor(fieldName: string) {
this.fieldName = fieldName;
this.headAsBoolean = true;
this.byValue = true;
this.docs = {};
}
}
export class MonomorphicResult implements MonomorphicResult {
constructor(fieldName: string, format: ResultFormat, type: MonomorphicResultType, byValue: boolean) {
this.fieldName = fieldName;
this.format = format;
this.monomorphicType = type;
this.byValue = byValue;
this.docs = {};
}
}
export class PolymorphicResult implements PolymorphicResult {
constructor(type: type.InterfaceType) {
this.interfaceType = type;
this.format = 'JSON';
this.docs = {};
}
}
export class ModelResult implements ModelResult {
constructor(type: type.ModelType, format: ModelResultFormat) {
this.modelType = type;
this.format = format;
this.docs = {};
}
}