powershell/utils/schema.ts (187 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 { ExternalDocumentation, ImplementationDetails, LanguageDetails } from './components'; import { Extensions } from './extensions'; import { DeepPartial, } from '@azure-tools/codegen'; import { Dictionary, values } from '@azure-tools/linq'; import { uid } from './uid'; import { Schema, ObjectSchema, Property, SchemaType, isObjectSchema } from '@autorest/codemodel'; import { EnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; import { ModelClass } from '../llcsharp/model/model-class'; import { ModelInterface } from '../llcsharp/model/interface'; export interface PropertyDetails extends ImplementationDetails { required: boolean; readOnly: boolean; } export interface EnumValue { value: any; description: string; name: string; } export interface EnumDetails { modelAsString: boolean; values: Array<EnumValue>; name: string; } export enum Purpose { Header = 'Header', } export interface Mutability { create: boolean, update: boolean, read: boolean } export interface VirtualProperty { /** The property that this represents */ property: Property; /** The things that went into building the name */ nameComponents: Array<string>; /** Names To use in priority order */ nameOptions: Array<string>; /** the name of this virtual property */ name: string; /** the member that should be called to get to the virtual property. (may be recursive) */ accessViaProperty?: VirtualProperty; accessViaMember?: VirtualProperty; /** the member's schema */ accessViaSchema?: Schema; originalContainingSchema: Schema; private?: boolean; alias: Array<string>; description: string; format?: PropertyFormat; required: boolean; readOnly?: boolean; sharedWith?: Array<VirtualProperty>; read?: boolean; update?: boolean; create?: boolean; serializedName?: string; } export interface PropertyFormat { suppressFormat?: boolean; index?: number; width?: number; label?: string; } export interface VirtualProperties { owned: Array<VirtualProperty>; inherited: Array<VirtualProperty>; inlined: Array<VirtualProperty>; } export interface SchemaDetails extends ImplementationDetails { /** namespace of the implementation of this item */ namespace?: string; enum?: EnumDetails; purpose?: Purpose; virtualProperties?: VirtualProperties; /** if this is a child of a polymorphic class, this will have the value of the descriminator. */ discriminatorValue?: string; suppressFormat?: boolean; typeDeclaration?: EnhancedTypeDeclaration; classImplementation?: ModelClass; interfaceImplementation?: ModelInterface; internalInterfaceImplementation?: ModelInterface; interfaceName?: string; internalInterfaceName?: string; fullInternalInterfaceName?: string; fullname?: string; } // export class Schema extends Extensions implements Schema { // public details: LanguageDetails<SchemaDetails>; // public required = new Array<string>(); // public enum = new Array<any>(); // public allOf = new Array<Schema>(); // public oneOf = new Array<Schema>(); // public anyOf = new Array<Schema>(); // public properties = new Dictionary<Property>(); // public extensions = new Dictionary<any>(); // constructor(name: string, initializer?: DeepPartial<Schema>) { // super(); // this.details = { // default: { // uid: `schema:${uid()}`, // description: '', // name // } // }; // this.apply(initializer); // } // } export function getPolymorphicBases(schema: ObjectSchema): Array<Schema> { // are any of my parents polymorphic directly, or any of their parents? return [...values(schema.parents?.all).where(parent => (<ObjectSchema>parent).discriminator ? true : false)]; } export function getAllProperties(schema: Schema): Array<Property> { if (isObjectSchema(schema)) { return [...values(schema.parents ? schema.parents.immediate : []).selectMany(getAllProperties), ...values(schema.properties)]; } else { return []; } } export function getAllPublicVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> { const props = virtualProperties || { owned: [], inherited: [], inlined: [] }; return values(props.owned, props.inherited, props.inlined).where(each => !each.private).toArray(); } export function getAllPublicVirtualPropertiesForSdk(virtualProperties?: VirtualProperties): Array<VirtualProperty> { const props = virtualProperties || { owned: [], inherited: [], inlined: [] }; // meanwhile we need to skip discriminator return values(props.inherited, props.owned, props.inlined).where(each => !each.private && !each.property.isDiscriminator).toArray(); } export function getAllPublicVirtualPropertiesForSdkWithoutInherited(virtualProperties?: VirtualProperties): Array<VirtualProperty> { const props = virtualProperties || { owned: [], inherited: [], inlined: [] }; return values(props.owned, props.inlined).where(each => !each.private && !each.property.isDiscriminator).toArray(); } export function getAllVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> { const props = virtualProperties || { owned: [], inherited: [], inlined: [] }; return values(props.owned, props.inherited, props.inlined).toArray(); } export function getVirtualPropertyFromPropertyName(virtualProperties: VirtualProperties | undefined, propertyName: string): VirtualProperty | undefined { const props = virtualProperties || { owned: [], inherited: [], inlined: [] }; return values([...values(props.owned), ...values(props.inherited), ...values(props.inlined)]).first(each => each.property.serializedName === propertyName); } // export interface Property extends Extensions { // details: LanguageDetails<PropertyDetails>; // /** description can be on the property reference, so that properties can have a description different from the type description. */ // description?: string; // schema: Schema; // } // export class Property extends Extensions implements Property { // public serializedName: string; // public details: LanguageDetails<PropertyDetails>; // public extensions = new Dictionary<any>(); // constructor(name: string, initializer?: DeepPartial<Property>) { // super(); // this.serializedName = name; // this.details = { // default: { // readOnly: false, // uid: `property:${uid()}`, // description: initializer?.description || '', // name, // required: false // } // }; // this.apply(initializer); // } // } export class Discriminator extends Extensions implements Discriminator { public extensions = new Dictionary<any>(); public mapping = new Dictionary<string>(); constructor(public propertyName: string, initializer?: DeepPartial<Discriminator>) { super(); this.apply(initializer); } } export interface Discriminator extends Extensions { propertyName: string; mapping: Dictionary<string>; } export enum JsonType { Array = 'array', Boolean = 'boolean', Integer = 'integer', Number = 'number', Object = 'object', String = 'string' } export function isJsonType(type: JsonType, schema?: Schema): schema is Schema { return schema ? schema.type === SchemaType.Object : false; } export function isSchemaObject(schema?: Schema): schema is Schema { return isJsonType(JsonType.Object, schema); } export class XML extends Extensions implements XML { public extensions = new Dictionary<any>(); public attribute = false; public wrapped = false; constructor(initializer?: DeepPartial<XML>) { super(); this.apply(initializer); } } export interface XML extends Extensions { name?: string; namespace?: string; // url prefix?: string; attribute: boolean; wrapped: boolean; } // export interface Schema extends Extensions { // details: LanguageDetails<SchemaDetails>; // /* common properties */ // type?: JsonType; // title?: string; // description?: string; // format?: string; // nullable: boolean; // readOnly: boolean; // writeOnly: boolean; // deprecated: boolean; // required: Array<string>; // /* number restrictions */ // multipleOf?: number; // maximum?: number; // exclusiveMaximum?: boolean; // minimum?: number; // exclusiveMinimum?: boolean; // /* string restrictions */ // maxLength?: number; // minLength?: number; // pattern?: string; // regex // /* array restrictions */ // maxItems?: number; // minItems?: number; // uniqueItems?: boolean; // /* object restrictions */ // maxProperties?: number; // minProperties?: number; // /* unbounded properties */ // example?: any; // default?: any; // /* Properties that are objects */ // discriminator?: Discriminator; // externalDocs?: ExternalDocumentation; // xml?: XML; // /* Properties that are collections of things that are not references */ // enum: Array<any>; // /* properties with potential references */ // not?: Schema; // allOf: Array<Schema>; // oneOf: Array<Schema>; // anyOf: Array<Schema>; // items?: Schema; // properties: Dictionary<Property>; // additionalProperties?: boolean | Schema; // } export function getMutability(property: Property): Mutability { const mutability = { create: true, update: true, read: true }; if (property.extensions && property.extensions['x-ms-mutability']) { const mt = <Array<string>>property.extensions['x-ms-mutability']; mutability.create = mt.includes('create') ? true : false; mutability.update = mt.includes('update') ? true : false; mutability.read = mt.includes('read') ? true : false; } return mutability; } // check whether it is value type export function valueType(type: string): boolean { if (['boolean', 'integer', 'number', 'unixtime', 'duration', 'uuid', 'date-time', 'date'].includes(type)) { return true; } return false; }