From b63b6d3870b1a76a272080471d61883955c33c9b Mon Sep 17 00:00:00 2001 From: derek Date: Wed, 8 Jul 2020 16:45:16 +0800 Subject: [PATCH 01/61] Support for simple API with modelerfour(defined in xkcd.ymal) --- powershell/autorest-configuration.md | 36 +- powershell/cmdlets/class.ts | 12 +- powershell/cmdlets/namespace.ts | 29 +- powershell/enums/namespace.ts | 111 ++- powershell/generators/csproj.ts | 3 +- powershell/generators/gitattributes.ts | 4 +- powershell/generators/gitignore.ts | 4 +- powershell/generators/nuspec.ts | 4 +- powershell/generators/psm1.custom.ts | 4 +- powershell/generators/psm1.internal.ts | 4 +- powershell/generators/psm1.ts | 5 +- powershell/generators/readme.ts | 4 +- powershell/generators/script-cmdlet.ts | 4 +- powershell/internal/project.ts | 195 ++++- powershell/internal/state.ts | 28 +- powershell/llcsharp/enums/namespace.ts | 4 +- powershell/llcsharp/generator.ts | 32 +- powershell/llcsharp/model/interface.ts | 157 +++- powershell/llcsharp/model/model-class-json.ts | 219 +++++- .../llcsharp/model/model-class-serializer.ts | 145 ++++ powershell/llcsharp/model/model-class.ts | 476 +++++++++++- powershell/llcsharp/model/namespace.ts | 160 +++- powershell/llcsharp/operation/api-class.ts | 80 +- powershell/llcsharp/operation/method.ts | 688 +++++++++++++++++- powershell/llcsharp/operation/namespace.ts | 6 +- powershell/llcsharp/operation/parameter.ts | 81 ++- powershell/llcsharp/project.ts | 83 ++- powershell/llcsharp/schema/array.ts | 77 +- .../schema/extended-type-declaration.ts | 3 +- powershell/llcsharp/schema/object.ts | 165 +++++ powershell/llcsharp/schema/schema-resolver.ts | 89 ++- powershell/llcsharp/schema/string.ts | 193 +++++ powershell/main.ts | 18 + powershell/models/model-extensions.ts | 237 +++++- powershell/module/module-class.ts | 252 ++++++- powershell/module/module-namespace.ts | 21 +- powershell/package.json | 2 + powershell/plugins/create-commands-v2.ts | 484 ++++++++++++ powershell/plugins/cs-namer-v2.ts | 257 +++++++ powershell/plugins/cs-namer.ts | 4 +- powershell/plugins/llcsharp-v2.ts | 78 ++ powershell/plugins/modifiers.ts | 2 + powershell/plugins/onbaordpipeline.md | 39 + .../plugin-create-inline-properties.ts | 399 ++++++++++ .../plugins/plugin-tweak-model-azure.ts | 175 +++++ powershell/plugins/plugin-tweak-model.ts | 356 +++++++++ powershell/plugins/powershell-v2.ts | 81 +++ powershell/plugins/powershell.ts | 3 +- powershell/plugins/ps-namer-v2.ts | 212 ++++++ powershell/plugins/ps-namer.ts | 6 +- powershell/utils/PwshModel.ts | 16 + powershell/utils/components.ts | 33 + powershell/utils/model-state.ts | 239 ++++++ samples/Xkcd/xkcd.yaml | 45 +- 54 files changed, 5883 insertions(+), 181 deletions(-) create mode 100644 powershell/plugins/create-commands-v2.ts create mode 100644 powershell/plugins/cs-namer-v2.ts create mode 100644 powershell/plugins/llcsharp-v2.ts create mode 100644 powershell/plugins/onbaordpipeline.md create mode 100644 powershell/plugins/plugin-create-inline-properties.ts create mode 100644 powershell/plugins/plugin-tweak-model-azure.ts create mode 100644 powershell/plugins/plugin-tweak-model.ts create mode 100644 powershell/plugins/powershell-v2.ts create mode 100644 powershell/plugins/ps-namer-v2.ts create mode 100644 powershell/utils/PwshModel.ts create mode 100644 powershell/utils/components.ts create mode 100644 powershell/utils/model-state.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 5b6f048abcc..7301da27f71 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -4,11 +4,18 @@ - Please don't edit this section unless you're re-configuring how the powershell extension plugs in to AutoRest AutoRest needs the below config to pick this up as a plug-in - see https://github.com/Azure/autorest/blob/master/docs/developer/architecture/AutoRest-extension.md +> modelerfour configuration +``` yaml +modelerfour: + emit-yaml-tags: false +``` + > if the modeler is loaded already, use that one, otherwise grab it. -``` yaml !isLoaded('@autorest/remodeler') +``` yaml use-extension: "@autorest/remodeler" : "~2.1.0" + "@autorest/modelerfour": "4.13.351" # will use highest 2.0.x ``` @@ -111,6 +118,27 @@ pipeline: tweakcodemodelazure: input: tweakcodemodel +# --- extension powershell based on modelerfour + tweakcodemodel-v2: + input: modelerfour/identity + + create-commands-v2: + input: tweakcodemodel-v2 + + create-virtual-properties-v2: + input: create-commands-v2 + + csnamer-v2: + input: create-virtual-properties-v2 + + psnamer-v2: + input: csnamer-v2 + + llcsharp-v2: + input: psnamer-v2 + + # powershell-v2: + # input: psnamer-v2 # --- extension powershell --- # creates high-level commands @@ -144,7 +172,7 @@ pipeline: input: modifiers llcsharp/text-transform: - input: llcsharp + input: llcsharp-v2 scope: scope-here powershell/text-transform: @@ -174,10 +202,10 @@ scope-here: # Specific Settings for cm emitting - selects the file types and format that cmv2-emitter will spit out. code-model-emitter-settings: - input-artifact: code-model-v3 + input-artifact: code-model-v4 is-object: true output-uri-expr: | - "code-model-v3" + "code-model-v4" # testing: ask for the files we need output-artifact: diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 7b08dff6287..6b7c132b8cb 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Schema as NewSchema } from '@azure-tools/codemodel'; import { command, getAllProperties, JsonType, http, getAllPublicVirtualProperties, getVirtualPropertyFromPropertyName, ParameterLocation, getAllVirtualProperties, VirtualParameter, VirtualProperty } from '@azure-tools/codemodel-v3'; import { escapeString, docComment, serialize, pascalCase, DeepPartial } from '@azure-tools/codegen'; import { items, values, Dictionary, length } from '@azure-tools/linq'; @@ -12,7 +13,7 @@ import { } from '@azure-tools/codegen-csharp'; import { ClientRuntime, EventListener, Schema, ArrayOf, EnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; -import { State } from '../internal/state'; +import { State, NewState } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; import { IParameter } from '@azure-tools/codemodel-v3/dist/code-model/components'; import { Variable, Local, ParameterModifier } from '@azure-tools/codegen-csharp'; @@ -1174,7 +1175,7 @@ export class CmdletClass extends Class { addDefaultInfo(cmdletParameter, vParam); } - const isEnum = propertyType.schema.details.csharp.enum !== undefined; + const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); @@ -1308,7 +1309,7 @@ export class CmdletClass extends Class { // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); } - const isEnum = propertyType.schema.details.csharp.enum !== undefined; + const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); @@ -1316,6 +1317,7 @@ export class CmdletClass extends Class { } const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); if (ifmatch) { + //no sure why there is an empty block } } @@ -1372,7 +1374,7 @@ export class CmdletClass extends Class { let type = ''; if (typeDeclaration instanceof ArrayOf) { type = typeDeclaration.elementTypeDeclaration; - } else if (pageableInfo && pageableInfo.responseType === 'pageable') { + } else if (!(typeDeclaration.schema instanceof NewSchema) && pageableInfo && pageableInfo.responseType === 'pageable') { if (typeDeclaration === undefined || typeDeclaration.schema.properties[pageableInfo.itemName] === undefined) { throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); } @@ -1421,4 +1423,4 @@ export class CmdletClass extends Class { this.add(new Attribute(ProfileAttribute, { parameters: [...profileNames] })); } } -} +} \ No newline at end of file diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index 52a2c80d80c..e5df54cd73b 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -5,7 +5,7 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime } from '../llcsharp/exports'; -import { State } from '../internal/state'; +import { State, NewState } from '../internal/state'; import { CmdletClass } from './class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -33,4 +33,31 @@ export class CmdletNamespace extends Namespace { } return this; } +} + +export class NewCmdletNamespace extends Namespace { + inputModels = new Array(); + public get outputFolder(): string { + return this.state.project.cmdletFolder; + } + + constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { + super('Cmdlets', parent); + this.apply(objectInitializer); + } + + async init() { + this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); + + // generate cmdlet classes on top of the SDK + for (const { key: index, value: operation } of items(this.state.model.commands.operations)) { + // skip ViaIdentity for set-* cmdlets. + if (this.state.project.azure && operation.details.csharp.verb === 'Set' && operation.details.csharp.name.indexOf('ViaIdentity') > 0) { + continue; + } + // skip-for-time-being + //this.addClass(await new CmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); + } + return this; + } } \ No newline at end of file diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index e6473ce05fd..a3b07985233 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -5,7 +5,7 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { EnumDetails } from '@azure-tools/codemodel-v3'; import { If, Parameter, Method, Namespace, System, Struct, Attribute, Class, dotnet, LambdaMethod, LiteralExpression, Modifier } from '@azure-tools/codegen-csharp'; -import { State } from '../internal/state'; +import { State, NewState } from '../internal/state'; import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, TypeConverterAttribute, PSTypeConverter } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -118,4 +118,113 @@ export class EnumNamespace extends Namespace { } } +} +export class NewEnumNamespace extends Namespace { + public get outputFolder(): string { + return join(this.state.project.apiFolder, 'Support'); + } + + constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { + super('Support', parent); + this.apply(objectInitializer); + // skip-for-time-being + // const enumInfos = values(state.model.schemas) + // .where(each => each.details.csharp.enum !== undefined && !each.details.csharp.skip) + // .select(each => ({ details: each.details.csharp.enum, description: each.details.csharp.description })) + // .toArray(); + + // const done = new Set(); + + + // for (const enumInfo of enumInfos) { + // if (done.has(enumInfo.details.name)) { + // continue; + // } + + // done.add(enumInfo.details.name); + + // if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) { + // continue; + // } + + // // generate a typeconverter for the enum class too. + + // const enumValues = values(enumInfo.details.values).select(v => v.value).toArray(); + // const enumClass = new Struct(this, enumInfo.details.name, undefined, { + // interfaces: [IArgumentCompleter], + // partial: true, + // description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`, + // fileName: `${enumInfo.details.name}.Completer` + // }); + // const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' }); + // const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' }); + // const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' }); + // const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' }); + // const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' }); + // const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters]; + + // enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () { + // for (const enumValue of enumValues) { + // yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`, + // `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`); + // } + // }); + + + // // generate a typeconverter for the enum class too. + + // const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, { + // interfaces: [PSTypeConverter], + // partial: true, + // description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`, + // fileName: `${enumInfo.details.name}.TypeConverter` + // }); + + // converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, { + // override: Modifier.Override, + // parameters: [ + // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + // new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + // ], + // description: 'Determines if the converter can convert the parameter to the parameter.', + // returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + // })); + + // converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { + // override: Modifier.Override, + // parameters: [ + // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + // new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + // ], + // description: 'Determines if the converter can convert the parameter to the parameter.', + // returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + // })); + + // converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), { + // override: Modifier.Override, + // parameters: [ + // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + // new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + // new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + // new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + // ], + // description: 'Converts the parameter to the parameter using and ', + // returnsDescription: `an instance of , or null if there is no suitable conversion.` + // })); + + // converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { + // override: Modifier.Override, + // parameters: [ + // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + // new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + // new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + // new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + // ], description: 'NotImplemented -- this will return null', + // returnsDescription: 'will always return null.' + // })); + + // enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + + // } + } } \ No newline at end of file diff --git a/powershell/generators/csproj.ts b/powershell/generators/csproj.ts index 9f19683dbff..0d14a60d7da 100644 --- a/powershell/generators/csproj.ts +++ b/powershell/generators/csproj.ts @@ -4,11 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Project } from '../internal/project'; +import { NewProject } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateCsproj(project: Project) { +export async function generateCsproj(project: Project | NewProject) { const release = project.azure ? ` true true MSSharedLibKey.snk diff --git a/powershell/generators/gitattributes.ts b/powershell/generators/gitattributes.ts index e3467fba6c4..764cdd68dd0 100644 --- a/powershell/generators/gitattributes.ts +++ b/powershell/generators/gitattributes.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; -export async function generateGitAttributes(project: Project) { +export async function generateGitAttributes(project: Project | NewProject) { project.state.writeFile(project.gitAttributes, '* text=auto', undefined, 'source-file-other'); } \ No newline at end of file diff --git a/powershell/generators/gitignore.ts b/powershell/generators/gitignore.ts index c25205e7509..7791a3c6e0b 100644 --- a/powershell/generators/gitignore.ts +++ b/powershell/generators/gitignore.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; -export async function generateGitIgnore(project: Project) { +export async function generateGitIgnore(project: Project | NewProject) { project.state.writeFile(project.gitIgnore, `bin obj .vs diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index 79d3f77ddf3..fb44a1df572 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateNuspec(project: Project) { +export async function generateNuspec(project: Project | NewProject) { const dependencies = project.azure ? ` diff --git a/powershell/generators/psm1.custom.ts b/powershell/generators/psm1.custom.ts index 7977240814d..61789f414ca 100644 --- a/powershell/generators/psm1.custom.ts +++ b/powershell/generators/psm1.custom.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; -export async function generatePsm1Custom(project: Project) { +export async function generatePsm1Custom(project: Project | NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Custom) || ''); const dllPath = relative(project.customFolder, project.dll); const internalPath = relative(project.customFolder, project.psm1Internal); diff --git a/powershell/generators/psm1.internal.ts b/powershell/generators/psm1.internal.ts index 76911b9c45a..d1e0a2e6127 100644 --- a/powershell/generators/psm1.internal.ts +++ b/powershell/generators/psm1.internal.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; import { getProfileExportScript } from './psm1'; -export async function generatePsm1Internal(project: Project) { +export async function generatePsm1Internal(project: Project | NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Internal) || ''); const dllPath = relative(project.internalFolder, project.dll); psm1.prepend('Generated', ` diff --git a/powershell/generators/psm1.ts b/powershell/generators/psm1.ts index 8a545e4e45e..78f1c22af67 100644 --- a/powershell/generators/psm1.ts +++ b/powershell/generators/psm1.ts @@ -3,10 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; + export function getProfileExportScript(exportFolderScript: string, isAzure: boolean): string { return ` # Export proxy cmdlet scripts @@ -39,7 +40,7 @@ export function getProfileExportScript(exportFolderScript: string, isAzure: bool `; } -export async function generatePsm1(project: Project) { +export async function generatePsm1(project: Project | NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1) || ''); let azureInitialize = ''; if (project.azure) { diff --git a/powershell/generators/readme.ts b/powershell/generators/readme.ts index b8563b454f6..384d87b1683 100644 --- a/powershell/generators/readme.ts +++ b/powershell/generators/readme.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; import { MdFile } from '../file-formats/md-file'; -export async function generateReadme(project: Project) { +export async function generateReadme(project: Project | NewProject) { const md = new MdFile(await project.state.readFile(project.readme) || ''); let azureInfo = ''; if (project.azure) { diff --git a/powershell/generators/script-cmdlet.ts b/powershell/generators/script-cmdlet.ts index b4794aacb06..ac1c25ee248 100644 --- a/powershell/generators/script-cmdlet.ts +++ b/powershell/generators/script-cmdlet.ts @@ -4,7 +4,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project } from '../internal/project'; +import { Project, NewProject } from '../internal/project'; import { serialize, indent, setIndentation, applyOverrides, pascalCase } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { State } from '../internal/state'; @@ -52,7 +52,7 @@ function getType(type: string) { return type; } -export async function generateScriptCmdlets(project: Project) { +export async function generateScriptCmdlets(project: Project | NewProject) { const commands = await project.state.getValue>('command', []); for (const command of values(commands)) { if (!command.action) { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index ba382c2274a..8c1e799ec8d 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,17 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, Boolean } from '../llcsharp/exports'; -import { State } from './state'; +import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, Boolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; +import { State, NewState } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { EnumNamespace } from '../enums/namespace'; -import { ModelExtensionsNamespace } from '../models/model-extensions'; +import { EnumNamespace, NewEnumNamespace } from '../enums/namespace'; +import { ModelExtensionsNamespace, NewModelExtensionsNamespace } from '../models/model-extensions'; -import { ModuleNamespace } from '../module/module-namespace'; -import { CmdletNamespace } from '../cmdlets/namespace'; +import { ModuleNamespace, NewModuleNamespace } from '../module/module-namespace'; +import { CmdletNamespace, NewCmdletNamespace } from '../cmdlets/namespace'; import { Host } from '@azure-tools/autorest-extension-base'; import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -56,6 +59,26 @@ export class PSSchemaResolver extends SchemaDefinitionResolver { } } +export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { + inResolve = false; + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): EnhancedTypeDeclaration { + const before = this.inResolve; + try { + // skip-for-time-being + // if (!this.inResolve) { + // this.inResolve = true; + // if (schema && schema.type === JsonType.Boolean) { + // return new PSSwitch(schema, required); + // } + // } + + return super.resolveTypeDeclaration(schema, required, state); + } finally { + this.inResolve = before; + } + } +} + export class Project extends codeDomProject { public azure!: boolean; public license!: string; @@ -208,6 +231,166 @@ export class Project extends codeDomProject { this.addNamespace(this.cmdlets); + // abort now if we have any errors. + this.state.checkpoint(); + return this; + } +} + +export class NewProject extends codeDomProject { + public azure!: boolean; + public license!: string; + public cmdletFolder!: string; + + public customFolder!: string; + public internalFolder!: string; + public testFolder!: string; + public runtimeFolder!: string; + public binFolder!: string; + public objFolder!: string; + public exportsFolder!: string; + public docsFolder!: string; + public examplesFolder!: string; + public resourcesFolder!: string; + public serviceName!: string; + public moduleName!: string; + public csproj!: string; + public nuspec!: string; + public gitIgnore!: string; + public gitAttributes!: string; + public readme!: string; + public dllName!: string; + public dll!: string; + public psd1!: string; + public psm1!: string; + public psm1Custom!: string; + public psm1Internal!: string; + public formatPs1xml!: string; + public apiFolder!: string; + public baseFolder!: string; + public moduleFolder!: string; + public schemaDefinitionResolver!: NewSchemaDefinitionResolver; + public moduleVersion!: string; + public profiles!: Array; + + public prefix!: string; + public subjectPrefix!: string; + public projectNamespace!: string; + public overrides!: Dictionary; + public serviceNamespace!: NewModuleNamespace; + public supportNamespace!: NewEnumNamespace; + public cmdlets!: NewCmdletNamespace; + + public modelsExtensions!: NewModelExtensionsNamespace; + public accountsVersionMinimum!: string; + public dependencyModuleFolder!: string; + public metadata!: Metadata; + public state!: NewState; + public helpLinkPrefix!: string; + get model() { return this.state.model; } + + constructor(protected service: Host, objectInitializer?: DeepPartial) { + super(); + this.apply(objectInitializer); + } + + + public async init(): Promise { + await super.init(); + this.state = await new NewState(this.service).init(this); + + this.schemaDefinitionResolver = new NewPSSchemaResolver(); + + this.projectNamespace = this.state.model.language.csharp?.namespace || ''; + + + this.overrides = { + 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, + 'using Data;': '', + 'using Parser;': '', + 'using Converters;': '', + 'using Internal.Extensions;': '', + + 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, + 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, + 'Microsoft.Rest': `${this.projectNamespace}`, + }; + + // Values + this.moduleVersion = await this.state.getValue('module-version'); + // skip-for-time-being + //this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || []; + this.profiles = []; + this.accountsVersionMinimum = '1.7.4'; + this.helpLinkPrefix = await this.state.getValue('help-link-prefix'); + this.metadata = await this.state.getValue('metadata'); + this.license = await this.state.getValue('header-text', ''); + + // Flags + this.azure = this.model.language.default.isAzure; + + // Names + this.prefix = this.model.language.default.prefix; + this.serviceName = this.model.language.default.serviceName; + this.subjectPrefix = this.model.language.default.subjectPrefix; + this.moduleName = await this.state.getValue('module-name'); + this.dllName = await this.state.getValue('dll-name'); + + // Folders + this.baseFolder = await this.state.getValue('current-folder'); + this.moduleFolder = await this.state.getValue('module-folder'); + this.cmdletFolder = await this.state.getValue('cmdlet-folder'); + + this.customFolder = await this.state.getValue('custom-cmdlet-folder'); + this.internalFolder = await this.state.getValue('internal-cmdlet-folder'); + this.testFolder = await this.state.getValue('test-folder'); + this.runtimeFolder = await this.state.getValue('runtime-folder'); + this.apiFolder = await this.state.getValue('api-folder'); + + this.binFolder = await this.state.getValue('bin-folder'); + this.objFolder = await this.state.getValue('obj-folder'); + this.exportsFolder = await this.state.getValue('exports-folder'); + this.docsFolder = await this.state.getValue('docs-folder'); + this.dependencyModuleFolder = await this.state.getValue('dependency-module-folder'); + this.examplesFolder = await this.state.getValue('examples-folder'); + this.resourcesFolder = await this.state.getValue('resources-folder'); + + // File paths + this.csproj = await this.state.getValue('csproj'); + this.dll = await this.state.getValue('dll'); + this.psd1 = await this.state.getValue('psd1'); + this.psm1 = await this.state.getValue('psm1'); + this.psm1Custom = await this.state.getValue('psm1-custom'); + this.psm1Internal = await this.state.getValue('psm1-internal'); + this.formatPs1xml = await this.state.getValue('format-ps1xml'); + this.nuspec = await this.state.getValue('nuspec'); + this.gitIgnore = `${this.baseFolder}/.gitignore`; + this.gitAttributes = `${this.baseFolder}/.gitattributes`; + this.readme = `${this.baseFolder}/readme.md`; + + // add project namespace + this.serviceNamespace = new NewModuleNamespace(this.state); + this.serviceNamespace.header = this.license; + this.addNamespace(this.serviceNamespace); + + //this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); + //this.supportNamespace.header = this.license; + //this.addNamespace(this.supportNamespace); + + this.modelsExtensions = new NewModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); + this.modelsExtensions.header = this.license; + this.addNamespace(this.modelsExtensions); + + // add cmdlet namespace + this.cmdlets = await new NewCmdletNamespace(this.serviceNamespace, this.state).init(); + this.cmdlets.header = this.license; + this.addNamespace(this.cmdlets); + + // abort now if we have any errors. this.state.checkpoint(); return this; diff --git a/powershell/internal/state.ts b/powershell/internal/state.ts index 37c70ab3b45..197c344362f 100644 --- a/powershell/internal/state.ts +++ b/powershell/internal/state.ts @@ -5,9 +5,11 @@ import { codemodel, ModelState } from '@azure-tools/codemodel-v3'; -import { Host, JsonPath } from '@azure-tools/autorest-extension-base'; -import { Project } from './project'; +import { Host, JsonPath, Session } from '@azure-tools/autorest-extension-base'; +import { Project, NewProject } from './project'; import { DeepPartial } from '@azure-tools/codegen'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; export interface GeneratorSettings { @@ -45,3 +47,25 @@ export class State extends ModelState { } } +export class NewState extends NewModelState { + project!: NewProject; + + public constructor(service: Host, objectInitializer?: DeepPartial) { + super(service); + this.apply(objectInitializer); + } + + async init(project?: NewProject) { + if (project) { + this.project = project; + } + return await super.init(project); + } + + path(...childPath: JsonPath) { + // const result = new State(this.service, this); + // result.currentPath = [...this.currentPath, ...childPath]; + //return result; + return this; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/enums/namespace.ts b/powershell/llcsharp/enums/namespace.ts index 90e9a014d64..e8a9ec52d42 100644 --- a/powershell/llcsharp/enums/namespace.ts +++ b/powershell/llcsharp/enums/namespace.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Namespace } from '@azure-tools/codegen-csharp'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class SupportNamespace extends Namespace { - constructor(parent: Namespace, private state: State, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: State | NewState, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/generator.ts b/powershell/llcsharp/generator.ts index 5f16695b6e8..644e9409f45 100644 --- a/powershell/llcsharp/generator.ts +++ b/powershell/llcsharp/generator.ts @@ -4,12 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { ModelState } from '@azure-tools/codemodel-v3'; +import { codeModelSchema } from '@azure-tools/codemodel'; import { Model } from './code-model'; -import { Host, JsonPath } from '@azure-tools/autorest-extension-base'; +import { Host, JsonPath, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { Project } from './project'; +import { Project, NewProject } from './project'; import { Dictionary } from '@azure-tools/linq'; import { DeepPartial } from '@azure-tools/codegen'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; export class State extends ModelState { project!: Project; @@ -33,3 +36,28 @@ export class State extends ModelState { return this; } } + +export class NewState extends NewModelState { + project!: NewProject; + + public constructor(service: Host, objectInitializer?: DeepPartial) { + super(service); + this.apply(objectInitializer); + } + + async init(project?: NewProject) { + if (project) { + this.project = project; + } + //const session = await startSession(this.service, {}, codeModelSchema); + return await super.init(project); + //return await super.init(project); + } + + path(...childPath: JsonPath) { + // const result = new State(this.service, this); + // result.currentPath = [...this.currentPath, ...childPath]; + //return result; + return this; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index eba0be9d479..15d40c5f1fe 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -8,9 +8,10 @@ import { KnownMediaType, JsonType, getPolymorphicBases } from '@azure-tools/code import { Expression, ExpressionOrLiteral, Interface, Namespace, OneOrMoreStatements, Variable, Access, InterfaceProperty, Attribute, StringExpression, LiteralExpression, Property, TypeDeclaration } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { State } from '../generator'; +import { Schema as NewSchema, Language } from '@azure-tools/codemodel'; +import { State, NewState } from '../generator'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ModelClass } from './model-class'; +import { ModelClass, NewModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; @@ -222,3 +223,155 @@ export class ModelInterface extends Interface implements EnhancedTypeDeclaration } } +export class NewModelInterface extends Interface implements EnhancedTypeDeclaration { + get schema(): NewSchema { + return this.classImplementation.schema; + } + + get defaultOfType() { + return this.classImplementation.defaultOfType; + } + + get convertObjectMethod() { + return this.classImplementation.convertObjectMethod; + } + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + return this.classImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); + } + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + return this.classImplementation.deserializeFromNode(mediaType, node, defaultValue); + } + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.classImplementation.deserializeFromString(mediaType, content, defaultValue); + } + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.classImplementation.deserializeFromResponse(mediaType, content, defaultValue); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return this.classImplementation.serializeToContent(mediaType, value, mode); + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + return this.classImplementation.serializeToNode(mediaType, value, serializedName, mode); + } + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.classImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); + } + + get isXmlAttribute(): boolean { + return this.classImplementation.isXmlAttribute; + } + + public isNullable = true; + + get isRequired(): boolean { + return this.classImplementation.isRequired; + } + + public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.classImplementation.validatePresence(eventListener, property); + } + public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.classImplementation.validateValue(eventListener, property); + } + + get hasHeaderProperties(): boolean { + // disabled + // return this.classImplementation.hasHeaderProperties; + return false; + } + constructor(parent: TypeContainer, interfaceName: string, public classImplementation: NewModelClass, public state: NewState, objectInitializer?: DeepPartial) { + super(parent, interfaceName); + this.partial = true; + this.apply(objectInitializer); + } + + get isInternal(): boolean { + return this.accessModifier === Access.Internal; + } + + init() { + (this).init = () => { }; // only allow a single init! + this.schema.language.csharp = this.schema.language.csharp || new Language(); + const implData = (this.schema.language.csharp = this.schema.language.csharp || {}); + //implData.interfaceImplementation = this; + this.description = `${this.schema.language.csharp.description}`; + + const virtualProperties = this.schema.language.csharp.virtualProperties || { + owned: [], + inherited: [], + inlined: [] + }; + // skip-for-time-being + // if (this.schema.language.csharp.virtualProperties) { + + // for (const virtualProperty of values(virtualProperties.owned)) { + // if (virtualProperty.private && !this.isInternal) { + // continue; + // } + + // const modelProperty = virtualProperty.property; + + // const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); + + // const isRequired = !!modelProperty.details.csharp.required; + // const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); + // const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { + // description: modelProperty.details.csharp.description, + // setAccess: internalSet ? Access.Internal : Access.Public + // })); + + // this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); + + // if (!this.isInternal && modelProperty.details.csharp.constantValue !== undefined) { + // p.setAccess = Access.Internal; + // } + // } + + // for (const virtualProperty of values(virtualProperties.inlined)) { + + // // don't publicly expose the 'private' properties. + // if (virtualProperty.private && !this.isInternal) { + // continue; + // } + + // const modelProperty = virtualProperty.property; + // const isRequired = !!modelProperty.details.csharp.required; + // const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); + + // const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); + + // const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { + // description: modelProperty.details.csharp.description, + // setAccess: internalSet ? Access.Internal : Access.Public + // })); + // this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); + + // } + // } + + if (!this.isInternal) { + // mark it as json serializable + if (!this.schema.language.csharp.isHeaderModel) { + if (this.state.project.jsonSerialization) { + this.interfaces.push(ClientRuntime.IJsonSerializable); + } + if (this.state.project.xmlSerialization) { + this.interfaces.push(ClientRuntime.IXmlSerializable); + } + } + } + return this; + } + + addInfoAttribute(p: Property, pType: TypeDeclaration, isRequired: boolean, internalSet: boolean, description: string, serializedName: string) { + if (!this.isInternal) { + return addInfoAttribute(p, pType, isRequired, internalSet, description, serializedName); + } + } +} diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 0751b79eb5c..2e238ddeae5 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -2,7 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Schema as NewSchema, ObjectSchema } from '@azure-tools/codemodel'; import { KnownMediaType, HeaderProperty, HeaderPropertyType, getAllProperties } from '@azure-tools/codemodel-v3'; +import { getAllProperties as newGetAllProperties } from '@azure-tools/codemodel'; import { EOL, DeepPartial, } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Access, Modifier, StringExpression, Expression, System } from '@azure-tools/codegen-csharp'; @@ -22,7 +24,7 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { ModelClass } from './model-class'; +import { ModelClass, NewModelClass } from './model-class'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; @@ -96,7 +98,8 @@ export class JsonSerializableClass extends Class { for (const each of values(modelClass.backingFields)) { serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - if ((each.typeDeclaration).schema.additionalProperties) { + const sch = (each.typeDeclaration).schema; + if (!(sch instanceof NewSchema) && (sch.additionalProperties)) { deserializeStatements.add(`${each.field.value} = new ${each.className}(json${this.excludes});`); } else { deserializeStatements.add(`${each.field.value} = new ${each.className}(json);`); @@ -239,3 +242,215 @@ export class JsonSerializableClass extends Class { })); } } + +export class NewJsonSerializableClass extends Class { + private btj!: Method; + private atj!: Method; + private bfj!: Method; + private afj!: Method; + private excludes: string; + + constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { + super(modelClass.namespace, modelClass.name); + this.apply(objectInitializer); + this.partial = true; + this.description = modelClass.description; + this.addPartialMethods(); + + // set up the declaration for the toJson method. + const container = new Parameter('container', ClientRuntime.JsonObject, { description: `The container to serialize this object into. If the caller passes in null, a new instance will be created and returned to the caller.` }); + const mode = new Parameter('serializationMode', ClientRuntime.SerializationMode, { description: `Allows the caller to choose the depth of the serialization. See .` }); + + const toJsonMethod = this.addMethod(new Method('ToJson', ClientRuntime.JsonNode, { + parameters: [container, mode], + description: `Serializes this instance of into a .`, + returnsDescription: `a serialized instance of as a .` + })); + + // setup the declaration for the json deserializer constructor + const jsonParameter = new Parameter('json', ClientRuntime.JsonObject, { description: `A ${ClientRuntime.JsonObject} instance to deserialize from.` }); + const deserializerConstructor = this.addMethod(new Constructor(this, { + parameters: [jsonParameter], access: Access.Internal, + description: `Deserializes a ${ClientRuntime.JsonObject} into a new instance of .` + })); + + + const serializeStatements = new Statements(); + const deserializeStatements = new Statements(); + this.excludes = ''; + + if (this.modelClass.dictionaryImpl) { + const vType = this.modelClass.dictionaryImpl.valueType; + // we have to ensure that all the known wire-names are excluded on deserialization. + const exclusions = new Parameter('exclusions', System.Collections.Generic.HashSet(dotnet.String), { defaultInitializer: dotnet.Null }); + deserializerConstructor.parameters.push(exclusions); + + this.excludes = [...values(newGetAllProperties(this.modelClass.schema)).select(each => each.serializedName).select(each => new StringExpression(each))].join(); + this.excludes = this.excludes ? `,${System.Collections.Generic.HashSet(dotnet.String).new()}{ ${this.excludes} }` : ''; + + const ap = `((${ClientRuntime}.IAssociativeArray<${vType.declaration}>)this).AdditionalProperties`; + + if (this.modelClass.dictionaryImpl.ownsDictionary) { + // we have to implement the deserializer for it. + + serializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.ToJson( ${ap}, ${container});`)); + + if (vType === System.Object) { + // wildcard style + deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); + + } else if (vType instanceof ObjectImplementation) { + deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${this.modelClass.fullName}.FromJson(j) ,${exclusions.value} );`)); + } else { + deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, null ,${exclusions.value} );`)); + } + } + } + + + for (const each of values(modelClass.backingFields)) { + serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); + const sch = (each.typeDeclaration).schema; + if (!(sch instanceof NewSchema) && (sch.additionalProperties)) { + deserializeStatements.add(`${each.field.value} = new ${each.className}(json${this.excludes});`); + } else { + deserializeStatements.add(`${each.field.value} = new ${each.className}(json);`); + } + } + + pushTempVar(); + for (const prop of values(modelClass.ownedProperties)) { + if (prop.details.csharp.HeaderProperty === 'Header') { + continue; + } + const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Json, prop.valuePrivate, container, prop.serializedName, mode); + + if (prop.details.csharp.readOnly) { + serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); + } else { + serializeStatements.add(serializeStatement); + } + deserializeStatements.add(prop.assignPrivate((prop.type).deserializeFromContainerMember(KnownMediaType.Json, jsonParameter, prop.serializedName, prop))); + } + popTempVar(); + + const $this = this; + + // generate the implementation for toJson + toJsonMethod.add(function* () { + yield `${container} = ${container} ?? new ${ClientRuntime.JsonObject.declaration}();`; + yield EOL; + + yield 'bool returnNow = false;'; + yield `${$this.btj.name}(ref ${container}, ref returnNow);`; + + yield If(toExpression('returnNow'), `return ${container};`); + + // get serialization statements + yield serializeStatements; + + yield `${$this.atj.name}(ref ${container});`; + yield Return(container); + }); + + // and let's fill in the deserializer constructor statements now. + deserializerConstructor.add(function* () { + yield 'bool returnNow = false;'; + yield `${$this.bfj.name}(json, ref returnNow);`; + yield If(toExpression('returnNow'), 'return;'); + + yield deserializeStatements; + yield `${$this.afj.name}(json);`; + }); + } + + public get definition(): string { + const $this = this.modelClass; + // gotta write this just before we write out the class, since we had to wait until everyone had reported to their parents. + const d = this.modelClass.discriminators; + const isp = this.modelClass.isPolymorphic; + // create the FromJson method + const node = new Parameter('node', ClientRuntime.JsonNode, { description: `a to deserialize from.` }); + const fromJson = this.addMethod(new Method('FromJson', this.modelClass.modelInterface, { + parameters: [node], static: Modifier.Static, + description: `Deserializes a into an instance of ${this.modelClass.modelInterface}.`, + returnsDescription: `an instance of ${this.modelClass.modelInterface}.` + })); + + if (isp) { + fromJson.description = fromJson.description + `\n Note: the ${this.modelClass.modelInterface} interface is polymorphic, and the precise model class that will get deserialized is determined at runtime based on the payload.`; + } + const $excludes = this.excludes; + fromJson.add(function* () { + + const json = IsDeclaration(node, ClientRuntime.JsonObject, 'json'); + + if (isp) { + yield If(Not(json.check), Return(dotnet.Null)); + yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; + /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ + // skip-for-time-being + // if ($this.schema.discriminator) { + // yield Switch(toExpression(`json.StringProperty("${$this.schema.discriminator.propertyName}")`), function* () { + // for (const { key, value } of items(d)) { + // yield TerminalCase(`"${key}"`, function* () { + // yield Return(value.new(json)); + // }); + // } + // }); + // } + yield Return($this.new(json, toExpression($excludes.substring(1)))); + } else { + // just tell it to create the instance (providing that it's a JSonObject) + yield Return(Ternery(json.check, $this.new(json), dotnet.Null)); + } + }); + + return super.definition; + } + + public get fileName(): string { + return `${super.fileName}.json`; + } + + protected addPartialMethods() { + // add partial methods for future customization + this.btj = this.addMethod(new PartialMethod('BeforeToJson', dotnet.Void, { + access: Access.Default, + parameters: [ + new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), + new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }), + ], + description: `BeforeToJson will be called before the json serialization has commenced, allowing complete customization of the object before it is serialized. + If you wish to disable the default serialization entirely, return true in the output parameter. + Implement this method in a partial class to enable this behavior.` + })); + + this.atj = this.addMethod(new PartialMethod('AfterToJson', dotnet.Void, { + access: Access.Default, + parameters: [ + new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), + ], + description: `AfterToJson will be called after the json erialization has finished, allowing customization of the before it is returned. Implement this method in a partial class to enable this behavior ` + })); + + this.bfj = this.addMethod(new PartialMethod('BeforeFromJson', dotnet.Void, { + access: Access.Default, + parameters: [ + new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), + new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the deserialization should be processed, or if the method should return instantly.' }), + ], + description: `BeforeFromJson will be called before the json deserialization has commenced, allowing complete customization of the object before it is deserialized. + If you wish to disable the default deserialization entirely, return true in the output parameter. + Implement this method in a partial class to enable this behavior.` + })); + + this.afj = this.addMethod(new PartialMethod('AfterFromJson', dotnet.Void, { + access: Access.Default, + parameters: [ + new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), + ], + description: 'AfterFromJson will be called after the json deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ' + })); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index f11323f523e..eb2ac30e105 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -30,6 +30,7 @@ import { popTempVar, pushTempVar } from '../schema/primitive'; import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; import { getVirtualPropertyName } from './model-class'; @@ -70,6 +71,42 @@ export class SerializationPartialClass extends Initializer { } +export class NewSerializationPartialClass extends Initializer { + constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + super(); + this.apply(objectInitializer); + } + + protected get virtualProperties() { + return this.schema.language.csharp?.virtualProperties || { + owned: [], + inherited: [], + inlined: [] + }; + } + protected get allVirtualProperties() { + const vp = this.virtualProperties; + // return [...vp.owned, ...vp.inherited, ...vp.inlined]; + return values(vp.owned, vp.inherited, vp.inlined).toArray(); + } + + protected contentParameter = new Parameter('content', this.serializationType, { description: `The ${this.serializationType.declaration} content that should be used.` }); + protected refContainerParameter = new Parameter('container', this.serializationType, { modifier: ParameterModifier.Ref, description: `The ${this.serializationType.declaration} container that the serialization result will be placed in.` }); + protected returnNowParameter = new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }); + + protected get typeCref() { + return ``; + } + + protected get thisCref() { + return ``; + } + + protected get interfaceCref() { + return ``; + } + +} export class DeserializerPartialClass extends SerializationPartialClass { private beforeDeserialize!: Method; private afterDeserialize!: Method; @@ -176,6 +213,113 @@ export class DeserializerPartialClass extends SerializationPartialClass { } } +export class NewDeserializerPartialClass extends NewSerializationPartialClass { + private beforeDeserialize!: Method; + private afterDeserialize!: Method; + constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); + this.apply(objectInitializer); + } + + async init() { + // add partial methods for extensibility + this.addPartialMethods(); + this.addDeserializerConstructor(); + this.addDeserializerMethod(); + } + + protected addDeserializerConstructor() { + const $this = this; + + const deserializerConstructor = this.targetClass.addMethod(new Constructor(this.targetClass, { + parameters: [this.contentParameter], access: Access.Internal, + description: `Deserializes a ${this.typeCref} into a new instance of ${this.thisCref}.` + })); + + deserializerConstructor.add(function* () { + const returnNow = new LocalVariable('returnNow', dotnet.Bool, { initializer: dotnet.False }); + yield returnNow.declarationStatement; + + yield `${$this.beforeDeserialize.name}(${$this.contentParameter}, ref ${returnNow.value});`; + yield If(returnNow, 'return;'); + yield $this.deserializeStatements; + // skip-for-time-being + // if ($this.hasAadditionalProperties($this.schema)) { + // // this type has an additional properties dictionary + // yield '// this type is a dictionary; copy elements from source to here.'; + // yield `CopyFrom(${$this.contentParameter.value});`; + // } + + yield `${$this.afterDeserialize.name}(${$this.contentParameter});`; + }); + } + + private hasAadditionalProperties(aSchema: Schema): boolean { + if (aSchema.additionalProperties) { + return true; + } else + for (const each of values(aSchema.allOf)) { + const r = this.hasAadditionalProperties(each); + if (r) { + return r; + } + } + return false; + } + + get deserializeStatements() { + const $this = this; + + return function* () { + yield '// actually deserialize '; + // skip-for-time-being + // for (const virtualProperty of values($this.allVirtualProperties)) { + // // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; + // const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.details.default.required); + + // const cvt = type.convertObjectMethod; + // const t = `((${virtualProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; + // const tt = type ? `(${type.declaration})` : ''; + + // yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; + // } + }; + } + + protected addDeserializerMethod() { + const $this = this; + + const deserialzeMethod = this.targetClass.addMethod(new Method(`DeserializeFrom${this.serializationFormat}`, this.targetInterface, { + parameters: [this.contentParameter], static: Modifier.Static, + description: `Deserializes a ${this.typeCref} into an instance of ${this.thisCref}.`, + returnsDescription: `an instance of ${this.interfaceCref}.` + })); + + deserialzeMethod.add(function* () { + yield Return($this.targetClass.new($this.contentParameter)); + }); + + } + + protected addPartialMethods() { + const before = `BeforeDeserialize${this.serializationFormat}`; + const after = `AfterDeserialize${this.serializationFormat}`; + this.beforeDeserialize = this.targetClass.addMethod(new PartialMethod(before, dotnet.Void, { + access: Access.Default, + parameters: [this.contentParameter, this.returnNowParameter], + description: `${before} will be called before the deserialization has commenced, allowing complete customization of the object before it is deserialized. + If you wish to disable the default deserialization entirely, return true in the output parameter. + Implement this method in a partial class to enable this behavior.` + })); + + this.afterDeserialize = this.targetClass.addMethod(new PartialMethod(after, dotnet.Void, { + access: Access.Default, + parameters: [this.contentParameter], + description: `${after} will be called after the deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ` + })); + } +} + export class SerializerPartialClass extends SerializationPartialClass { private beforeSerialize!: Method; private afterSerialize!: Method; @@ -218,3 +362,4 @@ export class SerializerPartialClass extends SerializationPartialClass { })); } } + diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 949bded3e5e..7c01b6196a6 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -8,15 +8,16 @@ import { camelCase, deconstruct, DeepPartial } from '@azure-tools/codegen'; import { items, values } from '@azure-tools/linq'; import { Access, Class, Constructor, Expression, ExpressionOrLiteral, Field, If, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Statements, System, TypeDeclaration, valueOf, Variable, BackedProperty, Property, Virtual, toExpression, StringExpression, LiteralExpression, Attribute } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation } from '../schema/object'; -import { ModelInterface } from './interface'; -import { JsonSerializableClass } from './model-class-json'; +import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; +import { ModelInterface, NewModelInterface } from './interface'; +import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-json'; import { ModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; import { DictionaryImplementation } from './model-class-dictionary'; +import { Languages, Language } from '@azure-tools/codemodel'; export function getVirtualPropertyName(vp?: VirtualProperty): string { @@ -482,6 +483,473 @@ export class ModelClass extends Class implements EnhancedTypeDeclaration { return this.featureImplementation.validatePresence(eventListener, property); } + public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { + this.discriminators.set(discriminatorValue, modelClass); + + // tell any polymorphic parents incase we're doing subclass of a subclass. + for (const each of this.parentModelClasses) { + each.addDiscriminator(discriminatorValue, modelClass); + } + } +} + +export class NewModelClass extends Class implements EnhancedTypeDeclaration { + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); + } + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + return this.featureImplementation.deserializeFromNode(mediaType, node, defaultValue); + } + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + return this.featureImplementation.serializeToNode(mediaType, value, serializedName, mode); + } + + get defaultOfType() { + return toExpression('null /* model class */'); + } + + get convertObjectMethod() { + return this.featureImplementation.convertObjectMethod; + } + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return this.featureImplementation.serializeToContent(mediaType, value, mode); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.featureImplementation.deserializeFromString(mediaType, content, defaultValue); + } + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.featureImplementation.deserializeFromResponse(mediaType, content, defaultValue); + } + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.featureImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); + } + + get isXmlAttribute(): boolean { + return this.featureImplementation.isXmlAttribute; + } + + public isNullable = true; + + get isRequired(): boolean { + return this.featureImplementation.isRequired; + } + + public isPolymorphic = false; + public get schema() { return this.featureImplementation.schema; } + + /* @internal */ validateMethod?: Method; + /* @internal */ discriminators: Map = new Map(); + /* @internal */ parentModelClasses: Array = new Array(); + /* @internal */ get modelInterface(): ModelInterface { return this.schema.language.csharp?.interfaceImplementation; } + /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } + + /* @internal */ state: NewState; + /* @internal */ backingFields = new Array(); + /* @internal */ featureImplementation: NewObjectImplementation; + /* @internal */ validationEventListener: Parameter = new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive validation events.` }); + /* @internal */ jsonSerializer?: NewJsonSerializableClass; + // /* @internal */ xmlSerializer?: XmlSerializableClass; + /* @internal */ dictionaryImpl?: DictionaryImplementation; + + private readonly validationStatements = new Statements(); + public ownedProperties = new Array(); + private pMap = new Map(); + + // public hasHeaderProperties: boolean; + + constructor(namespace: Namespace, schemaWithFeatures: NewObjectImplementation, state: NewState, objectInitializer?: DeepPartial) { + super(namespace, schemaWithFeatures.schema.language.csharp?.name || ''); + this.featureImplementation = schemaWithFeatures; + this.schema.language.csharp = this.schema.language.csharp || new Language(); + this.schema.language.csharp.classImplementation = this; // mark the code-model with the class we're creating. + this.state = state; + this.apply(objectInitializer); + + if (this.state.getValue('powershell') && this.schema.language.csharp.suppressFormat) { + this.add(new Attribute(DoNotFormatAttribute)); + } + + // must be a partial class + this.partial = true; + + //skip-for-time-being + //this.handleDiscriminator(); + + // create an interface for this model class + if (!this.schema.language.csharp.interfaceImplementation) { + (this.schema.language.csharp.interfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.interfaceName || `I${this.schema.language.csharp.name}`, this, this.state)); + + } + this.interfaces.push(this.modelInterface); + + if (!this.schema.language.csharp.internalInterfaceImplementation) { + (this.schema.language.csharp.internalInterfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.internalInterfaceName || `I${this.schema.language.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); + + } + + this.interfaces.push(this.internalModelInterface); + + this.schema.language.csharp.internalInterfaceImplementation.init(); + this.schema.language.csharp.interfaceImplementation.init(); + + // add default constructor + this.addMethod(new Constructor(this, { description: `Creates an new instance.` })); // default constructor for fits and giggles. + + // skip-for-time-being + // handle parent interface implementation + // if (!this.handleAllOf()) { + // // handle the AdditionalProperties if used + // if (this.schema.additionalProperties) { + // this.dictionaryImpl = new DictionaryImplementation(this).init(); + // } + // } + + // create the properties for ths schema + this.createProperties(); + + // add validation implementation + this.addValidation(); + + // add header properties for this model. + // DISABLED. + this.addHeaderDeserializer(); + + if (this.state.project.jsonSerialization) { + this.jsonSerializer = new NewJsonSerializableClass(this); + } + } + + private nested(virtualProperty: VirtualProperty, internal: boolean): string { + if (virtualProperty.accessViaProperty) { + if (virtualProperty.accessViaProperty.accessViaProperty) { + // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; + } + } + //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + } + + private accessor(virtualProperty: VirtualProperty, internal = false): string { + if (virtualProperty.accessViaProperty) { + const prefix = virtualProperty.accessViaProperty.accessViaProperty ? this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal) : ''; + const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); + if (containingProperty && virtualProperty.accessViaMember) { + //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + } + } + // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; + } + + private createProperties() { + // generate a protected backing field for each + // and then expand the nested properties into this class forwarding to the member. + + // add properties + if (this.schema.language.csharp?.virtualProperties) { + const addFormatAttributesToProperty = (property: Property, virtualProperty: VirtualProperty) => { + if (virtualProperty.format) { + if (virtualProperty.format.suppressFormat) { + property.add(new Attribute(DoNotFormatAttribute)); + } else { + const parameters = []; + if (virtualProperty.format.index !== undefined) { + parameters.push(`Index = ${virtualProperty.format.index}`); + } + + if (virtualProperty.format.label !== undefined) { + parameters.push(`Label = ${new StringExpression(virtualProperty.format.label)}`); + } + + if (virtualProperty.format.width !== undefined) { + parameters.push(`Width = ${virtualProperty.format.width}`); + } + + property.add(new Attribute(FormatTableAttribute, { parameters })); + } + } + }; + // skip-for-time-being + // /* Owned Properties */ + // for (const virtualProperty of values(this.schema.language.csharp.virtualProperties.owned)) { + // const actualProperty = virtualProperty.property; + // let n = 0; + // const decl = this.state.project.modelsNamespace.resolveTypeDeclaration(actualProperty.schema, actualProperty.details.csharp.required, this.state.path('schema')); + + // /* public property */ + // const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.details.csharp.required, actualProperty.serializedName, actualProperty.details.csharp.description, this.state.path('properties', n++), { + // initializer: actualProperty.details.csharp.constantValue ? typeof actualProperty.details.csharp.constantValue === 'string' ? new StringExpression(actualProperty.details.csharp.constantValue) : new LiteralExpression(actualProperty.details.csharp.constantValue) : undefined + // }); + + // if (actualProperty.details.csharp.readOnly) { + // myProperty.set = undefined; + // } + // myProperty.details = virtualProperty.property.details; + + // if (actualProperty.details.csharp.constantValue !== undefined) { + // myProperty.setAccess = Access.Internal; + // myProperty.set = undefined; + // } + + // if (virtualProperty.private) { + // // when properties are inlined, the container accessor can be internalized. I think. + // myProperty.setAccess = Access.Internal; + // myProperty.getAccess = Access.Internal; + // this.pMap.set(virtualProperty, myProperty); + // } + + // this.ownedProperties.push(this.add(myProperty)); + + // if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined) { + // /* internal interface property */ + + // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, { + // description: `Internal Acessors for ${virtualProperty.name}`, + // getAccess: Access.Explicit, + // setAccess: Access.Explicit, + // get: myProperty.get, + // set: myProperty.assignPrivate('value') + // })); + // } + + // if (this.state.getValue('powershell')) { + // myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] })); + // addFormatAttributesToProperty(myProperty, virtualProperty); + // } + // } + + // /* Inherited properties. */ + // for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inherited)) { + // // so each parent property that is getting exposed + // // has to be accessed via the field in this.backingFields + // const parentField = this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.details.csharp.interfaceImplementation.fullName === each.typeDeclaration.declaration : false); + + // const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); + // const opsType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.originalContainingSchema, false, this.state); + // const via = virtualProperty.accessViaProperty; + // const parentCast = `(${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName})`; + // const vp = this.add(new Property(virtualProperty.name, propertyType, { + // description: virtualProperty.property.details.csharp.description, + // get: toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`), + // set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value`) + // })); + + // if (virtualProperty.property.details.csharp.constantValue !== undefined) { + // vp.setAccess = Access.Internal; + // vp.set = undefined; + // } + + // if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { + + // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { + // description: `Internal Acessors for ${virtualProperty.name}`, + // getAccess: Access.Explicit, + // setAccess: Access.Explicit, + // get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`), + // set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`) + // })); + // } + + // if (this.state.getValue('powershell')) { + // vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] })); + // addFormatAttributesToProperty(vp, virtualProperty); + // } + // } + + // /* Inlined properties. */ + // for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inlined)) { + // if (virtualProperty.private) { + // // continue; + // // can't remove it, it has to be either public or internally implemented. + // } + + // if (virtualProperty.accessViaProperty) { + // const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); + // if (containingProperty) { + + // const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); + + // // regular inlined property + // const vp = new Property(virtualProperty.name, propertyType, { + // description: virtualProperty.property.details.csharp.description, + // get: toExpression(`${this.accessor(virtualProperty)}`), + // set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value`) + // }); + + // if (!virtualProperty.private) { + // this.add(vp); + // } + + // if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { + // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { + // description: `Internal Acessors for ${virtualProperty.name}`, + // getAccess: Access.Explicit, + // setAccess: Access.Explicit, + // get: vp.get, + // set: toExpression(`${this.accessor(virtualProperty)} = value`) + // })); + // } + + // if (virtualProperty.property.details.csharp.constantValue !== undefined) { + // vp.setAccess = Access.Internal; + // vp.set = undefined; + // } + + // if (this.state.getValue('powershell')) { + // vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] })); + // addFormatAttributesToProperty(vp, virtualProperty); + // } + // } + // } + // } + + } + } + + private addValidation() { + if (this.validationStatements.implementation.trim()) { + // we do have something to valdiate! + + // add the IValidates implementation to this object. + this.interfaces.push(ClientRuntime.IValidates); + this.validateMethod = this.addMethod(new Method('Validate', System.Threading.Tasks.Task(), { + async: Modifier.Async, + parameters: [this.validationEventListener], + description: 'Validates that this object meets the validation criteria.', + returnsDescription: `A < see cref = "${System.Threading.Tasks.Task()}" /> that will be complete when validation is completed.` + })); + this.validateMethod.add(this.validationStatements); + } + } + + private additionalPropertiesType(aSchema: Schema): TypeDeclaration | undefined { + // skip-for-time-being + // if (aSchema.additionalProperties) { + + // if (aSchema.additionalProperties === true) { + // return System.Object; + + // } else { + // // we're going to implement IDictionary + // return this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema.additionalProperties, true, this.state); + // } + // } else + // for (const each of values(aSchema.allOf)) { + // const r = this.additionalPropertiesType(each); + // if (r) { + // return r; + // } + // } + return undefined; + } + + // skip-for-time-being + // private handleAllOf() { + // let hasAdditionalPropertiesInParent = false; + // // handle s + // // add an 'implements' for the interface for the allOf. + // for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.allOf)) { + // const aSchema = eachSchemaValue; + // const aState = this.state.path('allOf', eachSchemaIndex); + + // const td = this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema, true, aState); + // const parentClass = (aSchema.details.csharp.classImplementation); + // const className = parentClass.fullName; + // const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); + + // // add the interface as a parent to our interface. + // const iface = aSchema.details.csharp.interfaceImplementation; + + // // add a field for the inherited values + // const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); + // this.backingFields.push({ + // className, + // typeDeclaration: td, + // field: backingField + // }); + // this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); + // this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); + + // this.internalModelInterface.interfaces.push(aSchema.details.csharp.internalInterfaceImplementation); + // this.modelInterface.interfaces.push(iface); + + // // + // const addlPropType = this.additionalPropertiesType(aSchema); + // if (addlPropType) { + // this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); + // hasAdditionalPropertiesInParent = true; + // } + // } + // return hasAdditionalPropertiesInParent; + // } + + // private handleDiscriminator() { + // if (this.schema.discriminator) { + // // this has a discriminator property. + // // our children are expected to tell us who they are + // this.isPolymorphic = true; + // // we'll add a deserializer factory method a bit later.. + // } + + // if (this.schema.details.csharp.discriminatorValue) { + // // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. + // // um. just how do we *really* know which allOf is polymorphic? + // // that's really sad. + // for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.allOf)) { + // const parentSchema = eachAllOfValue; + // const aState = this.state.path('allOf', eachAllOfIndex); + + // // ensure the parent schema has it's class created first. + // this.state.project.modelsNamespace.resolveTypeDeclaration(parentSchema, true, aState); + + // const parentClass = parentSchema.details.csharp.classImplementation; + // if (parentClass.isPolymorphic) { + // // remember this class for later. + // this.parentModelClasses.push(parentClass); + + // // tell that parent who we are. + // parentClass.addDiscriminator(this.schema.details.csharp.discriminatorValue, this); + // } + // } + // } + // } + private addHeaderDeserializer() { + const avp = getAllVirtualProperties(this.schema.language.csharp?.virtualProperties); + const headers = new Parameter('headers', System.Net.Http.Headers.HttpResponseHeaders); + const readHeaders = new Method(`${ClientRuntime.IHeaderSerializable}.ReadHeaders`, undefined, { + access: Access.Explicit, + parameters: [headers], + }); + + const used = false; + + // skip-for-time-being + // for (const headerProperty of values(avp).where(each => each.property.details.csharp[HeaderProperty] === HeaderPropertyType.HeaderAndBody || each.property.details.csharp[HeaderProperty] === HeaderPropertyType.Header)) { + // used = true; + // const t = `((${headerProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; + // const values = `__${camelCase([...deconstruct(headerProperty.property.serializedName), 'Header'])}`; + // const td = this.state.project.modelsNamespace.resolveTypeDeclaration(headerProperty.property.schema, false, this.state.path('schema')); + // readHeaders.add(If(`${valueOf(headers)}.TryGetValues("${headerProperty.property.serializedName}", out var ${values})`, `${t}.${headerProperty.name} = ${td.deserializeFromContainerMember(KnownMediaType.Header, headers, values, td.defaultOfType)};`)); + // } + if (used) { + this.interfaces.push(ClientRuntime.IHeaderSerializable); + this.add(readHeaders); + } + } + + public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.featureImplementation.validateValue(eventListener, property); + } + public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.featureImplementation.validatePresence(eventListener, property); + } + public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { this.discriminators.set(discriminatorValue, modelClass); diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 2d23f84beb5..583cd624e20 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -3,19 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Schema as NewSchema, Schemas as NewSchemas, Language } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { EnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation } from '../schema/object'; -import { SchemaDefinitionResolver } from '../schema/schema-resolver'; +import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; +import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../schema/schema-resolver'; import { EnumClass } from '../enums/enum'; import * as validation from '../validations'; import { ModelInterface } from './interface'; -import { ModelClass } from './model-class'; +import { ModelClass, NewModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -35,8 +36,8 @@ export class ModelsNamespace extends Namespace { private subNamespaces = new Dictionary(); resolver = new SchemaDefinitionResolver(); - - constructor(parent: Namespace, private schemas: Dictionary, private state: State, objectInitializer?: DeepPartial) { + newResolver = new NewSchemaDefinitionResolver(); + constructor(parent: Namespace, private schemas: Dictionary | NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { super('Models', parent); this.subNamespaces[this.fullName] = this; @@ -46,15 +47,28 @@ export class ModelsNamespace extends Namespace { // special case... hook this up before we get anywhere. state.project.modelsNamespace = this; + if (!(schemas instanceof NewSchemas)) { + for (const { key: index, value: schema } of items(schemas)) { + const state = this.state.path(index); - for (const { key: index, value: schema } of items(schemas)) { - const state = this.state.path(index); - - // verify that the model isn't in a bad state - if (validation.objectWithFormat(schema, state)) { - continue; + // verify that the model isn't in a bad state + if (validation.objectWithFormat(schema, state)) { + continue; + } + this.resolveTypeDeclaration(schema, true, state); } - this.resolveTypeDeclaration(schema, true, state); + } else { + if (schemas.objects) { + for (const schema of schemas.objects) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } + if (schemas.strings) { + for (const schema of schemas.strings) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } + //todo, need to add support for other types } } @@ -78,7 +92,7 @@ export class ModelsNamespace extends Namespace { const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - const mc = schema.details.csharp.classImplementation || new ModelClass(ns, td, this.state, { description: schema.details.csharp.description }); + const mc = schema.details.csharp.classImplementation || new ModelClass(ns, td, this.state, { description: schema.details.csharp.description }); // this gets implicity created during class creation: return schema.details.csharp.interfaceImplementation; @@ -102,4 +116,122 @@ export class ModelsNamespace extends Namespace { } return td; } + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): EnhancedTypeDeclaration { + if (!schema) { + throw new Error('SCHEMA MISSING?'); + } + + const td = this.newResolver.resolveTypeDeclaration(schema, required, state); + + if (!schema.language.csharp?.skip) { + if (td instanceof NewObjectImplementation) { + // it's a class object. + // create it if necessary + + const fullname = schema.language.csharp?.namespace || this.fullName; + + const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); + + const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); + + // this gets implicity created during class creation: + return schema.language.csharp?.interfaceImplementation; + } + + if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { + return td; + } + + if (td instanceof EnumImplementation) { + if (schema.language.csharp?.enum) { + const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); + if (length(ec) === 0) { + // skip-for-time-being + //new EnumClass(td, state); + // return schema.details.csharp.typeDeclaration = ec[0]; + } + } + schema.language.csharp = schema.language.csharp || new Language(); + return schema.language.csharp.typeDeclaration = td; + } + } + return td; + } } + +export class NewModelsNamespace extends Namespace { + private subNamespaces = new Dictionary(); + + resolver = new SchemaDefinitionResolver(); + newResolver = new NewSchemaDefinitionResolver(); + constructor(parent: Namespace, private schemas: NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { + super('Models', parent); + this.subNamespaces[this.fullName] = this; + + + this.apply(objectInitializer); + this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); + + // special case... hook this up before we get anywhere. + state.project.modelsNamespace = this; + + if (schemas.objects) { + for (const schema of schemas.objects) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } + if (schemas.strings) { + for (const schema of schemas.strings) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } + //todo, need to add support for other types + + } + + get outputFolder() { + return 'Models'; + } + + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): EnhancedTypeDeclaration { + if (!schema) { + throw new Error('SCHEMA MISSING?'); + } + + const td = this.newResolver.resolveTypeDeclaration(schema, required, state); + + if (!schema.language.csharp?.skip) { + if (td instanceof NewObjectImplementation) { + // it's a class object. + // create it if necessary + + const fullname = schema.language.csharp?.namespace || this.fullName; + + const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); + + const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); + + // this gets implicity created during class creation: + return schema.language.csharp?.interfaceImplementation; + } + + if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { + return td; + } + + if (td instanceof EnumImplementation) { + if (schema.language.csharp?.enum) { + const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); + if (length(ec) === 0) { + // skip-for-time-being + //new EnumClass(td, state); + // return schema.details.csharp.typeDeclaration = ec[0]; + } + } + schema.language.csharp = schema.language.csharp || new Language(); + return schema.language.csharp.typeDeclaration = td; + } + } + return td; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/operation/api-class.ts b/powershell/llcsharp/operation/api-class.ts index d52af8c87fb..f3045b86c00 100644 --- a/powershell/llcsharp/operation/api-class.ts +++ b/powershell/llcsharp/operation/api-class.ts @@ -6,48 +6,76 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Class, Namespace } from '@azure-tools/codegen-csharp'; -import { State } from '../generator'; -import { CallMethod, OperationMethod, ValidationMethod } from '../operation/method'; +import { State, NewState } from '../generator'; +import { CallMethod, OperationMethod, NewOperationMethod, ValidationMethod, NewCallMethod, NewValidationMethod } from '../operation/method'; import { ParameterLocation } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; export class ApiClass extends Class { // protected sender: Property; - constructor(namespace: Namespace, protected state: State, objectInitializer?: DeepPartial) { - super(namespace, state.model.details.csharp.name); + constructor(namespace: Namespace, protected state: State | NewState, objectInitializer?: DeepPartial) { + super(namespace, (state instanceof NewState) ? state.model.language.csharp?.name || '' : state.model.details.csharp.name); this.apply(objectInitializer); // add basics // this.sender = this.add(new Property("Sender", ClientRuntime.ISendAsync)); // add operations from code model - for (const { key: operationIndex, value: operation } of items(state.model.http.operations)) { - // an operation has parameters for parameters, body, callbacks, listener and sender - // we need to make sure that the parameters for a given operation are consistent between the operation method, the call method, and the validation method. - // can we generate the common parameters here and just give them to the methods? (ie, can we share the instances between the methods?) - // code-dom doesn't store references from the child to the parent, so as long as the definitions work without modification, it looks like we can. - - // we'll do that work in the OM and expose them as public properties. - const operationMethod = new OperationMethod(this, operation, false, state.path('components', 'operations', operationIndex)); - this.addMethod(operationMethod); - if ([...values(operation.parameters).select(each => each.in === ParameterLocation.Path)].length > 0) { - // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new OperationMethod(this, operation, true, state.path('components', 'operations', operationIndex)); - identityMethod.emitCall(false); - this.addMethod(identityMethod); + if (!(state instanceof NewState)) { + for (const { key: operationIndex, value: operation } of items(state.model.http.operations)) { + // an operation has parameters for parameters, body, callbacks, listener and sender + // we need to make sure that the parameters for a given operation are consistent between the operation method, the call method, and the validation method. + // can we generate the common parameters here and just give them to the methods? (ie, can we share the instances between the methods?) + // code-dom doesn't store references from the child to the parent, so as long as the definitions work without modification, it looks like we can. - } + // we'll do that work in the OM and expose them as public properties. + const operationMethod = new OperationMethod(this, operation, false, state.path('components', 'operations', operationIndex)); + this.addMethod(operationMethod); + if ([...values(operation.parameters).select(each => each.in === ParameterLocation.Path)].length > 0) { + // method has parameters in the path, so it could support '...ViaIdentity' + const identityMethod = new OperationMethod(this, operation, true, state.path('components', 'operations', operationIndex)); + identityMethod.emitCall(false); + this.addMethod(identityMethod); + + } + + // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) + const cm = new CallMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + if (!this.hasMethodWithSameDeclaration(cm)) { + this.addMethod(cm); + } - // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new CallMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); - if (!this.hasMethodWithSameDeclaration(cm)) { - this.addMethod(cm); + const vm = new ValidationMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + if (!this.hasMethodWithSameDeclaration(vm)) { + this.addMethod(vm); + } } + } else { + // todo + for (const operationGroup of state.model.operationGroups) { + for (const operation of operationGroup.operations) { + const operationMethod = new NewOperationMethod(this, operation, false, state); + this.addMethod(operationMethod); + if ([...values(operation.parameters).where(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { + // method has parameters in the path, so it could support '...ViaIdentity' + const identityMethod = new NewOperationMethod(this, operation, true, state); + identityMethod.emitCall(false); + this.addMethod(identityMethod); + + } + + // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) + const cm = new NewCallMethod(this, operationMethod, state); + if (!this.hasMethodWithSameDeclaration(cm)) { + this.addMethod(cm); + } - const vm = new ValidationMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); - if (!this.hasMethodWithSameDeclaration(vm)) { - this.addMethod(vm); + const vm = new NewValidationMethod(this, operationMethod, state); + if (!this.hasMethodWithSameDeclaration(vm)) { + this.addMethod(vm); + } + } } } } diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index f3356f8fb06..2684e51e14b 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { NewResponse, ParameterLocation } from '@azure-tools/codemodel-v3'; +import { Operation, SchemaResponse, Schema as NewSchema, Response } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { EOL, DeepPartial } from '@azure-tools/codegen'; import { Access, Modifier } from '@azure-tools/codegen-csharp'; @@ -23,8 +24,8 @@ import { Using } from '@azure-tools/codegen-csharp'; import { Local, LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { HttpOperation, Schema } from '../code-model'; -import { State } from '../generator'; -import { CallbackParameter, OperationBodyParameter, OperationParameter } from '../operation/parameter'; +import { State, NewState } from '../generator'; +import { CallbackParameter, NewCallbackParameter, OperationBodyParameter, OperationParameter, NewOperationParameter } from '../operation/parameter'; import { isMediaTypeJson, isMediaTypeXml, KnownMediaType, knownMediaType, normalizeMediaType, parseMediaType } from '@azure-tools/codemodel-v3'; import { ClassType, dotnet, System } from '@azure-tools/codegen-csharp'; @@ -224,7 +225,7 @@ export class OperationMethod extends Method { ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` + ${removeEncoding(pp, pp.param.name, KnownMediaType.QueryParameter)}`, ` + "&"` -)} + )} ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) }); yield urlV.declarationStatement; @@ -284,6 +285,236 @@ export class OperationMethod extends Method { } } +export class NewOperationMethod extends Method { + public methodParameters: Array; + public bodyParameter?: OperationBodyParameter; + public contextParameter!: Parameter; + public senderParameter!: Parameter; + public resourceUri!: Parameter; + public callbacks = new Array(); + + protected callName: string; + + constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: NewState, objectInitializer?: DeepPartial) { + super(viaIdentity ? `${operation.language.csharp?.name}ViaIdentity` : operation.language.csharp?.name || '', System.Threading.Tasks.Task()); + this.apply(objectInitializer); + this.async = Modifier.Async; + this.returnsDescription = `A that will be complete when handling of the response is completed.`; + const $this = this; + + this.callName = `${operation.language.csharp?.name}_Call`; + this.push(Using('NoSynchronizationContext', '')); + + // add parameters + this.methodParameters = []; + + const identity = new Parameter('viaIdentity', System.String); + if (this.viaIdentity) { + this.addParameter(identity); + } + let baseUrl = ''; + for (let index = 0; index < length(this.operation.parameters) && this.operation.parameters; index++) { + const value = this.operation.parameters[index]; + + if (value.language.default.name === '$host') { + baseUrl = value.clientDefaultValue; + continue; + } + const p = new NewOperationParameter(this, value, this.state.path('parameters', index)); + + if (value.language.csharp?.constantValue) { + const constTd = state.project.modelsNamespace.NewResolveTypeDeclaration(value.schema, true, state); + p.defaultInitializer = constTd.deserializeFromString(KnownMediaType.UriParameter, new StringExpression(`${value.language.csharp.constantValue}`), toExpression(constTd.defaultOfType)); + } + + // don't add path parameters when we're in identity mode + if (!this.viaIdentity || value.protocol.http?.in !== ParameterLocation.Path) { + this.addParameter(p); + } else { + this.add(function* () { + yield ''; + }); + } + this.methodParameters.push(p); + } + + this.description = this.operation.language.csharp?.description || ''; + + // add body paramter if there should be one. + // skip-for-time-being + // if (this.operation.requestBody) { + // // this request does have a request body. + // this.bodyParameter = new OperationBodyParameter(this, 'body', this.operation.requestBody.description || '', this.operation.requestBody.schema, this.operation.requestBody.required, this.state.path('requestBody'), { + // mediaType: knownMediaType(this.operation.requestBody.contentType), + // contentType: this.operation.requestBody.contentType + // }); + // this.addParameter(this.bodyParameter); + // } + + for (const response of values(this.operation.responses)) { + + const responseType = (response).schema ? state.project.modelsNamespace.NewResolveTypeDeclaration(((response).schema), true, state) : null; + //skip-for-time-being + //const headerType = response.headerSchema ? state.project.modelsNamespace.NewResolveTypeDeclaration(response.headerSchema, true, state) : null; + const headerType = null; + const newCallbackParameter = new NewCallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); + this.addParameter(newCallbackParameter); + this.callbacks.push(newCallbackParameter); + + + } + + // add eventhandler parameter + this.contextParameter = this.addParameter(new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive events.` })); + + // add optional parameter for sender + this.senderParameter = this.addParameter(new Parameter('sender', ClientRuntime.ISendAsync, { description: `an instance of an ${ClientRuntime.ISendAsync} pipeline to use to make the request.` })); + + let rx = this.operation.requests ? this.operation.requests[0].protocol.http?.path : ''; + // For post API, Some URI may contain an action string .e.x '/start' at the end + // of the URI, for such cases, we will drop the action string if identityCorrection + // is set in the configuration + // skip-for-time-being + // if (this.operation.method === 'post' && this.state.project.identityCorrection) { + // const idx = rx.lastIndexOf('/'); + // rx = rx.substr(0, idx); + // } + + + let url = `${baseUrl}/${rx.startsWith('/') ? rx.substr(1) : rx}`; + + + const serverParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Uri); + + const headerParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Header); + const pathParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Path); + const queryParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Query); + const cookieParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Cookie); + + // replace any server params in the uri + // skip-for-time-being + // for (const pp of serverParams) { + // url = url.replace(`{${pp.param.name}}`, `" + // + ${pp.name} + // + "`); + // } + + // for (const pp of pathParams) { + // rx = rx.replace(`{${pp.param.name}}`, `(?<${pp.param.name}>[^/]+)`); + + // if (this.viaIdentity) { + // url = url.replace(`{${pp.param.name}}`, `" + // + ${pp.name} + // + "`); + // } else { + // url = url.replace(`{${pp.param.name}}`, `" + // + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} + // + "`); + // } + // } + rx = `"^${rx}$"`; + url = url.replace(/\s*\+ ""/gm, ''); + + const bp = this.bodyParameter; + // add method implementation... + + this.add(function* () { + const eventListener = new EventListener($this.contextParameter, $this.state.project.emitSignals); + + yield EOL; + + if ($this.viaIdentity) { + yield '// verify that Identity format is an exact match for uri'; + yield EOL; + + const match = Local('_match', `${System.Text.RegularExpressions.Regex.new(rx).value}.Match(${identity.value})`); + yield match.declarationStatement; + yield If(`!${match}.Success`, `throw new global::System.Exception("Invalid identity for URI '${rx}'");`); + yield EOL; + yield '// replace URI parameters with values from identity'; + // skip-for-time-being + // for (const pp of pathParams) { + // yield `var ${pp.name} = ${match.value}.Groups["${pp.param.name}"].Value;`; + // } + } + + yield '// construct URL'; + // const urlV = new LocalVariable('_url', dotnet.Var, { + // initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( + // "${url}" + // ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` + // + ${removeEncoding(pp, pp.param.name, KnownMediaType.QueryParameter)}`, ` + // + "&"` + // )} + // ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) + // }); + const urlV = new LocalVariable('_url', dotnet.Var, { + initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( + "${url}" + ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` + + ${''}`, ` + + "&"` + )} + ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) + }); + yield urlV.declarationStatement; + + yield EOL; + + yield eventListener.signal(ClientRuntime.Events.URLCreated, urlV.value); + yield EOL; + + yield '// generate request object '; + const method = $this.operation.requests ? $this.operation.requests[0].protocol.http?.method : ''; + yield `var request = ${System.Net.Http.HttpRequestMessage.new(`${ClientRuntime.fullName}.Method.${method.capitalize()}, ${urlV.value}`)};`; + yield eventListener.signal(ClientRuntime.Events.RequestCreated, urlV.value); + yield EOL; + + // skip-for-time-being + // if (length(headerParams) > 0) { + // yield '// add headers parameters'; + // for (const hp of headerParams) { + // if (hp.param.name === 'Content-Length') { + // // content length is set when the request body is set + // continue; + // } + // yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.name, ClientRuntime.SerializationMode.None); + // } + // yield EOL; + // } + yield eventListener.signal(ClientRuntime.Events.HeaderParametersAdded, urlV.value); + + if (bp) { + yield '// set body content'; + yield `request.Content = ${bp.serializeToContent(bp.mediaType, ClientRuntime.SerializationMode.None)};`; + yield `request.Content.Headers.ContentType = ${System.Net.Http.Headers.MediaTypeHeaderValue.Parse(bp.contentType)};`; + yield eventListener.signal(ClientRuntime.Events.BodyContentSet, urlV.value); + } + + yield '// make the call '; + }); + } + + emitCall(returnFromCall: boolean) { + + // storage will return from the call for download, etc. + if (returnFromCall) { + this.returnType = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); + } + + this.add(`await this.${this.callName}(request,${this.callbacks.joinWith(each => each.use, ',')},${this.contextParameter.use},${this.senderParameter.use});`); + + // remove constant parameters and make them locals instead. + this.insert('// Constant Parameters'); + for (let i = length(this.parameters); i--; i < 0) { + const p = this.parameters[i]; + if (p && p.defaultInitializer) { + this.parameters.splice(i, 1); + this.insert(new LocalVariable(p.name, dotnet.Var, { initializer: p.defaultInitializer })); + } + } + } +} export class CallMethod extends Method { public returnNull = false; constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { @@ -425,12 +656,12 @@ export class CallMethod extends Method { yield EOL; yield '// while we wait, let\'s grab the headers and get ready to poll. '; - yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {' + yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {'; yield ' ' + asyncOperation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield '}' - yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {' + yield '}'; + yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {'; yield ' ' + location.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield '}' + yield '}'; const uriLocal = Local('_uri', Ternery( System.String.IsNullOrEmpty(asyncOperation), Ternery(System.String.IsNullOrEmpty(location), @@ -618,11 +849,410 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { + public responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); } } +export class NewCallMethod extends Method { + public returnNull = false; + constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); + this.description = `Actual wire call for method.`; + this.returnsDescription = opMethod.returnsDescription; + + this.apply(objectInitializer); + this.access = Access.Internal; + this.async = Modifier.Async; + this.push(Using('NoSynchronizationContext', '')); + + const $this = this; + // add parameters + // request, listener, sender + const reqParameter = this.addParameter(new Parameter('request', System.Net.Http.HttpRequestMessage, { description: 'the prepared HttpRequestMessage to send.' })); + opMethod.callbacks.forEach(each => this.addParameter(each)); + + this.addParameter(opMethod.contextParameter); + this.addParameter(opMethod.senderParameter); + + // add statements to this method + this.add(function* () { + const eventListener = new EventListener(opMethod.contextParameter, $this.state.project.emitSignals); + + const response = Local('_response', dotnet.Null, System.Net.Http.HttpResponseMessage); + yield response; + yield Try(function* () { + + const responder = function* () { + // TODO: omit generating _contentType var if it will never be used + // const contentType = new LocalVariable('_contentType', dotnet.Var, { initializer: `_response.Content.Headers.ContentType?.MediaType` }); + const contentType = Local('_contentType', `${response}.Content.Headers.ContentType?.MediaType`); + + yield contentType; + + // add response handlers + yield Switch(`${response}.StatusCode`, function* () { + for (const responses of values(opMethod.operation.responses)) { + if (responses.protocol.http?.statusCodes[0] !== 'default') { + const responseCode = responses.protocol.http?.statusCodes[0]; + // will use enum when it can, fall back to casting int when it can't + yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); + } else { + yield DefaultCase($this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); + } + } + + // missing default response? + if (!opMethod.operation.exceptions) { + // if no default, we need one that handles the rest of the stuff. + yield TerminalDefaultCase(function* () { + yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`; + }); + } + }); + }; + + // try statements + yield eventListener.signal(ClientRuntime.Events.BeforeCall, reqParameter.use); + yield `${response.value} = await ${opMethod.senderParameter.value}.SendAsync(${reqParameter.use}, ${opMethod.contextParameter.value});`; + + yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value); + const EOL = 'EOL'; + // LRO processing (if appropriate) + if ($this.opMethod.operation.language.csharp?.lro) { + yield '// this operation supports x-ms-long-running-operation'; + const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`)); + yield originalUri; + + yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`; + const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via']; + let finalUri: LocalVariable; + + switch (fsv) { + case 'original-uri': + // perform a final GET on the original URI. + finalUri = originalUri; + break; + + case 'location': + // perform a final GET on the uri in Location header + finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield finalUri; + break; + // skip-for-time-being + // case 'azure-asyncoperation': + // case 'azure-async-operation': + // // depending on the type of request, do the appropriate behavior + // switch ($this.opMethod.operation.method.toLowerCase()) { + // case 'post': + // case 'delete': + // finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); + // yield finalUri; + // break; + // case 'patch': + // case 'put': + // // perform a final GET on the original URI. + // finalUri = originalUri; + // break; + // } + // break; + + default: + // depending on the type of request, fall back to the appropriate behavior + if ($this.opMethod.operation.requests) { + switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) { + case 'post': + case 'delete': + finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield finalUri; + break; + case 'patch': + case 'put': + // perform a final GET on the original URI. + finalUri = originalUri; + break; + } + } + break; + + } + + const asyncOperation = Local('asyncOperation', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); + yield asyncOperation; + const location = Local('location', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield location; + + yield While(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), function* () { + yield EOL; + yield '// get the delay before polling. (default to 30 seconds if not present)'; + yield `int delay = (int)(${response.value}.Headers.RetryAfter?.Delta?.TotalSeconds ?? 30);`; + // yield If(`!int.TryParse( ${response.invokeMethod('GetFirstHeader', new StringExpression(`Retry-After`)).value}, out int delay)`, `delay = 30;`); + + yield eventListener.signal(ClientRuntime.Events.DelayBeforePolling, '$"Delaying {delay} seconds before polling."', response.value); + + yield EOL; + yield '// start the delay timer (we\'ll await later...)'; + const waiting = Local('waiting', new LiteralExpression(`${System.Threading.Tasks.Task()}.Delay(delay * 1000, ${$this.opMethod.contextParameter}.Token )`)); + yield waiting; + + yield EOL; + yield '// while we wait, let\'s grab the headers and get ready to poll. '; + yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {'; + yield ' ' + asyncOperation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); + yield '}'; + yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {'; + yield ' ' + location.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield '}'; + const uriLocal = Local('_uri', Ternery( + System.String.IsNullOrEmpty(asyncOperation), + Ternery(System.String.IsNullOrEmpty(location), + originalUri, + location), + asyncOperation)); + yield uriLocal; + + yield `${reqParameter.use} = ${reqParameter.use}.CloneAndDispose(${System.Uri.new(uriLocal)}, ${ClientRuntime.Method.Get});`; + + yield EOL; + yield '// and let\'s look at the current response body and see if we have some information we can give back to the listener'; + const content = Local('content', new LiteralExpression(`await ${response.value}.Content.ReadAsStringAsync()`)); + yield content; + + yield 'await waiting;'; + yield EOL; + yield '// check for cancellation'; + yield `if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; }`; + + yield eventListener.signal(ClientRuntime.Events.Polling, `$"Polling {${uriLocal}}."`, response.value); + + yield EOL; + yield '// drop the old response'; + yield `${response.value}?.Dispose();`; + + yield EOL; + yield '// make the polling call'; + yield `${response.value} = await ${opMethod.senderParameter}.SendAsync(${reqParameter.value}, ${opMethod.contextParameter});`; + + + yield EOL; + yield ` +// if we got back an OK, take a peek inside and see if it's done +if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) +{ + try { + if( ${ClientRuntime.JsonNode.Parse(toExpression(`await ${response.value}.Content.ReadAsStringAsync()`))} is ${ClientRuntime.JsonObject} json) + { + var state = json.Property("properties")?.PropertyT<${ClientRuntime.JsonString}>("provisioningState") ?? json.PropertyT<${ClientRuntime.JsonString}>("status"); + if( state is null ) + { + // the body doesn't contain any information that has the state of the LRO + // we're going to just get out, and let the consumer have the result + break; + } + await ${$this.opMethod.contextParameter}.Signal(${ClientRuntime.Events.Polling}, $"Polled {${uriLocal}} provisioning state {state}.", ${response.value}); if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; } + + switch( state?.ToString()?.ToLower() ) + { + case "succeeded": + case "failed": + case "canceled": + // we're done polling. + break; + + default: + // need to keep polling! + ${response.value}.StatusCode = ${System.Net.HttpStatusCode.Created}; + continue; + } + } + } catch { + // if we run into a problem peeking into the result, + // we really don't want to do anything special. + } +}`; + + yield EOL; + yield '// check for terminal status code'; + yield If(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), 'continue;'); + + yield '// we are done polling, do a request on final target?'; + + switch (fsv) { + case 'original-uri': + case 'azure-asyncoperation': + case 'azure-async-operation': + case 'location': + // perform a final GET on the specified final URI. + yield $this.finalGet(finalUri, reqParameter, response); + break; + + default: + yield If(`!string.IsNullOrWhiteSpace(${finalUri})`, function* () { + yield $this.finalGet(finalUri, reqParameter, response); + }); + break; + } + }); + + } + yield responder(); + }); + + yield Finally(function* () { + yield '// finally statements'; + yield eventListener.signalNoCheck(ClientRuntime.Events.Finally, 'request', '_response'); + yield `${response.value}?.Dispose();`; + yield `${reqParameter.use}?.Dispose();`; + }); + + if ($this.returnNull) { + yield Return('result'); + $this.insert(new LocalVariable('result', System.Net.Http.HttpResponseMessage, { initializer: dotnet.Null })); + } + }); + + this.opMethod.emitCall($this.returnNull); + } + + private * finalGet(finalLocation: ExpressionOrLiteral, reqParameter: Variable, response: Variable) { + yield '// create a new request with the final uri'; + yield reqParameter.assign(`${valueOf(reqParameter)}.CloneAndDispose(${System.Uri.new(finalLocation)}, ${ClientRuntime.Method.Get})`); + + yield EOL; + yield '// drop the old response'; + yield `${response.value}?.Dispose();`; + + yield EOL; + yield '// make the final call'; + yield response.assign(`await ${this.opMethod.senderParameter}.SendAsync(${valueOf(reqParameter)}, ${this.opMethod.contextParameter})`); + + // make sure we're not polling anymore. + yield 'break;'; + } + + private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { + if (length(responses) > 1) { + yield Switch('_contentType', function* () { + for (const eachResponse of values(responses)) { + const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); + + let count = length(eachResponse.mimeTypes); + for (const mt of values(eachResponse.mimeTypes)) { + count--; + const mediaType = normalizeMediaType(mt); + if (mediaType) { + if (count === 0) { + yield Case(new StringExpression(mediaType).toString(), $this.responseHandler(mimetype, eachResponse, callbackParameter)); + } else { + yield TerminalCase(new StringExpression(mediaType).toString(), ''); + } + } + } + } + }); + } else { + const response = responses[0]; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); + // all mimeTypes per for this response code. + yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); + yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); + } + } + + private * NewResponsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { + if (length(responses) > 1) { + yield Switch('_contentType', function* () { + for (const eachResponse of values(responses)) { + const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); + + let count = length(eachResponse.protocol.http?.mediaTypes); + for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { + count--; + const mediaType = normalizeMediaType(mt); + if (mediaType) { + if (count === 0) { + yield Case(new StringExpression(mediaType).toString(), $this.NewResponseHandler(mimetype, eachResponse, callbackParameter)); + } else { + yield TerminalCase(new StringExpression(mediaType).toString(), ''); + } + } + } + } + }); + } else { + const response = responses[0]; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); + // all mimeTypes per for this response code. + yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); + yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); + } + } + + private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { + const callbackParameters = new Array(); + + if (callbackParameter.responseType) { + // hande the body response + const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); + if (r) { + + callbackParameters.push(r); + } + + // if (parseMediaType(mimetype)) { + // this media type isn't directly supported by deserialization + // we can return a stream to the consumer instead + // } + } + + if (callbackParameter.headerType) { + // header model deserialization... + const r = callbackParameter.headerType.deserializeFromResponse(KnownMediaType.Header, toExpression('_response'), toExpression('null')); + if (r) { + callbackParameters.push(r); + } + } + // make the callback with the appropriate parameters + yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; + } + + private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { + const callbackParameters = new Array(); + + if (callbackParameter.responseType) { + // hande the body response + const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); + if (r) { + + callbackParameters.push(r); + } + + // if (parseMediaType(mimetype)) { + // this media type isn't directly supported by deserialization + // we can return a stream to the consumer instead + // } + } + + if (callbackParameter.headerType) { + // header model deserialization... + const r = callbackParameter.headerType.deserializeFromResponse(KnownMediaType.Header, toExpression('_response'), toExpression('null')); + if (r) { + callbackParameters.push(r); + } + } + // make the callback with the appropriate parameters + yield `await ${eachResponse.language.csharp?.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; + } + + private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { + return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); + } + private NewResponseHandler(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { + return this.NewResponseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); + } +} export class ValidationMethod extends Method { constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { @@ -665,3 +1295,45 @@ export class ValidationMethod extends Method { }); } } +export class NewValidationMethod extends Method { + + constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + super(`${opMethod.name}_Validate`, System.Threading.Tasks.Task()); + this.apply(objectInitializer); + this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; + this.returnsDescription = opMethod.returnsDescription; + this.access = Access.Internal; + this.async = Modifier.Async; + this.push(Using('NoSynchronizationContext', '')); + + // add the method parameters + for (const parameter of opMethod.methodParameters) { + if (!parameter.defaultInitializer) { + this.addParameter(parameter); + } + } + + if (opMethod.bodyParameter) { + this.addParameter(opMethod.bodyParameter); + } + + this.addParameter(opMethod.contextParameter); + + // add statements to this method + this.add(function* () { + for (const parameter of opMethod.methodParameters) { + if (!parameter.defaultInitializer) { + // spit out parameter validation + yield parameter.validatePresenceStatement(opMethod.contextParameter); + yield parameter.validationStatement(opMethod.contextParameter); + } + } + + // spit out body parameter validation too + if (opMethod.bodyParameter) { + yield opMethod.bodyParameter.validatePresenceStatement(opMethod.contextParameter); + yield opMethod.bodyParameter.validationStatement(opMethod.contextParameter); + } + }); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/operation/namespace.ts b/powershell/llcsharp/operation/namespace.ts index d84b6a2de70..f2c8d1d854d 100644 --- a/powershell/llcsharp/operation/namespace.ts +++ b/powershell/llcsharp/operation/namespace.ts @@ -6,12 +6,12 @@ import { ImportDirective } from '@azure-tools/codegen-csharp'; import { Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class ServiceNamespace extends Namespace { - constructor(public state: State, objectInitializer?: DeepPartial) { - super(state.model.details.csharp.namespace || 'INVALID.NAMESPACE', state.project); + constructor(public state: State | NewState, objectInitializer?: DeepPartial) { + super(state instanceof NewState ? state.model.language.csharp?.namespace : state.model.details.csharp.namespace || 'INVALID-NAMESPACE', state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); } diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index 4495c64c9c7..ada0719dbf0 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Method } from '@azure-tools/codegen-csharp'; - +import { Parameter as NewHttpOperationParameter } from '@azure-tools/codemodel'; import { KnownMediaType } from '@azure-tools/codemodel-v3'; import { System } from '@azure-tools/codegen-csharp'; import { Expression, ExpressionOrLiteral } from '@azure-tools/codegen-csharp'; @@ -16,7 +16,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { HttpOperationParameter, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; /** represents a method parameter for an http operation (header/cookie/query/path) */ @@ -67,6 +67,53 @@ export class OperationParameter extends Parameter implements EnhancedVariable { } } +export class NewOperationParameter extends Parameter implements EnhancedVariable { + public typeDeclaration: EnhancedTypeDeclaration; + + public param: NewHttpOperationParameter; + + constructor(parent: Method, param: NewHttpOperationParameter, state: NewState, objectInitializer?: DeepPartial) { + const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(param.schema, !!param.required, state); + super(param.language.csharp?.name || '', typeDeclaration); + this.param = param; + this.typeDeclaration = typeDeclaration; + this.apply(objectInitializer); + this.description = param.language.csharp?.description || ''; + } + + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { + // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)) + return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { + return this.typeDeclaration.deserializeFromNode(mediaType, node, this); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { + return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); + } + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { + return this.typeDeclaration.serializeToContent(mediaType, this, mode); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); + } + + public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { + return this.typeDeclaration.validatePresence(eventListener, this); + } + public validationStatement(eventListener: Variable): OneOrMoreStatements { + return this.typeDeclaration.validateValue(eventListener, this); + } +} + /** represents a method parameter for an http operation (body) */ export class OperationBodyParameter extends Parameter implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ @@ -157,3 +204,33 @@ export class CallbackParameter extends Parameter { this.apply(objectInitializer); } } + +export class NewCallbackParameter extends Parameter { + responseType: (EnhancedTypeDeclaration) | null; + headerType: (EnhancedTypeDeclaration) | null; + + constructor(name: string, responseType: (EnhancedTypeDeclaration) | null, headerType: (EnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { + // regular pipeline style. (callback happens after the pipline is called) + if (responseType) { + if (headerType) { + // both + super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); + } else { + // just response + super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task())); + } + } else { + if (headerType) { + // just headers + super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); + } else { + // no content? + super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task())); + } + } + + this.responseType = responseType; + this.headerType = headerType; + this.apply(objectInitializer); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/project.ts b/powershell/llcsharp/project.ts index bc684e0a59d..e20ffe398bb 100644 --- a/powershell/llcsharp/project.ts +++ b/powershell/llcsharp/project.ts @@ -7,13 +7,14 @@ import { Host } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { State } from './generator'; -import { ModelsNamespace } from './model/namespace'; +import { State, NewState } from './generator'; +import { ModelsNamespace, NewModelsNamespace } from './model/namespace'; import { ApiClass } from './operation/api-class'; import { ServiceNamespace } from './operation/namespace'; import { SupportNamespace } from './enums/namespace'; import { DeepPartial } from '@azure-tools/codegen'; + export class Project extends codeDomProject { public jsonSerialization = true; @@ -91,3 +92,81 @@ export class Project extends codeDomProject { public modelsNamespace!: ModelsNamespace; public supportNamespace!: SupportNamespace; } + +export class NewProject extends codeDomProject { + + public jsonSerialization = true; + public xmlSerialization = false; + public defaultPipeline = true; + public emitSignals = true; + public projectNamespace!: string; + public overrides!: Dictionary; + protected state!: NewState; + + apifolder!: string; + runtimefolder!: string; + azure!: boolean; + license!: string; + identityCorrection!: boolean; + + constructor(protected service: Host, objectInitializer?: DeepPartial) { + super(); + this.apply(objectInitializer); + } + + public async init(): Promise { + await super.init(); + + this.state = await new NewState(this.service).init(this); + this.apifolder = await this.state.getValue('api-folder', ''); + this.runtimefolder = await this.state.getValue('runtime-folder', 'runtime'); + this.azure = await this.state.getValue('azure', false) || await this.state.getValue('azure-arm', false); + this.identityCorrection = await this.state.getValue('identity-correction-for-post', false); + this.license = await this.state.getValue('header-text', ''); + + + // add project namespace + this.projectNamespace = this.state.model.language.csharp?.namespace; + this.overrides = { + 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, + 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, + 'using Converters;': '', + 'using Internal.Extensions;': '', + 'using Data;': '', + 'using Parser;': '', + + 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, + 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, + 'Microsoft.Rest': this.projectNamespace + }; + + this.serviceNamespace = new ServiceNamespace(this.state); + this.serviceNamespace.header = this.license; + this.addNamespace(this.serviceNamespace); + + // add support namespace + this.supportNamespace = new SupportNamespace(this.serviceNamespace, this.state); + this.supportNamespace.header = this.license; + this.addNamespace(this.supportNamespace); + + // add model classes + this.modelsNamespace = new NewModelsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); + this.modelsNamespace.header = this.license; + this.addNamespace(this.modelsNamespace); + + // create API class + new ApiClass(this.serviceNamespace, this.state, { description: `Low-level API implementation for the ${this.state.model.info.title} service. \n${this.state.model.info.description || ''}` }); + + // abort now if we have any errors. + this.state.checkpoint(); + + return this; + } + + public serviceNamespace!: ServiceNamespace; + public modelsNamespace!: NewModelsNamespace; + public supportNamespace!: SupportNamespace; +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/array.ts b/powershell/llcsharp/schema/array.ts index 11dbdb7504d..1c1be135f89 100644 --- a/powershell/llcsharp/schema/array.ts +++ b/powershell/llcsharp/schema/array.ts @@ -15,6 +15,9 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; + + import { popTempVar, pushTempVar } from '../schema/primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; @@ -25,19 +28,35 @@ export class ArrayOf implements EnhancedTypeDeclaration { return toExpression('null /* arrayOf */'); } - constructor(public schema: Schema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { + constructor(public schema: Schema | NewSchema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { } + protected get isWrapped(): boolean { - return this.schema.xml && this.schema.xml.wrapped || false; + if (this.schema instanceof NewSchema) { + return this.schema.serialization?.xml && this.schema.serialization?.xml.wrapped || false; + } else { + return this.schema.xml && this.schema.xml.wrapped || false; + } + } protected get wrapperName(): string | undefined { - return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; + if (this.schema instanceof NewSchema) { + return this.schema.serialization?.xml && this.isWrapped ? this.schema.serialization.xml.name : undefined; + } else { + return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; + } + } protected get serializedName(): string | undefined { - return this.schema.xml ? this.schema.xml.name : undefined; + if (this.schema instanceof NewSchema) { + return this.schema.serialization?.xml ? this.schema.serialization.xml.name : undefined; + } else { + return this.schema.xml ? this.schema.xml.name : undefined; + } + } get elementTypeDeclaration(): string { return this.elementType.declaration; @@ -48,6 +67,7 @@ export class ArrayOf implements EnhancedTypeDeclaration { } get encode(): string { + this.schema.extensions = this.schema.extensions || {}; return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; } @@ -150,15 +170,20 @@ export class ArrayOf implements EnhancedTypeDeclaration { const serArray = `global::System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}))`; return toExpression(`null != ${value} ? new ${ClientRuntime.XNodeArray}(${serArray}) : null`); } - - case KnownMediaType.Xml: { - if (this.isWrapped) { - const name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; - return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); - } else { - throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); - } - } + // skip-for-time-being + // case KnownMediaType.Xml: { + // if (this.isWrapped) { + // let name = ''; + // if (this.elementType.schema instanceof NewSchema) { + // name = this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || serializedName : serializedName; + // } else { + // name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; + // } + // return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); + // } else { + // throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); + // } + // } case KnownMediaType.Cookie: case KnownMediaType.QueryParameter: return toExpression(`(null != ${value} && ${value}.Length > 0 ? "${value}=" + ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current, each) => current + "," + ( ${this.encode}(each?.ToString()??${System.String.Empty}) ))) : ${System.String.Empty})`); @@ -183,15 +208,16 @@ export class ArrayOf implements EnhancedTypeDeclaration { `${(this.serializeToNode(mediaType, value, '', mode))}`, System.Text.Encoding.UTF8); } - case KnownMediaType.Xml: { - // if the reference doesn't define an XML schema then use its default name - const defaultName = this.elementType.schema.details.csharp.name; - return System.Net.Http.StringContent.new(Ternery( - IsNotNull(value), - `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, - System.String.Empty - ), System.Text.Encoding.UTF8); - } + // skip-for-time-being + // case KnownMediaType.Xml: { + // // if the reference doesn't define an XML schema then use its default name + // const defaultName = this.elementType.schema.details.csharp.name; + // return System.Net.Http.StringContent.new(Ternery( + // IsNotNull(value), + // `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, + // System.String.Empty + // ), System.Text.Encoding.UTF8); + // } case KnownMediaType.Cookie: case KnownMediaType.QueryParameter: @@ -226,8 +252,11 @@ export class ArrayOf implements EnhancedTypeDeclaration { } case KnownMediaType.Xml: if (this.isWrapped) { - - return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; + if (this.elementType.schema instanceof NewSchema) { + return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; + } else { + return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; + } } else { return If(`null != ${value}`, ForEach(each, toExpression(value), `AddIf(${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}, ${container}.Add);`)); } diff --git a/powershell/llcsharp/schema/extended-type-declaration.ts b/powershell/llcsharp/schema/extended-type-declaration.ts index b5a29aa1329..f518fd8818e 100644 --- a/powershell/llcsharp/schema/extended-type-declaration.ts +++ b/powershell/llcsharp/schema/extended-type-declaration.ts @@ -9,6 +9,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { TypeDeclaration } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; /** A TypeDeclaration that can assist in generating code for a variety of serialization, validation and other common use cases */ export interface EnhancedTypeDeclaration extends TypeDeclaration { @@ -48,7 +49,7 @@ export interface EnhancedTypeDeclaration extends TypeDeclaration { isXmlAttribute: boolean; /** the underlying schema for this type declarartion. */ - schema: Schema; + schema: Schema | NewSchema; isNullable: boolean; diff --git a/powershell/llcsharp/schema/object.ts b/powershell/llcsharp/schema/object.ts index 376203c3197..d651fa13d62 100644 --- a/powershell/llcsharp/schema/object.ts +++ b/powershell/llcsharp/schema/object.ts @@ -14,6 +14,7 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; @@ -179,3 +180,167 @@ export class ObjectImplementation implements EnhancedTypeDeclaration { get classDeclaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}`; } } + +export class NewObjectImplementation implements EnhancedTypeDeclaration { + public isXmlAttribute = false; + + get defaultOfType() { + return toExpression('null /* object */'); + } + + get isNullable(): boolean { + return true; + } + + get convertObjectMethod() { + return `${this.schema.language.csharp?.fullname}TypeConverter.ConvertFrom`; + } + + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + // JsonObject + const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; + return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonObject}>("${serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromJson(${tmp}) : ${defaultValue}`); + } + + case KnownMediaType.Xml: { + // XElement/XElement or XElement/XAttribute + const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; + // prefer specified XML name if available + return toExpression(`If( ${valueOf(container)}?.Element("${this.schema.serialization?.xml ? this.schema.serialization.xml.name || serializedName : serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); + } + } + return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); + } + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + try { + const tmp = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: { + // we're always going to go thru FromJson; it'll handle nulls and polymorphism. + return toExpression(`${this.classDeclaration}.FromJson(${node}) `); + } + case KnownMediaType.Xml: { + + return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); + } + } + } finally { + popTempVar(); + } + return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + return toExpression(`${value}?.ToJson(null, ${mode.value})`); + } + case KnownMediaType.Xml: { + return toExpression(`${value}?.ToXml(null, ${mode.value})`); + } + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + return System.Net.Http.StringContent.new( + Ternery( + IsNotNull(value), + `${value}.ToJson(null).ToString()`, + new StringExpression('{}')), + System.Text.Encoding.UTF8); + } + case KnownMediaType.Xml: { + return System.Net.Http.StringContent.new( + Ternery( + IsNotNull(value), + `${value}.ToXml(null).ToString()`, + System.String.Empty), + System.Text.Encoding.UTF8); + } + //skip-for-time-being + // case KnownMediaType.Multipart: { + // let contents = ''; + // for (const p of values(this.schema.properties)) { + // // to do -- add in a potential support for the filename too. + // contents = `${contents}${EOL} bodyContent.Add( ${System.Net.Http.StreamContent.new(`${value}.${p.details.csharp.name}`)},"${p.serializedName}");`; + // } + // // bodyContent.Add(new _ystem.Net.Http.StreamContent(body.AudioFile), "audioFile"); + // return toExpression(`new ${System.Func(System.Net.Http.MultipartFormDataContent)}(() => + // { + // var bodyContent = ${System.Net.Http.MultipartFormDataContent.new()}; + // ${contents} + // return bodyContent; + // })()`); + // } + } + return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + switch (mediaType) { + case KnownMediaType.Json: { + return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); + } + case KnownMediaType.Xml: { + return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); + } + } + return undefined; + } + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + switch (mediaType) { + case KnownMediaType.Json: { + if (this.schema.language.csharp?.hasHeaders) { + return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)}.ReadHeaders(_response.Headers))`); + } + return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); + } + case KnownMediaType.Xml: { + return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); + } + } + return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + // const v = (value).valuePrivate || value; + switch (mediaType) { + case KnownMediaType.Json: + return `AddIf( null != ${value} ? (${ClientRuntime.JsonNode}) ${value}.ToJson(null,${mode.value}) : null, "${serializedName}" ,${container}.Add );`; + + case KnownMediaType.Xml: + // prefer specified XML name if available + return `AddIf( null != ${value} ? ${value}.ToXml(new ${System.Xml.Linq.XElement}("${this.schema.serialization?.xml ? this.schema.serialization.xml.name || serializedName : serializedName}")) : null, ${container}.Add );`; + + } + return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; + } + + isRequired = false; + + constructor(public schema: NewSchema) { + } + + public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { + return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `.trim(); + } + public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { + return `await ${eventListener}.AssertObjectIsValid(${nameof(property.value)}, ${property}); `; + } + + get declaration(): string { return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.interfaceName}`; } + get classDeclaration(): string { return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.name}`; } + +} diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 8ab8a58edb0..209c0fc847f 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; + import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; @@ -16,10 +18,13 @@ import { DateTime, DateTime1123, UnixTime } from './date-time'; import { Duration } from './duration'; import { EnumImplementation } from './enum'; import { Numeric } from './integer'; -import { ObjectImplementation } from './object'; -import { String } from './string'; +import { ObjectImplementation, NewObjectImplementation } from './object'; +import { String, NewString } from './string'; import { Uuid } from './Uuid'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { PwshModel } from '../../utils/PwshModel'; +import { NewModelState } from '../../utils/model-state'; +import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; export class SchemaDefinitionResolver { private readonly cache = new Map(); @@ -144,4 +149,84 @@ export class SchemaDefinitionResolver { state.error(`Schema '${schema.details.csharp.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); throw new Error('Unknown Model. Fatal.'); } + } + +export class NewSchemaDefinitionResolver { + private readonly cache = new Map(); + private add(schema: NewSchema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { + this.cache.set(schema.language?.csharp?.fullname || '', value); + return value; + } + + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): EnhancedTypeDeclaration { + if (!schema) { + throw new Error('SCHEMA MISSING?'); + } + + // determine if we need a new model class for the type or just a known type object + switch (schema.type) { + // case SchemaType.Array: { + // // can be recursive! + // // handle boolean arrays as booleans (powershell will try to turn it into switches!) + // const ar = schema; + // const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(schema.items, true, state.path('items')); + // return new ArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); + // } + + case SchemaType.Object: { + const result = schema.language.csharp && this.cache.get(schema.language.csharp.fullname || ''); + if (result) { + return result; + } + return this.add(schema, new NewObjectImplementation(schema)); + } + case SchemaType.String: { + return new NewString(schema, required); + + } + + // case JsonType.Boolean: + // return new Boolean(schema, required); + + // case JsonType.Integer: + // switch (schema.format) { + // case IntegerFormat.Int64: + // case IntegerFormat.None: + // return new Numeric(schema, required, required ? 'long' : 'long?'); + // case IntegerFormat.UnixTime: + // return new UnixTime(schema, required); + // case IntegerFormat.Int32: + // return new Numeric(schema, required, required ? 'int' : 'int?'); + // } + // // fallback to int if the format isn't recognized + // return new Numeric(schema, required, required ? 'int' : 'int?'); + + // case JsonType.Number: + // switch (schema.format) { + // case NumberFormat.None: + // case NumberFormat.Double: + // return new Numeric(schema, required, required ? 'double' : 'double?'); + // case NumberFormat.Float: + // return new Numeric(schema, required, required ? 'float' : 'float?'); + // case NumberFormat.Decimal: + // return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); + // } + // // fallback to float if the format isn't recognized + // return new Numeric(schema, required, required ? 'float' : 'float?'); + + // case undefined: + // if (schema.extensions && schema.extensions['x-ms-enum']) { + // return new EnumImplementation(schema, required); + // } + + // "any" case + // this can happen when a model is just an all-of something else. (sub in the other type?) + case undefined: + break; + + } + state.error(`Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); + throw new Error('Unknown Model. Fatal.'); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index 078bf26bbfb..b88355984d4 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -12,6 +12,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; +import { Schema as NewSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; @@ -207,3 +208,195 @@ ${this.validateEnum(eventListener, property)} return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${this.schema.enum.joinWith((v) => `@"${v}"`)});`; } } + +/** A ETD for the c# string type. */ +export class NewString implements EnhancedTypeDeclaration { + public isXmlAttribute = false; + + get defaultOfType() { + return toExpression('null'); + } + get convertObjectMethod() { + return 'global::System.Convert.ToString'; + } + + get isNullable(): boolean { + return true; + } + + get encode(): string { + return this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; + } + + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + // container should be a JsonObject + const tmpVar = `__${camelCase(['json', ...deconstruct(serializedName)])}`; + return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmpVar}) ? (string)${tmpVar} : (string)${defaultValue}`); + } + case KnownMediaType.Xml: { + const xTmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; + return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}"), out var ${xTmp}) ? (string)${xTmp} : (string)${defaultValue}`); + } + case KnownMediaType.Header: { + // HttpResponseHeaders + const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; + return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${tmp} : (string)${defaultValue}`); + } + } + return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + try { + const tmp = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: + // node should be a JsonString + return toExpression(`${node} is ${ClientRuntime.JsonString} ${tmp} ? (${this.declaration})(${tmp}.ToString()) : ${defaultValue}`); + + case KnownMediaType.Xml: + return toExpression(`${node} is ${System.Xml.Linq.XElement} ${tmp} ? (string)${tmp} : ${defaultValue}`); + } + } finally { + popTempVar(); + } + return toExpression(`null /* deserializeFromContainer doesn't support '${mediaType}' ${__filename}*/`); + } + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + return toExpression(`null != (((object)${value})?.ToString()) ? (${ClientRuntime.JsonNode}) new ${ClientRuntime.JsonString}(${value}.ToString()) : null`); + + case KnownMediaType.Xml: + return toExpression(`null != (${value}?.ToString()) ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); + + case KnownMediaType.QueryParameter: + + if (this.isRequired) { + return toExpression(`"${serializedName}=" + ${this.encode}(${value})`); + } else { + return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${valueOf(value)}))`); + } + + case KnownMediaType.Cookie: + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + if (this.isRequired) { + return toExpression(`${this.encode}(${value})`); + } + return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : ${this.encode}(${value}) )`); + + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + + switch (mediaType) { + case KnownMediaType.Json: { + return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); + } + case KnownMediaType.Xml: { + return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); + } + case KnownMediaType.UriParameter: { + return toExpression(content); + } + } + return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); + } + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + switch (mediaType) { + case KnownMediaType.Json: + return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); + + } + return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); + } + + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + switch (mediaType) { + case KnownMediaType.Json: + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${container}.Add );`; + + case KnownMediaType.Xml: + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${container}.Add );`; + + case KnownMediaType.Header: + // container : HttpRequestHeaders + return this.isRequired ? + `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : + If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value});`); + + case KnownMediaType.QueryParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `${serializedName}={${value}.ToString()}` : + `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; + + case KnownMediaType.UriParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `(${serializedName}={${value}.ToString()})` : + `(null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}")`; + } + return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + constructor(public schema: StringSchema, public isRequired: boolean) { + + } + + get declaration(): string { + return 'string'; + } + + validateValue(eventListener: Variable, property: Variable): string { + return ` +${this.validateMinLength(eventListener, property)} +${this.validateMaxLength(eventListener, property)} +${this.validateRegex(eventListener, property)} + `.trim(); + + } + + public validatePresence(eventListener: Variable, property: Variable): string { + return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); + } + + private validateMinLength(eventListener: Variable, property: Variable): string { + if (!this.schema.minLength) { + return ''; + } + return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${this.schema.minLength});`; + } + private validateMaxLength(eventListener: Variable, property: Variable): string { + if (!this.schema.maxLength) { + return ''; + } + return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${this.schema.maxLength});`; + } + private validateRegex(eventListener: Variable, property: Variable): string { + if (!this.schema.pattern) { + return ''; + } + return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${this.schema.pattern}");`; + } + // private validateEnum(eventListener: Variable, property: Variable): string { + // if (!this.schema.enum || length(this.schema.enum) === 0) { + // return ''; + // } + // return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${this.schema.enum.joinWith((v) => `@"${v}"`)});`; + // } +} diff --git a/powershell/main.ts b/powershell/main.ts index 155741913ce..a338bc235c2 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -11,6 +11,14 @@ import { powershell } from './plugins/powershell'; import { addCompleter } from './plugins/add-azure-completers'; import { csnamer } from './plugins/cs-namer'; import { llcsharp } from './plugins/llcsharp'; +import { createInlinedPropertiesPlugin } from './plugins/plugin-create-inline-properties'; +import { tweakModelPlugin } from './plugins/plugin-tweak-model'; +import { tweakModelAzurePlugin } from './plugins/plugin-tweak-model-azure'; +import { createCommandsV2 } from './plugins/create-commands-v2'; +import { csnamerV2 } from './plugins/cs-namer-v2'; +import { namerV2 } from './plugins/ps-namer-v2'; +import { llcsharpV2 } from './plugins/llcsharp-v2'; +import { powershellV2 } from './plugins/powershell-v2'; require('source-map-support').install(); @@ -23,6 +31,16 @@ export async function main() { pluginHost.Add('add-azure-completers', addCompleter); pluginHost.Add('csnamer', csnamer); pluginHost.Add('llcsharp', llcsharp); + // Following are plugins moved from remodeler + pluginHost.Add('tweakcodemodel-v2', tweakModelPlugin); + pluginHost.Add('tweakcodemodelazure-v2', tweakModelAzurePlugin); + pluginHost.Add('create-virtual-properties-v2', createInlinedPropertiesPlugin); + pluginHost.Add('create-commands-v2', createCommandsV2); + pluginHost.Add('csnamer-v2', csnamerV2); + pluginHost.Add('psnamer-v2', namerV2); + pluginHost.Add('llcsharp-v2', llcsharpV2); + pluginHost.Add('powershell-v2', powershellV2); + await pluginHost.Run(); } diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 24e90893091..8fdea24e7c1 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -2,10 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Schema as NewSchema } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; -import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, DeserializerPartialClass } from '../llcsharp/exports'; -import { State } from '../internal/state'; +import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; +import { State, NewState } from '../internal/state'; import { PSObject, PSTypeConverter, TypeConverterAttribute } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -246,6 +247,238 @@ export class ModelExtensionsNamespace extends Namespace { yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); + // null if not successful + yield Return(dotnet.Null); + }); + } + } + } +} + +export class NewModelExtensionsNamespace extends Namespace { + CreateReferenceType(): Class { + const rt = new Class(this, 'ReferenceType'); + rt.add(new Property('Id', dotnet.String, { setAccess: Access.Internal })); + return rt; + } + private subNamespaces = new Dictionary(); + + public get outputFolder(): string { + return join(this.state.project.apiFolder, 'Models'); + } + resolver = new NewSchemaDefinitionResolver(); + + constructor(parent: Namespace, private schemas: Dictionary, private state: NewState, objectInitializer?: DeepPartial) { + super('Models', parent); + this.apply(objectInitializer); + this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); + this.subNamespaces[this.fullName] = this; + + const $this = this; + const resolver = (s: NewSchema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state); + + // Add typeconverters to model classes (partial) + for (const schema of values(schemas)) { + if (!schema || (schema.language.csharp && schema.language.csharp.skip)) { + continue; + } + + const td = this.resolver.resolveTypeDeclaration(schema, true, state); + if (td instanceof ObjectImplementation) { + + // it's a class object. + const className = td.schema.details.csharp.name; + const interfaceName = td.schema.details.csharp.interfaceName || ''; + const converterClass = `${className}TypeConverter`; + + if (this.findClassByName(className).length > 0) { + continue; + } + + // get the actual full namespace for the schema + const fullname = schema.language.csharp?.namespace || this.fullName; + const ns = this.subNamespaces[fullname] || this.add(new ApiVersionModelExtensionsNamespace(this.outputFolder, fullname)); + + // create the model extensions for each object model + // 2. A partial interface with the type converter attribute + const modelInterface = new Interface(ns, interfaceName, { + partial: true, + description: td.schema.details.csharp.description, + fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. + }); + modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + + // 1. A partial class with the type converter attribute + const model = new Class(ns, className, undefined, { + partial: true, + description: td.schema.details.csharp.description, + fileName: `${className}.PowerShell` + }); + + // if the model is supposed to be use 'by-reference' we should create an I*Reference interface for that + // and add that interface to the extension class + if (schema.language.csharp?.byReference) { + const refInterface = `${interfaceName}_Reference`; + schema.language.csharp.referenceInterface = `${ns.fullName}.${refInterface}`; + + const referenceInterface = new Interface(ns, refInterface, { + partial: true, + description: `Reference for model ${fullname}`, + fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. + }); + referenceInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + referenceInterface.add(new InterfaceProperty('Id', dotnet.String, { setAccess: Access.Internal })); + model.interfaces.push(referenceInterface); + + // add it to the generic reference type. + // referenceType = referenceType || this.CreateReferenceType(); + // referenceType.interfaces.push(referenceInterface); + } + + + model.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { + static: Modifier.Static, + parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], + description: `Creates a new instance of , deserializing the content from a json string.`, + returnsDescription: 'an instance of the model class.' + })); + + model.add(new LambdaMethod('ToJsonString', dotnet.String, new LiteralExpression(`ToJson(${dotnet.Null}, ${ClientRuntime.SerializationMode.IncludeAll})?.ToString()`), { + description: 'Serializes this instance to a json string.', + returnsDescription: 'a containing this model serialized to JSON text.' + })); + + const hashDeseralizer = new NewDeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); + const psDeseralizer = new NewDeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); + + // + static FromJsonString(string json); + // + string ToJsonString() + + // 3. A TypeConverter class + const typeConverter = new Class(ns, converterClass, PSTypeConverter, { + description: `A PowerShell PSTypeConverter to support converting to an instance of `, + fileName: `${className}.TypeConverter` + }); + typeConverter.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the parameter can be converted to the parameter', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false', + })); + typeConverter.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], description: 'NotImplemented -- this will return null', + returnsDescription: 'will always return null.' + })); + typeConverter.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, new LiteralExpression('CanConvertFrom(sourceValue)'), { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + })); + typeConverter.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression('ConvertFrom(sourceValue)'), { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], + description: 'Converts the parameter to the parameter using and ', + returnsDescription: `an instance of , or null if there is no suitable conversion.` + })); + + typeConverter.add(new Method('CanConvertFrom', dotnet.Bool, { + static: Modifier.Static, + parameters: [ + new Parameter('sourceValue', dotnet.Dynamic, { description: `the instance to check if it can be converted to the type.` }), + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: `true if the instance could be converted to a type, otherwise false ` + })).add(function* () { + yield If('null == sourceValue', Return(dotnet.True)); + + const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); + yield t.declarationStatement; + + if (schema.language.default.uid === 'universal-parameter-type' || schema.language.csharp?.byReference) { + yield '// we allow string conversion too.'; + yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); + } + + yield If(IsAssignableFrom(PSObject, t), function* () { + yield '// we say yest to PSObjects'; + yield Return(dotnet.True); + }); + yield If(IsAssignableFrom(System.Collections.IDictionary, t), function* () { + yield '// we say yest to Hashtables/dictionaries'; + yield Return(dotnet.True); + }); + + yield Try(If('null != sourceValue.ToJsonString()', Return(dotnet.True))); + yield Catch(undefined, '// Not one of our objects'); + + yield Try(function* () { + const t = new LocalVariable('text', dotnet.String, { initializer: 'sourceValue.ToString()?.Trim()' }); + yield t.declarationStatement; + yield Return(`${dotnet.True} == ${t.value}?.StartsWith("{") && ${dotnet.True} == ${t.value}?.EndsWith("}") && ${ClientRuntime.JsonNode.Parse(t)}.Type == ${ClientRuntime.JsonType.Object}`); + }); + yield Catch(undefined, '// Doesn\'t look like it can be treated as JSON'); + + yield Return(dotnet.False); + }); + + typeConverter.add(new Method('ConvertFrom', modelInterface, { + static: Modifier.Static, + parameters: [ + new Parameter('sourceValue', dotnet.Dynamic, { + description: `the value to convert into an instance of .` + }), + ], + description: 'Converts the parameter to the parameter using and ', + returnsDescription: `an instance of , or null if there is no suitable conversion.` + })).add(function* () { + // null begets null + yield If('null == sourceValue', Return(dotnet.Null)); + + const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); + yield t.declarationStatement; + + if (($this.state.project.azure && schema.language.default.uid === 'universal-parameter-type') || schema.language.csharp?.byReference) { + yield '// support direct string to id type conversion.'; + yield If(`${t.value} == typeof(${System.String})`, function* () { + yield Return(`new ${className} { Id = sourceValue }`); + }); + } + + if (schema.language.csharp?.byReference) { + yield '// if Id is present with by-reference schemas, just return the type with Id '; + yield Try(Return(`new ${className} { Id = sourceValue.Id }`)); + yield Catch(undefined, '// Not an Id reference parameter'); + } + + // if the type can be assigned directly, do that + yield If(IsAssignableFrom(td, t), Return('sourceValue')); + + // try using json first (either from string or toJsonString()) + yield Try(Return(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`)); + yield Catch(undefined, '// Unable to use JSON pattern'); + + yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); + yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); + // null if not successful yield Return(dotnet.Null); }); diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index 1bed829add9..027e4c56654 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -6,7 +6,7 @@ import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; import { InvocationInfo, PSCredential, IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, } from '../internal/powershell-declarations'; -import { State } from '../internal/state'; +import { State, NewState } from '../internal/state'; import { ClientRuntime } from '../llcsharp/exports'; import { DeepPartial } from '@azure-tools/codegen'; @@ -259,3 +259,253 @@ export class ModuleClass extends Class { }); } } + +export class NewModuleClass extends Class { + + // get the name of the client API class + TaskOfHttpResponseMessage = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); + + // lets the common code call the signal again (recursive! careful!) + incomingSignalFunc = System.Func( + dotnet.String, + System.Threading.CancellationToken, + System.Func(System.EventArgs), + /* returns */ System.Threading.Tasks.Task()); + + eventListenerFunc = System.Func( + dotnet.String, + System.Threading.CancellationToken, + System.Func(System.EventArgs), + this.incomingSignalFunc, + InvocationInfo, + dotnet.String, + dotnet.String, + dotnet.String, + System.Exception, + /* returns */ System.Threading.Tasks.Task()); + + IEventListenerExpanded = [ + System.Threading.CancellationToken, /* token */ + System.Action(), /* Cancel() */ + this.incomingSignalFunc, + ]; + + nextStep = System.Func( + System.Net.Http.HttpRequestMessage, + ...this.IEventListenerExpanded, + /* returns */ this.TaskOfHttpResponseMessage); + + initMethod = this.add(new Method('Init', dotnet.Void, { description: 'Initialization steps performed after the module is loaded.' })); + createPipelineMethod!: Method; + + pInvocationInfo = new Parameter('invocationInfo', InvocationInfo, { description: 'The from the cmdlet' }); + pPipeline = new Parameter('pipeline', ClientRuntime.HttpPipeline, { modifier: ParameterModifier.Ref, description: 'The HttpPipeline for the request' }); + pProxy = new Parameter('proxy', System.Uri, { description: 'The HTTP Proxy to use.' }); + pProxyCredential = new Parameter('proxyCredential', PSCredential, { description: 'The HTTP Proxy Credentials' }); + pUseDefaultCredentials = new Parameter('proxyUseDefaultCredentials', dotnet.Bool, { description: 'True if the proxy should use default credentials' }); + + pCorrelationId = new Parameter('correlationId', dotnet.String, { description: 'the cmdlet\'s correlation id.' }); + pParameterName = new Parameter('parameterName', dotnet.String, { description: 'The name of the parameter to get the value for.' }); + + pId = new Parameter('id', dotnet.String, { description: 'The ID of the event ' }); + pToken = new Parameter('token', System.Threading.CancellationToken, { description: 'The cancellation token for the event ' }); + pGetEventData = new Parameter('getEventData', System.Func(System.EventArgs), { description: 'A delegate to get the detailed event data' }); + + pParameterSetName = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.' }); + pParameterSetNameWithDefault = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.', defaultInitializer: dotnet.Null }); + pProcessRecordId = new Parameter('processRecordId', dotnet.String, { description: 'the cmdlet\'s process record correlation id.' }); + pException = new Parameter('exception', System.Exception, { description: 'the exception that is being thrown (if available)' }); + + fPipeline = this.add(new Field('_pipeline', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance' })); + fPipelineWithProxy = this.add(new Field('_pipelineWithProxy', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance (when proxy is enabled)' })); + fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); + fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); + + constructor(namespace: Namespace, private readonly state: NewState, objectInitializer?: DeepPartial) { + super(namespace, 'Module'); + this.apply(objectInitializer); + this.partial = true; + this.description = 'A class that contains the module-common code and data.'; + + const $this = this; + + // static instance property + this.add(new LazyProperty('Instance', this, new LiteralExpression(`new ${this.declaration}()`), { + instanceAccess: this.declaration, + static: Modifier.Static, + description: 'the singleton of this module class' + })); + + const clientAPI = new ClassType(this.state.model.language.csharp?.namespace, this.state.model.language.csharp?.name || ''); + const clientProperty = this.add(new Property('ClientAPI', clientAPI, { description: 'The instance of the Client API' })); + + if (this.state.project.azure) { + this.createAzureInitAndPipeline(namespace); + } else { + this.createInitAndPipeline(namespace); + } + + this.add(new Constructor(this, { + access: Access.Private, + description: 'Creates the module instance.', + body: function* () { + yield '/// constructor'; + yield clientProperty.assignPrivate(clientAPI.new()); + yield `${$this.fHandler}.Proxy = ${$this.fWebProxy};`; + + yield $this.fPipeline.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new()))); + yield $this.fPipelineWithProxy.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new($this.fHandler)))); + } + })); + + /* extensibility points */ + this.add(new PartialMethod('BeforeCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); + this.add(new PartialMethod('AfterCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); + this.add(new PartialMethod('CustomInit', dotnet.Void)); + + /* Setting the Proxy */ + this.add(new Method('SetProxyConfiguration', dotnet.Void, { + parameters: [this.pProxy, this.pProxyCredential, this.pUseDefaultCredentials], + *body() { + yield '// set the proxy configuration'; + yield `${$this.fWebProxy}.Address = proxy;`; + yield `${$this.fWebProxy}.BypassProxyOnLocal = false;`; + yield `${$this.fWebProxy}.Credentials = proxyCredential ?.GetNetworkCredential();`; + yield `${$this.fWebProxy}.UseDefaultCredentials = proxyUseDefaultCredentials;`; + yield `${$this.fHandler}.UseProxy = proxy != null;`; + } + })); + } + + createInitAndPipeline(namespace: Namespace) { + const $this = this; + // non-azure init method + this.initMethod.add(function* () { + yield '// called at module init time...'; + yield 'CustomInit();'; + }); + + this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { + parameters: [this.pInvocationInfo, this.pParameterSetNameWithDefault], + description: 'Creates an instance of the HttpPipeline for each call.', + returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` + })); + + // non-azure createPipeline method + this.createPipelineMethod.add(function* () { + const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); + yield pip.declarationStatement; + yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; + yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); + yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; + yield Return(pip); + }); + + this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); + } + + createAzureInitAndPipeline(namespace: Namespace) { + const $this = this; + + const sendAsyncStep = namespace.add(new Alias('SendAsyncStepDelegate', + System.Func( + System.Net.Http.HttpRequestMessage, + ...this.IEventListenerExpanded, + this.nextStep, /* Next( ...) */ + /* returns */ this.TaskOfHttpResponseMessage))); + + const pipelineChangeDelegate = namespace.add(new Alias('PipelineChangeDelegate', System.Action(sendAsyncStep.fullDefinition))); + + const getParameterDelegate = namespace.add(new Alias('GetParameterDelegate', System.Func( + dotnet.String, /* resourceId */ + dotnet.String, /* moduleName */ + InvocationInfo, /* invocationInfo */ + dotnet.String, /* correlationId */ + dotnet.String, /* parameterName */ + /* returns */ dotnet.Object))); + + const moduleLoadPipelineDelegate = namespace.add(new Alias('ModuleLoadPipelineDelegate', System.Action( + dotnet.String, /* resourceId */ + dotnet.String, /* moduleName */ + pipelineChangeDelegate.fullDefinition, /* prependStep */ + pipelineChangeDelegate.fullDefinition))); /* appendStep */ + + const newRequestPipelineDelegate = namespace.add(new Alias('NewRequestPipelineDelegate', System.Action( + InvocationInfo, /* invocationInfo */ + dotnet.String, /* correlationId */ + dotnet.String, /* processRecordId */ + pipelineChangeDelegate.fullDefinition, /* prependStep */ + pipelineChangeDelegate.fullDefinition))); /* appendStep */ + + const argumentCompleterDelegate = namespace.add(new Alias('ArgumentCompleterDelegate', System.Func( + dotnet.String, /* completerName */ + InvocationInfo, /* invocationInfo */ + dotnet.String, /* correlationId */ + dotnet.StringArray, /* resourceTypes */ + dotnet.StringArray, /* parentResourceParameterNames */ + /* returns */ dotnet.StringArray, + ))); + + const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); + const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', this.eventListenerFunc)); + + namespace.add(new Alias('NextDelegate', this.nextStep)); + + /* AzAccounts VTable properties */ + const OnModuleLoad = this.add(new Property('OnModuleLoad', moduleLoadPipelineDelegate, { description: 'The delegate to call when this module is loaded (supporting a commmon module).' })); + const OnNewRequest = this.add(new Property('OnNewRequest', newRequestPipelineDelegate, { description: 'The delegate to call before each new request (supporting a commmon module).' })); + const GetParameterValue = this.add(new Property('GetParameterValue', getParameterDelegate, { description: 'The delegate to call to get parameter data from a common module.' })); + const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); + const ArgumentCompleter = this.add(new Property('ArgumentCompleter', argumentCompleterDelegate, { description: 'Gets completion data for azure specific fields' })); + const ProfileName = this.add(new Property('ProfileName', System.String, { description: 'The name of the currently selected Azure profile' })); + + const moduleIdentity = this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); + const currentProfile = this.add(new Field('Profile', dotnet.String, { initialValue: System.String.Empty, description: 'The currently selected profile.' })); + const moduleResourceId = this.add(new LambdaProperty('ResourceId', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The ResourceID for this module (azure arm).' })); + + /* get parameter method (calls azAccounts) */ + this.add(new LambdaMethod('GetParameter', dotnet.Object, new LiteralExpression(`${GetParameterValue.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value}, ${$this.pInvocationInfo.value}, ${$this.pCorrelationId.value},${$this.pParameterName.value} )`), { + parameters: [this.pInvocationInfo, this.pCorrelationId, this.pParameterName], + description: 'Gets parameters from a common module.', + returnsDescription: 'The parameter value from the common module. (Note: this should be type converted on the way back)' + })); + + /* signal method (calls azAccounts) */ + const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); + const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { + parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pCorrelationId, this.pProcessRecordId, this.pException], async: Modifier.Async, + description: 'Called to dispatch events to the common module listener', + returnsDescription: `A that will be complete when handling of the event is completed.` + })); + + signalImpl.push(Using('NoSynchronizationContext', '')); + signalImpl.add(function* () { + yield `await ${EventListener.value}?.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName}, ${$this.pCorrelationId},${$this.pProcessRecordId},${$this.pException});`; + }); + + /* init method */ + this.initMethod.add(function* () { + yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipeline.value}.Prepend(step); } , (step)=> { ${$this.fPipeline.value}.Append(step); } );`; + yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipelineWithProxy.value}.Prepend(step); } , (step)=> { ${$this.fPipelineWithProxy.value}.Append(step); } );`; + yield 'CustomInit();'; + }); + + this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { + parameters: [this.pInvocationInfo, this.pCorrelationId, this.pProcessRecordId, this.pParameterSetNameWithDefault], + description: 'Creates an instance of the HttpPipeline for each call.', + returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` + })); + + /* pipeline create method */ + this.createPipelineMethod.add(function* () { + const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); + yield pip.declarationStatement; + yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; + yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); + yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; + yield `pipeline.Append(new Runtime.CmdInfoHandler(${$this.pProcessRecordId}, ${$this.pInvocationInfo.use}, ${$this.pParameterSetName}).SendAsync);`; + yield `${OnNewRequest.value}?.Invoke( ${$this.pInvocationInfo.use}, ${$this.pCorrelationId},${$this.pProcessRecordId}, (step)=> { ${pip}.Prepend(step); } , (step)=> { ${pip}.Append(step); } );`; + yield Return(pip); + }); + } +} diff --git a/powershell/module/module-namespace.ts b/powershell/module/module-namespace.ts index cefbdae32de..6913ba6936b 100644 --- a/powershell/module/module-namespace.ts +++ b/powershell/module/module-namespace.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../llcsharp/exports'; -import { State } from '../internal/state'; -import { ModuleClass } from './module-class'; +import { State, NewState } from '../internal/state'; +import { ModuleClass, NewModuleClass } from './module-class'; import { DeepPartial } from '@azure-tools/codegen'; export class ModuleNamespace extends Namespace { @@ -23,4 +23,21 @@ export class ModuleNamespace extends Namespace { // module class this.moduleClass = new ModuleClass(this, state); } +} + +export class NewModuleNamespace extends Namespace { + public moduleClass: NewModuleClass; + + public get outputFolder(): string { + return this.state.project.moduleFolder; + } + + constructor(public state: NewState, objectInitializer?: DeepPartial) { + super(state.model.language.csharp?.namespace || 'INVALID.NAMESPACE', state.project); + this.apply(objectInitializer); + this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); + + // module class + this.moduleClass = new NewModuleClass(this, state); + } } \ No newline at end of file diff --git a/powershell/package.json b/powershell/package.json index 9cb887fd879..891838f6031 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -54,9 +54,11 @@ "eslint": "~6.2.2" }, "dependencies": { + "js-yaml": "3.13.1", "@azure-tools/codegen": "~2.1.0", "@azure-tools/codegen-csharp": "~3.0.0", "@azure-tools/codemodel-v3": "~3.1.0", + "@azure-tools/codemodel": "~4.13.327", "@azure-tools/autorest-extension-base": "~3.1.0", "@azure-tools/linq": "~3.1.0", "@azure-tools/tasks": "~3.0.0", diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts new file mode 100644 index 00000000000..34b14a091d3 --- /dev/null +++ b/powershell/plugins/create-commands-v2.ts @@ -0,0 +1,484 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +//import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; +import { JsonType, processCodeModel, codemodel, components, command, http, ModelState, Schema as SchemaV3 } from '@azure-tools/codemodel-v3'; +import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates, serialize } from '@azure-tools/codegen'; +import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; +import { Schema } from '../llcsharp/exports'; +import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { Lazy } from '@azure-tools/tasks'; +import { clone } from '@azure-tools/linq'; +import { verbs } from '../internal/verbs'; +import { PwshModel } from '../utils/PwshModel'; +import { IParameterPwsh } from '../utils/components'; +import { NewModelState } from '../utils/model-state'; + +type State = NewModelState; + + +// UNUSED: Moved to plugin-tweak-model.ts in remodeler +// For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. +export function titleToAzureServiceName(title: string): string { + const titleCamelCase = pascalCase(deconstruct(title)).trim(); + const serviceName = titleCamelCase + // Remove: !StartsWith(Management)AndContains(Management), Client, Azure, Microsoft, APIs, API, REST + .replace(/(?!^Management)(?=.*)Management|Client|Azure|Microsoft|APIs|API|REST/g, '') + // Remove: EndsWith(ServiceResourceProvider), EndsWith(ResourceProvider), EndsWith(DataPlane), EndsWith(Data) + .replace(/ServiceResourceProvider$|ResourceProvider$|DataPlane$|Data$/g, ''); + return serviceName || titleCamelCase; +} + + +const pluralizationService = new EnglishPluralizationService(); +pluralizationService.addWord('Database', 'Databases'); +pluralizationService.addWord('database', 'databases'); + + +interface CommandVariant { + alias: Array; + verb: string; + subject: string; + subjectPrefix: string; + variant: string; + action: string; +} + + +function fn(active: Array, remaining: Array, result: Array>): Array> { + if (length(active) || length(remaining)) { + if (length(remaining)) { + fn([...active, remaining[0]], remaining.slice(1), result); + fn(active, remaining.slice(1), result); + } else { + result.push(active); + } + } + return result; +} +function combinations(elements: Array) { + return fn([], elements, []); +} + +function splitOnPreposition(preposition: string, parts: Array) { + const i = parts.indexOf(preposition); + if (i > 0) { + return [ + parts.slice(0, i), + parts.slice(i + 1) + ]; + } + return undefined; +} + +function splitOnAnyPreposition(parts: Array) { + for (const p of ['with', 'at', 'by', 'for', 'in', 'of']) { + const result = splitOnPreposition(p, parts); + if (result && result[0].length > 0) { + // we found it, let's give it back. + return result; + } + } + return undefined; +} + + +export /* @internal */ class Inferrer { + commonParameters = new Array(); + verbMap!: { [operationIdMethod: string]: string }; + prefix!: string; + serviceName!: string; + subjectPrefix!: string; + isAzure!: boolean; + + constructor(private state: State) { + } + async init() { + this.commonParameters = await this.state.getValue('azure', false) ? [ + // 'resourceGroupName', + 'subscriptionId' + ] : []; + + this.verbMap = await this.state.getValue('verb-mapping') || {}; + this.isAzure = await this.state.getValue('azure', false); + this.prefix = await this.state.getValue('prefix'); + this.serviceName = titleToAzureServiceName(await this.state.getValue('service-name')); + this.state.setValue('service-name', this.serviceName); + + this.subjectPrefix = await this.state.getValue('subject-prefix'); + + this.state.setValue('isAzure', this.isAzure); + this.state.setValue('prefix', this.prefix); + + const model = this.state.model; + + this.state.message({ + Channel: Channel.Debug, Text: `[CMDLET-PREFIX] => '${model.language.default.prefix}'` + }); + + model.language.default.serviceName = this.serviceName; + this.state.message({ + Channel: Channel.Debug, Text: `[SERVICE-NAME] => '${model.language.default.serviceName}'` + }); + + model.language.default.subjectPrefix = this.subjectPrefix; + this.state.message({ + Channel: Channel.Debug, Text: `[SUBJECT-PREFIX] => '${model.language.default.subjectPrefix}'` + }); + + return this; + } + + async createCommands() { + const model = this.state.model; + this.state.model.commands = { + operations: new Dictionary(), + parameters: new Dictionary(), + }; + + this.state.message({ Channel: Channel.Debug, Text: 'detecting high level commands...' }); + for (const operationGroup of values(model.operationGroups)) { + for (const operation of values(operationGroup.operations)) { + for (const variant of await this.inferCommandNames(operation, operationGroup.$key, this.state)) { + await this.addVariants(operation.parameters, operation, variant, '', this.state); + } + } + } + // for (const operation of values(model.http.operations)) { + // for (const variant of await this.inferCommandNames(operation, this.state)) { + // // no common parameters (standard variations) + // await this.addVariants(operation.parameters, operation, variant, '', this.state); + // } + // } + return model; + } + + inferCommand(operation: Array, group: string, suffix: Array = []): Array { + operation = operation.filter(each => each !== 'all'); + // no instant match + switch (length(operation)) { + case 0: + throw new Error('Missing operation id?'); + + case 1: + // simple operation, just an id with a single value + // OPERATION => OPERATION-GROUP + return [ + this.createCommandVariant(operation[0], deconstruct(group), suffix, this.state.model) + ]; + + case 2: + // should try to infer [SUBJECT] and [ACTION] from operation + if (verbs.has(operation[0])) { + // [ACTION][SUBJECT] + return [ + this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) + ]; + } + if (verbs.has(operation[1])) { + // [SUBJECT][ACTION] + return [ + this.createCommandVariant(operation[1], [...deconstruct(group), operation[0]], suffix, this.state.model) + ]; + + } + // can't tell which is the [ACTION] -- let's return it the way we used to, + // but now let's mention that we are doing that. + this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); + return [ + this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) + ]; + + } + // three or more words. + // first, see if it's an 'or' + const either = splitOnPreposition('or', operation); + if (either) { + // looks like we got two sets of operations from this. + return [ + ...this.inferCommand([...either[0], ...either[1].slice(1)], group, suffix), + ...this.inferCommand(either[1], group, suffix), + ]; + } + + // any other preposition? + const parts = splitOnAnyPreposition(operation); + if (parts) { + // so this is something like DoActionWithStyle + return [...this.inferCommand(parts[0], group, parts[1])]; + } + + // if not, then seek out a verb from there. + for (let i = 0; i < length(operation); i++) { + if (verbs.has(operation[i])) { + // if the action is first + if (i === 0) { + // everything else is the subject + return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i + 1)] : operation.slice(i + 1), suffix, this.state.model)]; + } + if (i === length(operation) - 1) { + // if it's last, the subject would be the first thing + return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(0, i)] : operation.slice(0, i), suffix, this.state.model)]; + } + + // otherwise + // things before are part of the subject + // things after the verb should be part of the suffix + return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i, i)] : operation.slice(i, i), [...suffix, ...operation.slice(i + 1)], this.state.model)]; + } + } + + // so couldn't tell what the action was. + // fallback to the original behavior with a warning. + this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); + return [this.createCommandVariant(operation[0], group ? [...deconstruct(group), ...operation.slice(1)] : operation.slice(1), [...suffix, ...operation.slice(1)], this.state.model)]; + } + + async inferCommandNames(op: Operation, group: string, state: State): Promise> { + + const method = op.language.default.name; + // skip-for-time-being + // if (!method) { + // if (!group) { + // // no operation id at all? + // const path = op.path.replace(/{.*?}/g, '').replace(/\/+/g, '/').replace(/\/$/g, ''); + // method = path.split('/').last; + // } else { + // // no group given, use string as method + // method = group; + // } + // group = pascalCase(op.tags) || ''; + + // } + + const groupWords = deconstruct(group); + groupWords[groupWords.length - 1] = pluralizationService.singularize(groupWords.last); + + group = pascalCase(groupWords); + const operation = deconstruct(method); + + // instant match + if (this.verbMap[method]) { + return [this.createCommandVariant(method, [group], [], state.model)]; + } + + // dig deeper. + return this.inferCommand(operation, group); + } + + async addVariant(vname: string, body: Parameter | null, bodyParameterName: string, parameters: Array, operation: Operation, variant: CommandVariant, state: State) { + const op = await this.addCommandOperation(vname, parameters, operation, variant, state); + + // if this has a body with it, let's add that parameter + if (body && body.schema) { + op.details.default.hasBody = true; + op.parameters.push(new IParameterPwsh(bodyParameterName, new SchemaV3('not used'), body.schema, { + details: { + default: { + description: body.schema.language.default.description, + name: pascalCase(bodyParameterName), + isBodyParameter: true, + } + } + })); + + // let's add a variant where it's expanded out. + // *IF* the body is an object + if (body.schema.type === SchemaType.Object) { + const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); + opExpanded.details.default.dropBodyParameter = true; + opExpanded.parameters.push(new IParameterPwsh(`${bodyParameterName}Body`, new SchemaV3('not used'), body.schema, { + details: { + default: { + description: body.schema.language.default.description, + name: pascalCase(`${bodyParameterName}Body`), + isBodyParameter: true, + } + } + })); + } + } + } + + + isNameConflict(model: codemodel.Model, variant: CommandVariant, vname: string) { + for (const each of values(model.commands.operations)) { + if (each.details.default.name === vname) { + return true; + } + } + return false; + } + + // for tracking unique operation identities + operationIdentities = new Set(); + + async addCommandOperation(vname: string, parameters: Array, operation: Operation, variant: CommandVariant, state: State): Promise { + // skip-for-time-being following code seems redundant ----- + // let apiversion = ''; + + // for (const each of items(operation.responses)) { + // for (const rsp of items(each)) { + // if (rsp.schema && rsp.schema.details && rsp.schema.details.default && rsp.schema.details.default.apiversion) { + // apiversion = rsp.schema.details.default.apiversion; + // break; + // } + // } + // } + // ---------------------------------------------------------- + + // if vname is > 64 characters, let's trim it + // after trimming it, make sure there aren't any other operation with a name that's exactly the same + if (length(vname) > 64) { + const names = deconstruct(vname); + let newVName = ''; + for (let i = 0; i < length(names); i++) { + newVName = pascalCase(names.slice(0, i)); + if (length(newVName) > 60) { + break; + } + } + vname = newVName; + } + + // if we have an identical vname, let's add 'etc' + let fname = `${variant.verb}-${variant.subject}-${vname}`; + let n = 1; + while (this.operationIdentities.has(fname)) { + vname = `${vname.replace(/\d*$/g, '')}${n++}`; + fname = `${variant.verb}-${variant.subject}-${vname}`; + } + this.operationIdentities.add(fname); + + variant.variant = vname; + vname = pascalCase(vname); + // skip-for-time-being x-ms-metadata looks not supported any more. + //const xmsMetadata = operation.pathExtensions ? operation.pathExtensions['x-ms-metadata'] ? clone(operation.pathExtensions['x-ms-metadata']) : {} : {}; + + return state.model.commands.operations[`${length(state.model.commands.operations)}`] = new command.CommandOperation(operation.language.default.name, { + asjob: operation.language.default.asjob ? true : false, + extensions: { + + }, + ...variant, + details: { + ...operation.language, + default: { + ...operation.language.default, + subject: variant.subject, + subjectPrefix: variant.subjectPrefix, + verb: variant.verb, + name: vname, + alias: variant.alias + } + }, + // operationId is not needed any more + operationId: '', + parameters: parameters.map(httpParameter => { + // make it's own copy of the parameter since after this, + // the parameter can be altered for each operation individually. + const each = clone(httpParameter, false, undefined, undefined, ['schema', 'origin']); + each.language.default = { + ...each.language.default, + name: pascalCase(each.language.default.name), + httpParameter + }; + each.details = {}; + each.details.default = { + ...each.language.default, + name: pascalCase(each.language.default.name), + httpParameter + }; + return each; + }), + // skip-for-time-being, this callGraph is used in the header comments + callGraph: [], + }); + } + + async addVariants(parameters: Array | undefined, operation: Operation, variant: CommandVariant, vname: string, state: State) { + // now synthesize parameter set variants multiplexed by the variants. + const [constants, requiredParameters] = values(parameters).bifurcate(parameter => parameter.language.default.constantValue || parameter.language.default.fromHost ? true : false); + const constantParameters = constants.map(each => `'${each.language.default.constantValue}'`); + + // the body parameter + const body = (operation.requests && operation.requests[0].parameters) ? operation.requests[0].parameters[0] : null; + // skip-for-time-being, looks x-ms-requestBody-name is not supported any more + //const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : ''; + const bodyParameterName = body ? 'bodyParameter' : ''; + + // all the properties in the body parameter + const bodyProperties = (body && body.schema && isObjectSchema(body.schema)) ? values(getAllProperties(body.schema)).where(property => !property.language.default.readOnly).toArray() : []; + + // smash body property names together + const bodyPropertyNames = bodyProperties.joinWith(each => each.language.default.name); + + // for each polymorphic body, we should do a separate variant that takes the polymorphic body type instead of the base type + // skip-for-time-being, this is for polymorphism + //const polymorphicBodies = (body && body.schema && body.schema.details.default.polymorphicChildren && length(body.schema.details.default.polymorphicChildren)) ? (>body.schema.details.default.polymorphicChildren).joinWith(child => child.details.default.name) : ''; + + // wait! "update" should be "set" if it's a POST + if (variant.verb === 'Update' && operation.requests && operation.requests[0].protocol?.http?.method === http.HttpMethod.Put) { + variant.verb = 'Set'; + } + + // create variant + // skip-for-time-being, since operationId looks not included in m4. + //state.message({ Channel: Channel.Debug, Text: `${variant.verb}-${variant.subject} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${bodyPropertyNames} ${polymorphicBodies ? `; Polymorphic bodies: ${polymorphicBodies} ` : ''}` }); + await this.addVariant(pascalCase([variant.action, vname]), body, bodyParameterName, [...constants, ...requiredParameters], operation, variant, state); + + const [pathParams, otherParams] = values(requiredParameters).bifurcate(each => each?.protocol?.http?.in === ParameterLocation.Path); + const dvi = await state.getValue('disable-via-identity', false); + + if (!dvi && length(pathParams) > 0 && variant.action.toLowerCase() != 'list') { + // we have an operation that has path parameters, a good canididate for piping for identity. + await this.addVariant(pascalCase([variant.action, vname, 'via-identity']), body, bodyParameterName, [...constants, ...otherParams], operation, variant, state); + } + + } + + createCommandVariant(action: string, subject: Array, variant: Array, model: PwshModel): CommandVariant { + const verb = this.getPowerShellVerb(action); + if (verb === 'Invoke') { + // if the 'operation' name was "post" -- it's kindof redundant. + // so, only include the operation name in the group name if it's anything else + if (action.toLowerCase() !== 'post') { + subject = [action, ...subject]; + } + } + + return { + alias: [], + subject: pascalCase([...removeSequentialDuplicates(subject.map(each => pluralizationService.singularize(each)))]), + variant: pascalCase(variant), + verb, + subjectPrefix: model.language.default.subjectPrefix, + action + }; + } + + getPowerShellVerb(action: string): string { + const verb = this.verbMap[pascalCase(action)]; + if (verb) { + return verb; + } else { + return 'Invoke'; + } + } +} + + +export async function createCommandsV2(service: Host) { + // return processCodeModel(commandCreator, service); + //const session = await startSession(service, {}, codeModelSchema); + //const result = tweakModelV2(session); + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-createcommands-v2.yaml', serialize(await (await new Inferrer(state).init()).createCommands()), undefined, 'code-model-v4'); + + // return processCodeModel(async (state) => { + // return await (await new Inferrer(state).init()).createCommands(); + // }, service, 'createCommands-v2'); +} \ No newline at end of file diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts new file mode 100644 index 00000000000..484e8d7f727 --- /dev/null +++ b/powershell/plugins/cs-namer-v2.ts @@ -0,0 +1,257 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +//import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; +import { ModelState } from '@azure-tools/codemodel-v3'; +import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen'; +import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; +import { System } from '@azure-tools/codegen-csharp'; + +import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { SchemaDetails } from '../llcsharp/code-model'; +import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; + +type State = NewModelState; + + +function setPropertyNames(schema: Schema) { + // name each property in this schema + // skip-for-time-being + // for (const propertySchema of values(schema.properties)) { + // const propertyDetails = propertySchema.details.default; + + // const className = schema.details.csharp.name; + + // let pname = getPascalIdentifier(propertyDetails.name); + // if (pname === className) { + // pname = `${pname}Property`; + // } + + // if (pname === 'default') { + // pname = '@default'; + // } + + // propertySchema.details.csharp = { + // ...propertyDetails, + // name: pname // and so are the propertyNmaes + // }; + + // if (propertyDetails.isNamedStream) { + // propertySchema.details.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); + // } + // } + +} + + +function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, serviceNamespace: string) { + const baseNamespace = new Set(); + const subNamespace = new Map>(); + // dolauli need to notice this -- schemas in the namespace of the lowest supported api version + // in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion. + // otherwise, we just want to differientiate with a simple incremental numbering scheme. + + for (const group of values(schemaGroups)) { + for (const schema of group) { + let thisNamespace = baseNamespace; + let thisApiversion = ''; + + // create the namespace if required + if (azure) { + const metadata = schema.extensions && schema.extensions['x-ms-metadata']; + if (metadata) { + const apiVersions = | undefined>metadata.apiVersions; + if (apiVersions && length(apiVersions) > 0) { + thisApiversion = minimum(apiVersions); + thisNamespace = subNamespace.get(thisApiversion) || new Set(); + subNamespace.set(thisApiversion, thisNamespace); + } + } + } + + // for each schema, we're going to set the name + // to the suggested name, unless we have collisions + // at which point, we're going to add a number (for now?) + const details = schema.language.default; + let schemaName = getPascalIdentifier(details.name); + const apiName = (!thisApiversion) ? '' : getPascalIdentifier(`Api ${thisApiversion}`); + const ns = (!thisApiversion) ? [] : ['.', apiName]; + + + let n = 1; + while (thisNamespace.has(schemaName)) { + schemaName = getPascalIdentifier(`${details.name}_${n++}`); + } + thisNamespace.add(schemaName); + + // object types. + if (schema.type === SchemaType.Object) { + schema.language.csharp = { + ...details, + apiversion: thisApiversion, + apiname: apiName, + interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), // objects have an interfaceName + internalInterfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal'])), // objects have an ineternal interfaceName for setting private members. + fullInternalInterfaceName: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal']))}`, + name: getPascalIdentifier(schemaName), + namespace: pascalCase([serviceNamespace, '.', 'Models', ...ns]), // objects have a namespace + fullname: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${getPascalIdentifier(schemaName)}`, + }; + } else if (schema.type === SchemaType.String && schema.language.default.enum) { + // oh, it's an enum type + // Skip for time-being + // schema.language.csharp = { + // ...details, + // interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), + // name: getPascalIdentifier(schema.language.default.enum.name), + // namespace: pascalCase([serviceNamespace, '.', 'Support']), + // fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schema.language.default.enum.name)}`, + // enum: { + // ...schema.language.default.enum, + // name: getPascalIdentifier(schema.language.default.enum.name), + // values: schema.language.default.enum.values.map(each => { + // return { + // ...each, + // name: getPascalIdentifier(each.name), + // description: each.description + // }; + // }) + // } + // }; + } else { + schema.language.csharp = { + ...details, + interfaceName: '', + internalInterfaceName: '', + name: schemaName, + namespace: '', + fullname: '' + }; + } + + // name each property in this schema + setPropertyNames(schema); + + // fix enum names + // skip-for-time-being + // if (schema.details.default.enum) { + // schema.details.csharp.enum = { + // ...schema.details.default.enum, + // name: getPascalIdentifier(schema.details.default.enum.name) + // }; + + // // and the value names themselves + // for (const value of values(schema.details.csharp.enum.values)) { + // value.name = getPascalIdentifier(value.name); + // } + // } + } + } + +} + +async function setOperationNames(state: State, resolver: NewSchemaDefinitionResolver) { + // keep a list of operation names that we've assigned. + const operationNames = new Set(); + for (const operationGroup of values(state.model.operationGroups)) { + for (const operation of values(operationGroup.operations)) { + const details = operation.language.default; + + // come up with a name + const oName = getPascalIdentifier(details.name); + let i = 1; + let operationName = oName; + while (operationNames.has(operationName)) { + // if we have used that name, try again. + operationName = `${oName}${i++}`; + } + operationNames.add(operationName); + + operation.language.csharp = { + ...details, // inherit + name: operationGroup.language.default.name + operationName, + }; + + // parameters are camelCased. + for (const parameter of values(operation.parameters)) { + const parameterDetails = parameter.language.default; + + let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name))); + + if (propName === 'default') { + propName = '@default'; + } + + parameter.language.csharp = { + ...parameterDetails, + name: propName + }; + } + + for (const rsp of values(operation.responses)) { + // per responseCode + const response = rsp; + const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state) : undefined; + // const headerTypeDefinition = response.headerSchema ? resolver.resolveTypeDeclaration(response.headerSchema, true, state.path('schemas', response.headerSchema.details.default.name)) : undefined; + let code = (System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]] ? System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]].value : response.protocol.http?.statusCodes[0]).replace('global::System.Net.HttpStatusCode', ''); + let rawValue = code.replace(/\./, ''); + if (response.protocol.http?.statusCodes[0] === 'default' || rawValue === 'default' || '') { + rawValue = 'any response code not handled elsewhere'; + code = 'default'; + } + response.language.csharp = { + ...response.language.default, + responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '', + headerType: '', + name: (length(response.protocol.http?.mimeTypes) <= 1) ? + camelCase(fixLeadingNumber(deconstruct(`on ${code}`))) : // the common type (or the only one.) + camelCase(fixLeadingNumber(deconstruct(`on ${code} ${response.protocol.http?.mimeTypes[0]}`))), + description: (length(response.protocol.http?.mimeTypes) <= 1) ? + `a delegate that is called when the remote service returns ${response.protocol.http?.statusCodes[0]} (${rawValue}).` : + `a delegate that is called when the remote service returns ${response.protocol.http?.statusCodes[0]} (${rawValue}) with a Content-Type matching ${response.protocol.http?.mimeTypes.join(',')}.` + + }; + } + } + } +} + +async function nameStuffRight(state: State): Promise { + const resolver = new NewSchemaDefinitionResolver(); + const model = state.model; + + // set the namespace for the service + const serviceNamespace = await state.getValue('namespace', 'Sample.API'); + const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false); + const clientName = getPascalIdentifier(model.language.default.name); + + // dolauli see model.details.csharp for c# related staff + // set c# client details (name) + model.language.csharp = { + ...model.language.default, // copy everything by default + name: clientName, + namespace: serviceNamespace, + fullname: `${serviceNamespace}.${clientName}` + }; + + setSchemaNames(>>model.schemas, azure, serviceNamespace); + await setOperationNames(state, resolver); + + return model; +} + + +export async function csnamerV2(service: Host) { + // dolauli add names for http operations and schemas + //return processCodeModel(nameStuffRight, service, 'csnamer'); + //const session = await startSession(service, {}, codeModelSchema); + //const result = tweakModelV2(session); + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-csnamer-v2.yaml', serialize(await nameStuffRight(state)), undefined, 'code-model-v4'); +} + diff --git a/powershell/plugins/cs-namer.ts b/powershell/plugins/cs-namer.ts index dca4d054ff5..4cf798a7899 100644 --- a/powershell/plugins/cs-namer.ts +++ b/powershell/plugins/cs-namer.ts @@ -48,7 +48,7 @@ function setPropertyNames(schema: Schema) { function setSchemaNames(schemas: Dictionary, azure: boolean, serviceNamespace: string) { const baseNamespace = new Set(); const subNamespace = new Map>(); - + // dolauli need to notice this -- schemas in the namespace of the lowest supported api version // in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion. // otherwise, we just want to differientiate with a simple incremental numbering scheme. @@ -222,6 +222,7 @@ async function nameStuffRight(state: State): Promise { const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false); const clientName = getPascalIdentifier(model.details.default.name); + // dolauli see model.details.csharp for c# related staff // set c# client details (name) model.details.csharp = { ...model.details.default, // copy everything by default @@ -238,6 +239,7 @@ async function nameStuffRight(state: State): Promise { export async function csnamer(service: Host) { + // dolauli add names for http operations and schemas return processCodeModel(nameStuffRight, service, 'csnamer'); } diff --git a/powershell/plugins/llcsharp-v2.ts b/powershell/plugins/llcsharp-v2.ts new file mode 100644 index 00000000000..802f820fc78 --- /dev/null +++ b/powershell/plugins/llcsharp-v2.ts @@ -0,0 +1,78 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { Host, startSession } from '@azure-tools/autorest-extension-base'; +import { codeModelSchema } from '@azure-tools/codemodel'; +import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; +import { join } from 'path'; +import { Model } from '../llcsharp/code-model'; +import { State } from '../llcsharp/generator'; +import { Project, NewProject } from '../llcsharp/project'; +import { PwshModel } from '../utils/PwshModel'; + +const resources = `${__dirname}/../../resources`; + +export async function llcsharpV2(service: Host) { + try { + const project = await new NewProject(service).init(); + + await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); + + // recursive copy resources + await copyResources(join(resources, 'runtime', 'csharp', 'client'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); + await copyResources(join(resources, 'runtime', 'csharp', 'pipeline'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); + // Note: + // we are using the Carbon.Json library, but we don't *really* want to expose that as public members where we don't have to + // and I don't want to make code changes in the source repository, so I can keep merging from upstream as simple as possible. + // so, we're converting as much as possible to internal, and exposing only what must be exposed to make the code compile. + + await copyResources(join(resources, 'runtime', 'csharp', 'json'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), { + ...project.overrides, + 'public': 'internal', + 'internal (.*) class JsonNumber': 'public $1 class JsonNumber', + 'internal (.*) class JsonObject': 'public $1 class JsonObject', + 'internal (.*) class JsonNode': 'public $1 class JsonNode', + 'internal (.*) class JsonString': 'public $1 class JsonString', + 'internal (.*) class XNodeArray': 'public $1 class XNodeArray', + 'internal (.*) class JsonArray': 'public $1 class JsonArray', + 'internal(.*) class JsonTokenizer': 'public$1 class JsonTokenizer', + 'internal(.*) class JsonParser': 'public$1 class JsonParser', + 'internal(.*) class TokenReader': 'public$1 class TokenReader', + 'internal(.*) class SourceReader': 'public$1 class SourceReader', + 'internal(.*) class (.*)Converter': 'public$1 class $2Converter', + 'internal(.*) interface IJsonSerializable': 'public$1 interface IJsonSerializable', + 'internal override string ToString': 'public override string ToString', + 'internal void Add\\(': 'public void Add(', + 'internal bool ContainsKey\\(': 'public bool ContainsKey(', + 'internal bool Remove\\(': 'public bool Remove(', + 'internal bool TryGetValue\\(': 'public bool TryGetValue(', + 'internal (.*) JsonNode this\\[': 'public $1 JsonNode this[', + + 'internal ICollection Values': 'public ICollection Values', + 'internal ICollection Keys': 'public ICollection Keys', + 'internal bool IsReadOnly': 'public bool IsReadOnly', + 'internal (.*) int Count': 'public $1 int Count', + 'internal bool Contains\\(': 'public bool Contains(', + 'internal(.*) bool Equals': 'public$1 bool Equals', + 'internal (.*) int GetHashCode': 'public $1 int GetHashCode', + 'internal void Dispose': 'public void Dispose', + 'internal (.*) operator': 'public $1 operator', + 'internal object FromJson\\(': 'public object FromJson(', + 'internal JsonNode ToJson\\(': 'public JsonNode ToJson(', + + }); + + if (project.xmlSerialization) { + await copyResources(join(resources, 'runtime', 'csharp', 'xml'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); + } + + if (project.azure) { + await copyResources(join(resources, 'runtime', 'csharp.azure'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); + } + + } catch (E) { + console.error(`${__filename} - ${E.stack}/${E.message}`); + throw E; + } +} diff --git a/powershell/plugins/modifiers.ts b/powershell/plugins/modifiers.ts index c929386a67d..e6928d1e7f3 100644 --- a/powershell/plugins/modifiers.ts +++ b/powershell/plugins/modifiers.ts @@ -232,6 +232,7 @@ function isWhereEnumDirective(it: any): it is WhereEnumDirective { async function tweakModel(state: State): Promise { // only look at directives without the `transform` node. + // dolauli for directives with transform are implemented in autorest core for (const directive of directives.filter(each => !each.transform)) { const getPatternToMatch = (selector: string | undefined): RegExp | undefined => { return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined; @@ -689,6 +690,7 @@ async function tweakModel(state: State): Promise { } export async function applyModifiers(service: Host) { + // dolauli implement directives const allDirectives = await service.GetValue('directive'); directives = values(allDirectives) // .select(directive => directive) diff --git a/powershell/plugins/onbaordpipeline.md b/powershell/plugins/onbaordpipeline.md new file mode 100644 index 00000000000..2624fd75fa9 --- /dev/null +++ b/powershell/plugins/onbaordpipeline.md @@ -0,0 +1,39 @@ +There are three key steps for on-boarding a new RP with AutoRest PowerShell Generator. +- Onboard request +- Design review +- PR review + +## Onboard Request +The first step is to send an onboard request to Azure PowerShell PM Damien(). And you are expected to provide information as below(maybe more). +- RP status +- Roadmap +- Contact person for customer support + +Damien will assist you to work out a speclet for your RP, which is something like combination of use-case spec and function spec. + +## Design Review +Based on the speclet, you may start to generate code. Detailed steps are below. + +- Generate code with PowerShell generator +- Customize code based on the speclet +- Write examples + +When all above steps are completed, you may file a ticket in https://github.com/Azure/azure-powershell-cmdlet-review-pr/issues for design review. +The issue should contain content below. +- Link to the speclet +- Cmdlets syntax and examples (you may copy and paste them from the ./docs folder) +- A link to the code repo which contains the docs folder + +The issue will be assigned to an engineer in Azure PowerShell team for review. If the RP is complex, a review meeting will be needed, otherwise, review may be done through comments in the ticket/emails. + +## Code Review +When design review is ongoing, you may write the test cases. After design review passes, you may file a PR against the generation branch of azure-powershell for code review. And code list is as following. +- readme.md +- custom +- examples +- test +- docs + +After code review, congratulaitions, you got the chance to take the release train, which is once every three week. + + diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts new file mode 100644 index 00000000000..e64e184a206 --- /dev/null +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -0,0 +1,399 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { Schema, codemodel, JsonType, processCodeModel, VirtualProperty, VirtualParameter, resolveParameterNames, ModelState, getAllProperties, getAllPublicVirtualProperties } from '@azure-tools/codemodel-v3'; +import { getPascalIdentifier, removeSequentialDuplicates, pascalCase, fixLeadingNumber, deconstruct, selectName, EnglishPluralizationService, serialize } from '@azure-tools/codegen'; +import { length, values, } from '@azure-tools/linq'; +import { Host, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; + + +function getPluralizationService(): EnglishPluralizationService { + const result = new EnglishPluralizationService(); + result.addWord('Database', 'Databases'); + result.addWord('database', 'databases'); + return result; +} + +type State = NewModelState; + +export function singularize(word: string): string { + return getPluralizationService().singularize(word); +} + +function getNameOptions(typeName: string, components: Array) { + const result = new Set(); + + // add a variant for each incrementally inclusive parent naming scheme. + for (let i = 0; i < length(components); i++) { + const subset = pascalCase([...removeSequentialDuplicates(components.slice(-1 * i, length(components)))]); + result.add(subset); + } + + // add a second-to-last-ditch option as . + result.add(pascalCase([...removeSequentialDuplicates([...fixLeadingNumber(deconstruct(typeName)), ...deconstruct(components.last)])])); + return [...result.values()]; +} + + +// function createVirtualProperties(schema: Schema, stack: Array, threshold: number, conflicts: Array) { +// // dolauli +// // owned: all properties(obj & nonobj) in the schema, +// // inherited: Properties from parents, +// // inlined: for obj properties, flatten them to children, +// // did we already inline this object +// if (schema.details.default.inline === 'yes') { +// return true; +// } + +// if (schema.details.default.inline === 'no') { +// return false; +// } + +// // this is bad. This would happen when we have a circular reference in the tree. +// // dolauli curious in which case this will happen, got it to use no-inline to skip inline and avoid circular reference +// if (schema.details.default.inline === 'inprogress') { +// let text = (`Note: during processing of '${schema.details.default.name}' a circular reference has been discovered.`); +// text += '\n In order to proceed, you must add a directive to indicate which model you want to not inline.\n'; +// text += '\ndirective:'; +// text += '\n- no-inline: # choose ONE of these models to disable inlining'; +// for (const each of stack) { +// text += (`\n - ${each} `); +// } +// text += '\n'; +// conflicts.push(text); +// /* `directive: +// - no-inline: +// - MyModel +// - YourModel +// - HerModel +// ` */ + +// // `, and we're skipping inlining.\n ${stack.join(' => ')}`); +// // mark it as 'not-inlining' +// schema.details.default.inline = 'no'; +// return false; +// } + +// // ok, set to in progress now. +// schema.details.default.inline = 'inprogress'; + +// // virutual property set. +// const virtualProperties = schema.details.default.virtualProperties = { +// owned: new Array(), +// inherited: new Array(), +// inlined: new Array(), +// }; + +// // First we should run thru the properties in parent classes and create inliners for each property they have. +// // dolauli handle properties in parents +// for (const parentSchema of values(schema.allOf)) { +// // make sure that the parent is done. +// createVirtualProperties(parentSchema, [...stack, `${schema.details.default.name}`], threshold, conflicts); + +// const parentProperties = parentSchema.details.default.virtualProperties || { +// owned: [], +// inherited: [], +// inlined: [], +// }; + +// // now we go thru the parent's virutal properties and create our own copies +// for (const virtualProperty of [...parentProperties.inherited, ...parentProperties.inlined, ...parentProperties.owned]) { +// // make sure that we have a list of shared owners of this property. +// virtualProperty.sharedWith = virtualProperty.sharedWith || [virtualProperty]; + +// // we are just copying over theirs to ours. +// const inheritedProperty = { +// name: virtualProperty.name, +// property: virtualProperty.property, +// private: virtualProperty.private, +// nameComponents: virtualProperty.nameComponents, +// nameOptions: virtualProperty.nameOptions, +// accessViaProperty: virtualProperty, +// accessViaMember: virtualProperty, +// accessViaSchema: parentSchema, +// originalContainingSchema: virtualProperty.originalContainingSchema, +// description: virtualProperty.description, +// alias: [], +// required: virtualProperty.required || !!values(schema.required).first(each => !!each && !!each.toLowerCase && each.toLowerCase() === virtualProperty.property.details.default.name.toLowerCase()), +// sharedWith: virtualProperty.sharedWith, +// }; +// // add it to the list of virtual properties that share this property. +// virtualProperty.sharedWith.push(inheritedProperty); + +// // add it to this class. +// virtualProperties.inherited.push(inheritedProperty); +// } +// } + +// // dolauli figure out object properties and non object properties in this class +// const [objectProperties, nonObjectProperties] = values(schema.properties).bifurcate(each => +// !schema.details.default['skip-inline'] && // if this schema is marked skip-inline, none can be inlined, treat them all as straight properties. +// !each.schema.details.default['skip-inline'] && // if the property schema is marked skip-inline, then it should not be processed either. +// each.schema.type === JsonType.Object && // is it an object +// getAllProperties(each.schema).length > 0 // does it have properties (or inherit properties) +// ); + +// // run thru the properties in this class. +// // dolauli handle properties in this class +// for (const property of objectProperties) { +// const propertyName = property.details.default.name; + +// // for each object member, make sure that it's inlined it's children that it can. +// createVirtualProperties(property.schema, [...stack, `${schema.details.default.name}`], threshold, conflicts); + +// // this happens if there is a circular reference. +// // this means that this class should not attempt any inlining of that property at all . +// // dolauli pay attention to the condition check +// const canInline = +// // (!property.schema.details.default['skip-inline']) && +// (!property.schema.details.default.byReference) && +// (!property.schema.additionalProperties) && +// property.schema.details.default.inline === 'yes'; + +// // the target has properties that we can inline +// const virtualChildProperties = property.schema.details.default.virtualProperties || { +// owned: [], +// inherited: [], +// inlined: [], +// }; + +// const allNotRequired = values(getAllPublicVirtualProperties()).all(each => !each.property.details.default.required); + +// const childCount = length(virtualChildProperties.owned) + length(virtualChildProperties.inherited) + length(virtualChildProperties.inlined); +// if (canInline && (property.details.default.required || allNotRequired) && (childCount < threshold || propertyName === 'properties')) { + + +// // if the child property is low enough (or it's 'properties'), let's create virtual properties for each one. +// // create a private property for the inlined ones to use. +// const privateProperty = { +// name: getPascalIdentifier(propertyName), +// propertySchema: schema, +// property, +// nameComponents: [getPascalIdentifier(propertyName)], +// nameOptions: getNameOptions(schema.details.default.name, [propertyName]), +// private: true, +// description: property.description || '', +// originalContainingSchema: schema, +// alias: [], +// required: property.details.default.required, +// }; +// virtualProperties.owned.push(privateProperty); + +// for (const inlinedProperty of [...virtualChildProperties.inherited, ...virtualChildProperties.owned]) { +// // child properties are be inlined without prefixing the name with the property name +// // unless there is a collision, in which case, we have to resolve + +// // (scan back from the far right) +// // deeper child properties should be inlined with their parent's name +// // ie, this.[properties].owner.name should be this.ownerName + +// const proposedName = getPascalIdentifier(`${propertyName === 'properties' || /*objectProperties.length === 1*/ propertyName === 'error' ? '' : pascalCase(fixLeadingNumber(deconstruct(propertyName)).map(each => singularize(each)))} ${inlinedProperty.name}`); + +// const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; +// virtualProperties.inlined.push({ +// name: proposedName, +// property: inlinedProperty.property, +// private: inlinedProperty.private, +// nameComponents: components, +// nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), +// accessViaProperty: privateProperty, +// accessViaMember: inlinedProperty, +// accessViaSchema: schema, +// originalContainingSchema: schema, +// description: inlinedProperty.description, +// alias: [], +// required: inlinedProperty.required && privateProperty.required, +// }); +// } + + +// for (const inlinedProperty of [...virtualChildProperties.inlined]) { +// // child properties are be inlined without prefixing the name with the property name +// // unless there is a collision, in which case, we have to resolve + +// // (scan back from the far right) +// // deeper child properties should be inlined with their parent's name +// // ie, this.[properties].owner.name should be this.ownerName + + +// const proposedName = getPascalIdentifier(inlinedProperty.name); +// const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; +// virtualProperties.inlined.push({ +// name: proposedName, +// property: inlinedProperty.property, +// private: inlinedProperty.private, +// nameComponents: components, +// nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), +// accessViaProperty: privateProperty, +// accessViaMember: inlinedProperty, +// accessViaSchema: schema, +// originalContainingSchema: schema, +// description: inlinedProperty.description, +// alias: [], +// required: inlinedProperty.required && privateProperty.required +// }); +// } +// } else { +// // otherwise, we're not below the threshold, and we should treat this as a non-inlined property +// nonObjectProperties.push(property); +// } +// } + +// for (const property of nonObjectProperties) { +// const name = getPascalIdentifier(property.details.default.name); +// // this is not something that has properties, +// // so we don't need to do any inlining +// // however, we can add it to our list of virtual properties +// // so that our consumers can get it. +// virtualProperties.owned.push({ +// name, +// property, +// nameComponents: [name], +// nameOptions: [name], +// description: property.description || '', +// originalContainingSchema: schema, +// alias: [], +// required: property.details.default.required +// }); +// } + +// // resolve name collisions. +// const allProps = [...virtualProperties.owned, ...virtualProperties.inherited, ...virtualProperties.inlined]; +// const inlined = new Map(); + +// for (const each of allProps) { +// // track number of instances of a given name. +// inlined.set(each.name, (inlined.get(each.name) || 0) + 1); +// } + +// const usedNames = new Set(inlined.keys()); +// for (const each of virtualProperties.inlined.sort((a, b) => length(a.nameOptions) - length(b.nameOptions))) { +// const ct = inlined.get(each.name); +// if (ct && ct > 1) { +// // console.error(`Fixing collision on name ${each.name} #${ct} `); +// each.name = selectName(each.nameOptions, usedNames); +// } +// } +// schema.details.default.inline = 'yes'; +// return true; +// } + +function createVirtualParameters(operation: CommandOperation) { + // dolauli expand body parameter + // for virtual parameters, there are two keys, operation and body + const virtualParameters = { + operation: new Array(), + body: new Array() + }; + + /// const dropBodyParameter = !!operation.details.default.dropBodyParameter; + const dropBodyParameter = false; + // loop thru the parameters of the command operation, and if there is a body parameter, expand it if necessary. + for (const parameter of values(operation.parameters)) { + if (parameter.details.default.constantValue) { + // this parameter has a constant value -- SKIP IT + continue; + } + // dolauli fromhost and apiversion are not exposed, this if block looks useless + if (parameter.details.default.fromHost || parameter.details.default.apiversion) { + // handled in the generator right now. Not exposed to the user directly. + continue; + } + + if (dropBodyParameter && parameter.details.default.isBodyParameter) { + // the client will make a hidden body parameter for this, and we're expected to fill it. + const vps = parameter.schema.details.default.virtualProperties; + if (vps) { + for (const virtualProperty of [...vps.inherited, ...vps.owned, ...vps.inlined]) { + // dolauli add virtual parameter for virtual property + if (virtualProperty.private || virtualProperty.property.details.default.readOnly || virtualProperty.property.details.default.constantValue !== undefined || virtualProperty.property.details.default.HeaderProperty === 'Header') { + // private or readonly properties aren't needed as parameters. + continue; + } + virtualParameters.body.push({ + name: virtualProperty.name, + description: virtualProperty.property.details.default.description, + nameOptions: virtualProperty.nameOptions, + required: virtualProperty.required, + schema: virtualProperty.property.schema, + origin: virtualProperty, + alias: [] + }); + } + } + } else { + // dolauli if not drop body or not body parameter add it to operation + virtualParameters.operation.push({ + name: parameter.details.default.name, + nameOptions: [parameter.details.default.name], + description: parameter.details.default.description, + required: parameter.details.default.isBodyParameter ? true : parameter.required, + schema: parameter.schema, + origin: parameter, + alias: [] + }); + } + } + + //resolveParameterNames([], virtualParameters); + + // dolauli see operation.details.default.virtualParameters + operation.details.default.virtualParameters = virtualParameters; +} + +async function createVirtuals(state: State): Promise { + /* + A model class should provide inlined properties for anything in a property called properties + + Classes that have $THRESHOLD number of properties should be inlined. + + Individual models can change the $THRESHOLD for generate + */ + // dolauli this plugin is used to expand the property in an object. + // dolauli inline-threshold could be set in readme.md + // skip-for-time-being + // const threshold = await state.getValue('inlining-threshold', 24); + // const conflicts = new Array(); + + // for (const schema of values(state.model.schemas)) { + // if (schema.type === JsonType.Object) { + // // did we already inline this object + // // dolauli skip if inlined + // if (schema.details.default.inlined) { + // continue; + // } + // // we have an object, let's process it. + + // createVirtualProperties(schema, new Array(), threshold, conflicts); + // } + // } + // if (length(conflicts) > 0) { + // // dolauli need to figure out how inline-properties is used in readme.md + // state.error('You have one or more circular references in your model, you must add configuration entries to specify which models won\'t be inlined.', ['inline-properties']); + // for (const each of conflicts) { + // state.error(each, ['circular reference']); + // } + // throw new Error('Circular references exists, must mark models as `no-inline`'); + // } + // dolauli update operations under commands + for (const operation of values(state.model.commands.operations)) { + createVirtualParameters(operation); + } + + return state.model; +} + + +export async function createInlinedPropertiesPlugin(service: Host) { + //const session = await startSession(service, {}, codeModelSchema); + //const result = tweakModelV2(session); + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-create-virtual-properties-v2.yaml', serialize(await createVirtuals(state)), undefined, 'code-model-v4'); + //return processCodeModel(createVirtuals, service, 'create-virtual-properties-v2'); +} diff --git a/powershell/plugins/plugin-tweak-model-azure.ts b/powershell/plugins/plugin-tweak-model-azure.ts new file mode 100644 index 00000000000..4fb91a2f8e1 --- /dev/null +++ b/powershell/plugins/plugin-tweak-model-azure.ts @@ -0,0 +1,175 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { codemodel, JsonType, processCodeModel, ModelState, getAllProperties, HttpMethod, schema } from '@azure-tools/codemodel-v3'; +import { keys, length, values } from '@azure-tools/linq'; + +import { Channel, Host } from '@azure-tools/autorest-extension-base'; +type State = ModelState; + +const xmsPageable = 'x-ms-pageable'; + +async function tweakModel(state: State): Promise { + 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 operation of values(model.http.operations)) { + if (operation.extensions && operation.extensions[xmsPageable]) { + // it's marked pagable. + operation.details.default.pageable = { + responseType: 'pageable', + nextLinkName: operation.extensions[xmsPageable].nextLinkName || undefined, + itemName: operation.extensions[xmsPageable].itemName || 'value', + operationName: operation.extensions[xmsPageable].operationName || `${operation.operationId}Next`, + }; + continue; + } + + // let's just check to see if it looks like it's supposed to be a collection + for (const responses of values(operation.responses)) { + for (const response of values(responses)) { + // does the response have a schema? + if (response.schema) { + const schema = response.schema; + + // is this just an array response? + if (schema.type === JsonType.Array) { + operation.details.default.pageable = { + responseType: 'array', + }; + continue; + } + + // if it returns an object, let's see what's inside... + if (schema.type === JsonType.Object) { + + // does it have a single member that is an array (ie, value : [...]) + if (length(schema.properties) === 1 && length(schema.allOf) === 0) { + const propertyName = keys(schema.properties).first(); + if (propertyName) { + const property = schema.properties[propertyName]; + if (property.schema.type === JsonType.Array) { + // nested array! + operation.details.default.pageable = { + responseType: 'nested-array', + itemName: propertyName, + }; + } + continue; + } + } + + // does it kinda look like a x-ms-pagable (value/nextlink?) + if (length(schema.properties) === 2 && length(schema.allOf) === 0) { + if (schema.properties.nextLink) { + const propertyName = keys(schema.properties).where(each => each !== 'nextLink').first(); + if (propertyName) { + const property = schema.properties[propertyName]; + if (property.schema.type === JsonType.Array) { + // nested array! + operation.details.default.pageable = { + responseType: 'nested-array', + itemName: propertyName, + nextLinkName: 'nextLink' + }; + } + continue; + } + } + + } + + } + } + + } + } + } + + // make sure that all operations with lro have an options block. + for (const operation of values(model.http.operations)) { + if (operation.extensions && operation.extensions['x-ms-long-running-operation']) { + operation.details.default.asjob = true; + + operation.details.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 + delete operation.responses['201']; + delete operation.responses['202']; + } + } + + // 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 operation of values(model.http.operations)) { + const apiVersions = operation.pathExtensions && operation.pathExtensions['x-ms-metadata'] ? operation.pathExtensions['x-ms-metadata'].apiVersions : undefined; + for (const parameter of values(operation.parameters)) { + + if (parameter.name === '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 (length(apiVersions) === 1) { + parameter.details.default.constantValue = apiVersions[0]; + continue; + } + + // otherwise, the parameter can't have a constant value + parameter.details.default.constantValue = undefined; + + // mark it so that we can add profile support in the method generation + parameter.details.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 values(model.schemas)) { + // find schemas that have an 'id' and are not readonly + if (values(getAllProperties(schema)).any(prop => prop.serializedName === 'id' && !prop.details.default.readOnly)) { + + // look thru the operations, and the PUT methods + for (const op of values(model.http.operations).where(o => o.method === HttpMethod.Put)) { + + // see if any of the responses have the same schema as we are looking for + if (values(op.responses).any(rsps => values(rsps).any(resp => !!resp.schema && resp.schema.details.default.uid === schema.details.default.uid))) { + + // tell it not to inline that + schema.details.default.byReference = true; + } + + } + } + } + } + + return model; +} + +// Azure version - +// Additional tweaks the code model to adjust things so that the code will generate better. + +export async function tweakModelAzurePlugin(service: Host) { + return processCodeModel(tweakModel, service, 'tweakcodemodelazure-v2'); +} diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts new file mode 100644 index 00000000000..785a2273b28 --- /dev/null +++ b/powershell/plugins/plugin-tweak-model.ts @@ -0,0 +1,356 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { ModelState } from '@azure-tools/codemodel-v3'; +//import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; +import { pascalCase, deconstruct, fixLeadingNumber, serialize } from '@azure-tools/codegen'; +import { items, keys, values, Dictionary, length } from '@azure-tools/linq'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; + +import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { defaultCipherList } from 'constants'; + +export const HeaderProperty = 'HeaderProperty'; +export enum HeaderPropertyType { + Header = 'Header', + HeaderAndBody = 'HeaderAndBody' +} +type State = NewModelState; + + +// For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. +export function titleToAzureServiceName(title: string): string { + const titleCamelCase = pascalCase(deconstruct(title)).trim(); + const serviceName = titleCamelCase + // Remove: !StartsWith(Management)AndContains(Management), Client, Azure, Microsoft, APIs, API, REST + .replace(/(?!^Management)(?=.*)Management|Client|Azure|Microsoft|APIs|API|REST/g, '') + // Remove: EndsWith(ServiceResourceProvider), EndsWith(ResourceProvider), EndsWith(DataPlane), EndsWith(Data) + .replace(/ServiceResourceProvider$|ResourceProvider$|DataPlane$|Data$/g, ''); + return serviceName || titleCamelCase; +} + + +// function dropDuplicatePropertiesInChildSchemas(schema: Schema, state: State, map: Map = new Map()) { +// let success = true; +// for (const parent of values(schema.allOf)) { +// handle parents first +// if (!dropDuplicatePropertiesInChildSchemas(parent, state, map)) { +// return false; +// } +// } +// for (const { key: id, value: property } of items(schema.properties)) { +// see if it's in the parent. +// const pProp = map.get(property.serializedName); +// if (pProp) { +// if the parent prop is the same type as the child prop +// we're going to drop the child property. +// if (pProp.schema.type === property.schema.type) { +// if it's an object type, it has to be the exact same schema type too +// if (pProp.schema.type != JsonType.Object || pProp.schema === property.schema) { +// state.verbose(`Property '${property.serializedName}' in '${schema.details.default.name}' has a property the same as the parent, and is dropping the duplicate.`, {}); +// delete schema.properties[id]; +// } else { +// const conflict = `Property '${property.serializedName}' in '${schema.details.default.name}' has a conflict with a parent schema (allOf ${schema.allOf.joinWith(each => each.details.default.name)}.`; +// state.error(conflict, [], {}); +// success = false; +// } +// } +// } +// else { +// map.set(property.serializedName, property); +// } +// } +// return success; +// } + +async function tweakModelV2(state: State): Promise { + const title = pascalCase(fixLeadingNumber(deconstruct(await state.getValue('title', state.model.info.title)))); + state.setValue('title', title); + + const serviceName = await state.getValue('service-name', titleToAzureServiceName(title)); + state.setValue('service-name', serviceName); + + const model = state.model; + + const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); + universalId.apiVersions = universalId.apiVersions || []; + state.model.schemas.objects = state.model.schemas.objects || []; + state.model.schemas.objects.push(universalId); + + model.commands = { + operations: new Dictionary(), + parameters: new Dictionary(), + }; + + return model; +} +// async function tweakModel(state: State): Promise { +// const title = pascalCase(fixLeadingNumber(deconstruct(await state.getValue('title', state.model.info.title)))); +// state.setValue('title', title); + +// const serviceName = await state.getValue('service-name', titleToAzureServiceName(title)); +// state.setValue('service-name', serviceName); + +// const model = state.model; +// model.schemas = model.schemas || []; + +// const set = new Set(); +// const removes = new Set(); + +// for (const key of keys(model.schemas)) { +// const value = model.schemas[key]; +// if (set.has(value)) { +// // this schema is already in the collection. let's drop it when we're done +// removes.add(key); +// } else { +// set.add(value); +// } +// } + +// // we're going to create a schema that represents the distinct sum +// // of all operation PATH parameters +// const universalId = new Schema(`${serviceName}Identity`, { +// type: JsonType.Object, description: 'Resource Identity', details: { +// default: { +// uid: 'universal-parameter-type' +// } +// } +// }); +// model.schemas['universal-parameter-type'] = universalId; + +// for (const operation of values(model.http.operations)) { +// for (const param of values(operation.parameters).where(each => each.in === ParameterLocation.Path)) { +// const name = param.details.default.name; +// if (!universalId.properties[name]) { +// universalId.properties[name] = new Property(name, { +// schema: param.schema, description: param.description, serializedName: name, details: { +// default: { +// description: param.description, +// name: name, +// required: false, +// readOnly: false, +// uid: `universal-parameter:${name}` +// } +// } +// }); +// } +// } +// } + +// if (await state.getValue('azure', false)) { +// universalId.properties['id'] = new Property('id', { +// schema: new Schema('_identity_type_', { type: JsonType.String, description: 'Resource identity path' }), +// description: 'Resource identity path', serializedName: 'id', details: { +// default: { +// description: 'Resource identity path', +// name: 'id', +// required: false, +// readOnly: false, +// uid: 'universal-parameter:resource identity' +// } +// } +// }); +// } + +// // remove schemas that are referenced elsewhere previously. +// for (const each of removes.values()) { +// delete model.schemas[each]; +// } + +// // 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 values(model.http.operations)) { +// for (const responses of values(operation.responses)) { +// for (const response of responses) { +// if (response.schema) { +// if (response.schema.type === JsonType.String && response.schema.format === StringFormat.Binary) { +// // WHY WAS THIS HERE?! +// // response.mimeTypes = [KnownMediaType.Stream]; +// } +// } +// } +// } +// } + +// // schemas that have parents and implement properties that are in the parent schemas +// // will have the property dropped in the child schema +// for (const schema of values(model.schemas)) { +// if (length(schema.allOf) > 0) { +// if (!dropDuplicatePropertiesInChildSchemas(schema, state)) { +// throw new Error('Schemas are in conflict.'); +// } +// } +// } + + +// if (await state.getValue('use-storage-pipeline', false)) { +// // 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 values(model.http.operations)) { +// for (const responses of values(operation.responses)) { +// for (const response of responses) { +// // for a given response, find the possible models that can be returned from the service +// for (const header of values(response.headers)) { + +// if (!response.schema) { +// // no response schema? can we fake one? +// // service.Message({ Channel: Channel.Debug, Text: `${header.key} is in ${operation.details.default.name} but there is no response model` }); +// continue; +// } + +// // 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 (isSchemaObject(response.schema)) { +// response.schema.details.default.hasHeaders = true; +// const property = response.schema.properties[header.key]; +// if (!property) { +// state.message({ Channel: 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 Property(header.key, { schema: header.schema, description: header.description }); +// newProperty.details.default.name = header.key; +// newProperty.details.default.required = false; + +// // mark it that it's a header-only property +// newProperty.details.default[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.default[HeaderProperty]) { + +// state.message({ Channel: Channel.Debug, Text: `Property ${header.key} in model ${response.schema.details.default.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[HeaderProperty] = HeaderPropertyType.HeaderAndBody; +// property.details.default.name = header.key; +// } +// } +// } +// } +// } +// } +// } +// } + +// // remove well-known header parameters from operations and add mark the operation has supporting that feature + +// for (const operation of values(model.http.operations)) { +// // if we have an operation with a body, and content-type is a multipart/formdata +// // then we should go thru the parameters of the body and look for a string/binary parameters +// // and remember to add another parameter for the filename of the string/binary +// if (operation.requestBody && knownMediaType(operation.requestBody.contentType) === KnownMediaType.Multipart) { +// for (const prop of values(operation.requestBody.schema.properties)) { +// if (prop.schema.type === JsonType.String && prop.schema.format === 'binary') { +// prop.details.default.isNamedStream = true; +// } +// } +// } + +// // move well-known hearder parameters into details, and we can process them in the generator how we please. +// // operation.details.default.headerparameters = values(operation.parameters).where(p => p.in === ParameterLocation.Header && ['If-Match', 'If-None-Match'].includes(p.name)).toArray(); + +// // remove if-match and if-none-match parameters from the operation itself. +// // operation.parameters = values(operation.parameters).where(p => !(p.in === ParameterLocation.Header && ['If-Match', 'If-None-Match'].includes(p.name))).toArray(); + +// } + +// // identify models that are polymorphic in nature +// for (const schema of values(model.schemas)) { +// // if this actual type is polymorphic, make sure we know that. +// if (schema.discriminator) { +// schema.details.default.isPolymorphic = true; +// } + + +// const parents = getPolymorphicBases(schema); +// if (length(parents) > 0) { +// // if our parent is polymorphic, then we must have a discriminator value +// schema.details.default.discriminatorValue = schema.extensions['x-ms-discriminator-value'] || schema.details.default.name; + +// // and make sure that all our polymorphic parents have a reference to this type. +// for (const parent of getPolymorphicBases(schema)) { + +// parent.details.default.polymorphicChildren = parent.details.default.polymorphicChildren || new Array(); +// parent.details.default.polymorphicChildren.push(schema); +// } +// } +// } + +// // identify parameters that are constants +// for (const operation of values(model.http.operations)) { +// for (const parameter of values(operation.parameters)) { +// if (parameter.required && length(parameter.schema.enum) === 1) { +// // parameters with an enum single value are constants +// parameter.details.default.constantValue = parameter.schema.enum[0]; +// } +// } +// } + +// const enumsToSkip = new Set(); +// // identify properties that are constants +// for (const schema of values(model.schemas)) { +// for (const property of values(schema.properties)) { +// if (property.details.default.required && length(property.schema.enum) === 1) { +// // properties with an enum single value are constants +// // add the constant value +// property.details.default.constantValue = property.schema.enum[0]; + +// // mark as skip the generation of this model +// enumsToSkip.add(property.schema.details.default.uid); + +// // make it a string and keep its name +// property.schema = new Schema(property.schema.details.default.name, { type: property.schema.type }); +// } else { +// enumsToSkip.delete(property.schema.details.default.uid); +// } +// } +// } + +// // mark enums that shouldn't be generated +// for (const schema of values(model.schemas)) { +// if (enumsToSkip.has(schema.details.default.uid)) { +// schema.details.default.skip = true; +// } +// } + +// for (const operation of values(model.http.operations)) { +// for (const { key: responseCode, value: responses } of items(operation.responses)) { +// for (const response of values(responses)) { +// if (responseCode === 'default' || response.extensions['x-ms-error-response'] === true) { +// response.details.default.isErrorResponse = true; +// } +// } +// } +// } + +// return model; +// } + +// Universal version - +// tweaks the code model to adjust things so that the code will generate better. + +export async function tweakModelPlugin(service: Host) { + //const session = await startSession(service, {}, codeModelSchema); + const state = await new NewModelState(service).init(); + //const result = tweakModelV2(session); + await service.WriteFile('code-model-v4-tweakcodemodel-v2.yaml', serialize(await tweakModelV2(state)), undefined, 'code-model-v4'); + //return processCodeModel(tweakModelV2, service, 'tweakcodemodel-v2'); +} diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts new file mode 100644 index 00000000000..13e71a4e64b --- /dev/null +++ b/powershell/plugins/powershell-v2.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { codemodel } from '@azure-tools/codemodel-v3'; +import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; +import { Host } from '@azure-tools/autorest-extension-base'; +import { join } from 'path'; +import { Project, NewProject } from '../internal/project'; +import { State } from '../internal/state'; +import { generatePsm1 } from '../generators/psm1'; +import { generateCsproj } from '../generators/csproj'; +import { generatePsm1Custom } from '../generators/psm1.custom'; +import { generatePsm1Internal } from '../generators/psm1.internal'; +import { generateNuspec } from '../generators/nuspec'; +import { generateGitIgnore } from '../generators/gitignore'; +import { generateGitAttributes } from '../generators/gitattributes'; +import { generateReadme } from '../generators/readme'; +import { generateScriptCmdlets } from '../generators/script-cmdlet'; + +const sourceFileCSharp = 'source-file-csharp'; +const resources = `${__dirname}/../../resources`; + + +async function copyRequiredFiles(project: Project | NewProject) { + const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; + + // Project assets + await copyResources(join(resources, 'assets'), async (fname, content) => project.state.writeFile(fname, content, undefined, 'source-file-other'), undefined, transformOutput); + + // Runtime files + await copyResources(join(resources, 'psruntime'), async (fname, content) => project.state.writeFile(join(project.runtimeFolder, fname), content, undefined, sourceFileCSharp), project.overrides, transformOutput); + + // Modules files + await copyBinaryResources(join(resources, 'modules'), async (fname, content) => project.state.writeFile(join(project.dependencyModuleFolder, fname), content, undefined, 'binary-file')); + + if (project.azure) { + // Signing key file + await copyBinaryResources(join(resources, 'signing'), async (fname, content) => project.state.writeFile(join(project.baseFolder, fname), content, undefined, 'binary-file')); + } +} + + +export async function powershellV2(service: Host) { + const debug = await service.GetValue('debug') || false; + + try { + const project = await new NewProject(service).init(); + + await project.writeFiles(async (filename, content) => project.state.writeFile(filename, applyOverrides(content, project.overrides), undefined, sourceFileCSharp)); + + await service.ProtectFiles(project.psd1); + await service.ProtectFiles(project.readme); + await service.ProtectFiles(project.customFolder); + await service.ProtectFiles(project.testFolder); + await service.ProtectFiles(project.docsFolder); + await service.ProtectFiles(project.examplesFolder); + await service.ProtectFiles(project.resourcesFolder); + + // wait for all the generation to be done + await copyRequiredFiles(project); + await generateCsproj(project); + await generatePsm1(project); + await generatePsm1Custom(project); + await generatePsm1Internal(project); + await generateNuspec(project); + await generateGitIgnore(project); + await generateGitAttributes(project); + await generateReadme(project); + + await generateScriptCmdlets(project); + + } catch (E) { + if (debug) { + console.error(`${__filename} - FAILURE ${JSON.stringify(E)} ${E.stack}`); + } + throw E; + } +} + diff --git a/powershell/plugins/powershell.ts b/powershell/plugins/powershell.ts index 4020637cf7b..feffd74bee1 100644 --- a/powershell/plugins/powershell.ts +++ b/powershell/plugins/powershell.ts @@ -18,12 +18,13 @@ import { generateGitIgnore } from '../generators/gitignore'; import { generateGitAttributes } from '../generators/gitattributes'; import { generateReadme } from '../generators/readme'; import { generateScriptCmdlets } from '../generators/script-cmdlet'; +import { NewProject } from '../internal/project'; const sourceFileCSharp = 'source-file-csharp'; const resources = `${__dirname}/../../resources`; -async function copyRequiredFiles(project: Project) { +async function copyRequiredFiles(project: Project | NewProject) { const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; // Project assets diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts new file mode 100644 index 00000000000..20f3fa05386 --- /dev/null +++ b/powershell/plugins/ps-namer-v2.ts @@ -0,0 +1,212 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { Host, Channel, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames, ModelState, isMediaTypeMultipartFormData, VirtualParameter } from '@azure-tools/codemodel-v3'; +import { deconstruct, removeProhibitedPrefix, removeSequentialDuplicates, pascalCase, serialize } from '@azure-tools/codegen'; +import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; +import * as linq from '@azure-tools/linq'; +import { singularize } from '../internal/name-inferrer'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; + +type State = NewModelState; + +function getCmdletName(verb: string, subjectPrefix: string, subject: string): string { + return `${verb}-${subjectPrefix}${subject}`; +} + +export function getDeduplicatedNoun(subjectPrefix: string, subject: string): { subjectPrefix: string; subject: string } { + // dedup parts + const dedupedPrefix = [...removeSequentialDuplicates(deconstruct(subjectPrefix))]; + const dedupedSubject = [...removeSequentialDuplicates(deconstruct(subject))]; + + // dedup the noun + const dedupedMerge = [...removeSequentialDuplicates([...dedupedPrefix, ...dedupedSubject])]; + + // figure out what belongs to the subject + const reversedFinalSubject = new Array(); + for (let mCount = length(dedupedMerge) - 1, sCount = length(dedupedSubject) - 1; sCount >= 0 && mCount >= 0; mCount--, sCount--) { + if (dedupedMerge[mCount] !== dedupedSubject[sCount]) { + break; + } + + reversedFinalSubject.push(dedupedMerge.pop()); + } + + // what's left belongs to the prefix + const finalPrefix = new Array(); + for (const each of dedupedMerge) { + finalPrefix.push(each); + } + + return { subjectPrefix: pascalCase(finalPrefix), subject: pascalCase(reversedFinalSubject.reverse()) }; +} + +async function tweakModel(state: State): Promise { + // get the value + const isAzure = await state.getValue('azure', false); + // without setting snitize-names, isAzure is applied + const shouldSanitize = await state.getValue('sanitize-names', isAzure); + + // make sure recursively that every details field has csharp + for (const { index, instance } of linq.visitor(state.model)) { + if (index === 'language' && instance.default && !instance.csharp) { + instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); + } + } + // dolauli sanitize name + if (shouldSanitize) { + for (const operation of values(state.model.commands.operations)) { + // clean the noun (i.e. subjectPrefix + subject) + const prevSubjectPrefix = operation.details.csharp.subjectPrefix; + const prevSubject = operation.details.csharp.subject; + const dedupedNounParts = getDeduplicatedNoun(operation.details.csharp.subjectPrefix, operation.details.csharp.subject); + if (prevSubjectPrefix !== dedupedNounParts.subjectPrefix || prevSubject !== dedupedNounParts.subject) { + const verb = operation.details.csharp.verb; + const variantName = operation.details.csharp.name; + const prevCmdletName = getCmdletName(verb, prevSubjectPrefix, prevSubject); + operation.details.csharp.subjectPrefix = dedupedNounParts.subjectPrefix; + operation.details.csharp.subject = dedupedNounParts.subject; + const newCmdletName = getCmdletName(verb, operation.details.csharp.subjectPrefix, operation.details.csharp.subject); + state.message( + { + Channel: Channel.Debug, + Text: `Sanitized cmdlet-name -> Changed cmdlet-name from ${prevCmdletName} to ${newCmdletName}: {subjectPrefix: ${operation.details.csharp.subjectPrefix}, subject: ${operation.details.csharp.subject}${variantName ? `, variant: ${variantName}}` : '}'}` + } + ); + } + + const virtualParameters = [...allVirtualParameters(operation.details.csharp.virtualParameters)]; + for (const parameter of virtualParameters) { + let prevName = parameter.name; + const otherParametersNames = values(virtualParameters) + .select(each => each.name) + .where(name => name !== parameter.name) + .toArray(); + + // first try to singularize the parameter + const singularName = singularize(parameter.name); + if (prevName != singularName) { + parameter.name = singularName; + state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to singular ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); + } + + // save the name again to compare in case it was modified + prevName = parameter.name; + + // now remove the subject from the beginning of the parameter + // to reduce naming redundancy, but just for path parameters + // e.g. get-vm -vmname ---> get-vm -name + if ((parameter.origin).in === ParameterLocation.Path) { + const sanitizedName = removeProhibitedPrefix( + parameter.name, + operation.details.csharp.subject, + otherParametersNames + ); + + if (prevName !== sanitizedName) { + if (parameter.alias === undefined) { + parameter.alias = []; + } + + // saved the prev name as alias + parameter.alias.push(parameter.name); + + // change name + parameter.name = sanitizedName; + state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); + state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); + } + } + } + } + + for (const schemaGroup of values(>>state.model.schemas)) { + for (const schema of schemaGroup) { + const virtualProperties = [...allVirtualProperties(schema.language.csharp?.virtualProperties)]; + + for (const property of virtualProperties) { + let prevName = property.name; + const otherPropertiesNames = values(virtualProperties) + .select(each => each.name) + .where(name => name !== property.name) + .toArray(); + + // first try to singularize the property + const singularName = singularize(property.name); + if (prevName != singularName) { + property.name = singularName; + state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to singular ${property.name} from model ${schema.language.csharp?.name}` }); + } + + // save the name again to compare in case it was modified + prevName = property.name; + + // now remove the model=name from the beginning of the property-name + // to reduce naming redundancy + const sanitizedName = removeProhibitedPrefix( + property.name, + schema.language.csharp?.name ? schema.language.csharp?.name : '', + otherPropertiesNames + ); + + if (prevName !== sanitizedName) { + property.alias = property.alias || []; + + // saved the prev name as alias + property.alias.push(property.name); + + // change name + property.name = sanitizedName; + state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to ${property.name} from model ${schema.language.csharp?.name}` }); + state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); + + // update shared properties too + if (property.sharedWith) { + for (const sharedProperty of property.sharedWith) { + if (sharedProperty.name !== sanitizedName) { + state.message({ Channel: Channel.Debug, Text: `Changing shared property ${sharedProperty.name} to ${sanitizedName}` }); + sharedProperty.alias = sharedProperty.alias || []; + sharedProperty.alias.push(sharedProperty.name); + sharedProperty.name = sanitizedName; + } + } + } + } + } + } + } + } + + // do collision detection work. + for (const command of values(state.model.commands.operations)) { + const vp = command.details.csharp?.virtualParameters; + if (vp) { + resolveParameterNames([], vp); + } + } + + for (const schemaGroup of values(>>state.model.schemas)) { + for (const schema of schemaGroup) { + const vp = schema.language.csharp?.virtualProperties; + if (vp) { + resolvePropertyNames(schema.language.csharp?.name ? [schema.language.csharp?.name] : [], vp); + } + } + } + return state.model; +} + + +export async function namerV2(service: Host) { + // dolauli add csharp for cmdlets in the command->operation node + //return processCodeModel(tweakModel, service, 'psnamer'); + //const session = await startSession(service, {}, codeModelSchema); + //const result = tweakModelV2(session); + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-psnamer-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); +} \ No newline at end of file diff --git a/powershell/plugins/ps-namer.ts b/powershell/plugins/ps-namer.ts index aea242a2307..b01a9fce18d 100644 --- a/powershell/plugins/ps-namer.ts +++ b/powershell/plugins/ps-namer.ts @@ -26,7 +26,7 @@ export function getDeduplicatedNoun(subjectPrefix: string, subject: string): { s // figure out what belongs to the subject const reversedFinalSubject = new Array(); - for (let mCount = length(dedupedMerge) - 1, sCount = length(dedupedSubject) - 1; sCount >= 0 && mCount >= 0; mCount-- , sCount--) { + for (let mCount = length(dedupedMerge) - 1, sCount = length(dedupedSubject) - 1; sCount >= 0 && mCount >= 0; mCount--, sCount--) { if (dedupedMerge[mCount] !== dedupedSubject[sCount]) { break; } @@ -46,6 +46,7 @@ export function getDeduplicatedNoun(subjectPrefix: string, subject: string): { s async function tweakModel(state: State): Promise { // get the value const isAzure = await state.getValue('azure', false); + // without setting snitize-names, isAzure is applied const shouldSanitize = await state.getValue('sanitize-names', isAzure); // make sure recursively that every details field has csharp @@ -54,7 +55,7 @@ async function tweakModel(state: State): Promise { instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); } } - + // dolauli sanitize name if (shouldSanitize) { for (const operation of values(state.model.commands.operations)) { // clean the noun (i.e. subjectPrefix + subject) @@ -195,5 +196,6 @@ async function tweakModel(state: State): Promise { export async function namer(service: Host) { + // dolauli add csharp for cmdlets in the command->operation node return processCodeModel(tweakModel, service, 'psnamer'); } \ No newline at end of file diff --git a/powershell/utils/PwshModel.ts b/powershell/utils/PwshModel.ts new file mode 100644 index 00000000000..dd05c29465a --- /dev/null +++ b/powershell/utils/PwshModel.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { CommandComponents } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +import { DeepPartial } from '@azure-tools/codegen'; + +export class PwshModel extends CodeModel { + public commands = new CommandComponents(); + constructor(title: string, sourceTracking = false, initializer?: DeepPartial) { + super(title, sourceTracking); + + this.apply(initializer); + } +} \ No newline at end of file diff --git a/powershell/utils/components.ts b/powershell/utils/components.ts new file mode 100644 index 00000000000..7dcb38cb51a --- /dev/null +++ b/powershell/utils/components.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { DeepPartial } from '@azure-tools/codegen'; +import { Dictionary } from '@azure-tools/linq'; +import { components, Schema } from '@azure-tools/codemodel-v3'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; + + +export class IParameterPwsh extends components.IParameter { + constructor(public name: string, public schema: Schema, public newSchema: NewSchema, initializer?: DeepPartial) { + super(name, schema); + } +} +// export class IParameter extends Extensions { +// constructor(public name: string, public schema: Schema, initializer?: DeepPartial) { +// super(); +// this.description = ''; +// this.deprecated = false; +// this.required = false; +// this.details = { +// default: { +// uid: `parameter:${uid()}`, +// description: this.description, +// name, +// } +// }; +// this.allowEmptyValue = false; +// this.apply(initializer); +// } +// } + diff --git a/powershell/utils/model-state.ts b/powershell/utils/model-state.ts new file mode 100644 index 00000000000..c51ff1e84e6 --- /dev/null +++ b/powershell/utils/model-state.ts @@ -0,0 +1,239 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Channel, Host, JsonPath, Mapping, RawSourceMap, Message } from '@azure-tools/autorest-extension-base'; +import { safeEval, deserialize, Initializer, DeepPartial } from '@azure-tools/codegen'; +import { Dictionary } from '@azure-tools/linq'; + +export class NewModelState> extends Initializer { + public model!: T; + protected documentName!: string; + protected currentPath: JsonPath = new Array(); + private context!: any; + private _debug = false; + private _verbose = false; + + public constructor(protected service: Host, objectInitializer?: DeepPartial>) { + super(); + this.apply(objectInitializer); + } + + async init(project?: any) { + const m = await NewModelState.getModel(this.service); + this.model = m.model; + this.documentName = m.filename; + this.initContext(project); + this._debug = await this.getValue('debug', false); + this._verbose = await this.getValue('verbose', false); + return this; + } + + async initContext(project: any) { + this.context = this.context || { + $config: await this.service.GetValue(''), + $project: project, + $lib: { + path: require('path') + } + }; + return this; + } + + async readFile(filename: string): Promise { + return this.service.ReadFile(filename); + } + + + async getValue(key: string, defaultValue?: V): Promise { + // check if it's in the model first + let value = this.model && this.model.language && this.model.language.default ? (this.model.language.default)[key] : undefined; + + // fall back to the configuration + if (value == null || value === undefined) { + value = await this.service.GetValue(key); + } + + // try as a safe eval execution. + if (value === null || value === undefined) { + try { + value = safeEval(key, this.context); + } + catch { + value = null; + } + } + + if (defaultValue === undefined && value === null) { + throw new Error(`No value for configuration key '${key}' was provided`); + } + + if (typeof value === 'string') { + value = await this.resolveVariables(value); + } + + // ensure that any content variables are resolved at the end. + return (value !== null ? value : defaultValue); + } + + async setValue(key: string, value: V) { + (this.model.language.default)[key] = value; + } + + async listInputs(artifactType?: string | undefined): Promise> { + return this.service.ListInputs(artifactType); + } + + async protectFiles(path: string): Promise { + return this.service.ProtectFiles(path); + } + writeFile(filename: string, content: string, sourceMap?: Array | RawSourceMap | undefined, artifactType?: string | undefined): void { + return this.service.WriteFile(filename, content, sourceMap, artifactType); + } + + message(message: Message): void { + if (message.Channel === Channel.Debug && this._debug === false) { + return; + } + if (message.Channel === Channel.Verbose && this._verbose === false) { + return; + } + return this.service.Message(message); + } + + updateConfigurationFile(filename: string, content: string): void { + return this.service.UpdateConfigurationFile(filename, content); + } + async getConfigurationFile(filename: string): Promise { + return this.service.GetConfigurationFile(filename); + } + protected errorCount = 0; + + protected static async getModel(service: Host) { + const files = await service.ListInputs(); + const filename = files[0]; + if (files.length === 0) { + throw new Error('Inputs missing.'); + } + return { + filename, + model: deserialize(await service.ReadFile(filename), filename) + }; + } + + + cache!: Array; + replacer(key: string, value: any) { + this.cache = this.cache || new Array(); + + if (typeof value === 'object' && value !== null) { + if (this.cache.indexOf(value) !== -1) { + // Duplicate reference found + try { + // If this value does not reference a parent it can be deduped + return JSON.parse(JSON.stringify(value)); + } catch (error) { + // discard key if value cannot be deduped + return; + } + } + // Store value in our collection + this.cache.push(value); + } + return value; + } + + async resolveVariables(input: string): Promise { + let output = input; + for (const rx of [/\$\((.*?)\)/g, /\$\{(.*?)\}/g]) { + /* eslint-disable */ + for (let match; match = rx.exec(input);) { + const text = match[0]; + const inner = match[1]; + let value = await this.getValue(inner, null); + + if (value !== undefined && value !== null) { + if (typeof value === 'object') { + value = JSON.stringify(value, this.replacer, 2); + } + if (value === '{}') { + value = 'true'; + } + output = output.replace(text, value); + } + } + } + return output; + } + + + public path(...childPath: JsonPath) { + // this strategy for tracking source path locations + // has proved fundementally crappy. + + // will be removing this stuff and transitioning to source-track method. + + //const result = new ModelState(this.service, this); + //result.currentPath = [...this.currentPath, ...childPath]; + // return result; + return this; + } + + public checkpoint() { + if (this.errorCount > 0) { + throw new Error(); + } + } + + protected msg(channel: Channel, message: string, key: Array, details: any) { + this.message({ + Channel: channel, + Key: key, + Source: [ + { + document: this.documentName, + Position: { + path: this.currentPath + } + } + ], + Text: message, + Details: details + }); + } + + public warning(message: string, key: Array, details?: any) { + this.msg(Channel.Warning, message, key, details); + } + public hint(message: string, key: Array, details?: any) { + this.msg(Channel.Hint, message, key, details); + } + + public error(message: string, key: Array, details?: any) { + this.errorCount++; + this.msg(Channel.Error, message, key, details); + } + public fatal(message: string, key: Array, details?: any) { + this.errorCount++; + this.msg(Channel.Fatal, message, key, details); + } + + protected output(channel: Channel, message: string, details?: any) { + this.message({ + Channel: channel, + Text: message, + Details: details + }); + } + + public debug(message: string, details: any) { + this.output(Channel.Debug, message, details); + } + public verbose(message: string, details: any) { + this.output(Channel.Verbose, message, details); + } + public log(message: string, details: any) { + this.output(Channel.Information, message, details); + } +} diff --git a/samples/Xkcd/xkcd.yaml b/samples/Xkcd/xkcd.yaml index 9994099c81c..12dc56adfae 100644 --- a/samples/Xkcd/xkcd.yaml +++ b/samples/Xkcd/xkcd.yaml @@ -30,6 +30,7 @@ consumes: - application/json paths: + /info.0.json: get: operationId: xkcd_getComicForToday @@ -39,45 +40,5 @@ paths: '200': description: OK schema: - $ref: '#/definitions/comic' - '/{comicId}/info.0.json': - get: - operationId: xkcd_getComic - description: | - Fetch comics and metadata by comic id. - parameters: - - in: path - name: comicId - required: true - type: number - responses: - '200': - description: OK - schema: - $ref: '#/definitions/comic' -definitions: - comic: - properties: - alt: - type: string - day: - type: string - img: - type: string - link: - type: string - month: - type: string - news: - type: string - num: - type: number - safe_title: - type: string - title: - type: string - transcript: - type: string - year: - type: string - type: object \ No newline at end of file + type: string + \ No newline at end of file From c4d93b83cc5c2826081f8f6f41ad5fe8b49e0776 Mon Sep 17 00:00:00 2001 From: derek Date: Thu, 9 Jul 2020 16:56:23 +0800 Subject: [PATCH 02/61] Move some libs from modeler-v3 to autorest.powershell and remove modeler-v3 dependency in the new plugins --- powershell/autorest-configuration.md | 8 +- powershell/internal/project.ts | 4 +- powershell/models/model-extensions.ts | 348 +++++++++--------- powershell/plugins/create-commands-v2.ts | 29 +- powershell/plugins/cs-namer-v2.ts | 1 - .../plugin-create-inline-properties.ts | 7 +- powershell/plugins/plugin-tweak-model.ts | 2 +- powershell/plugins/powershell-v2.ts | 4 +- powershell/plugins/ps-namer-v2.ts | 3 +- powershell/utils/PwshModel.ts | 3 +- powershell/utils/command-operation.ts | 79 ++++ powershell/utils/components.ts | 225 ++++++++++- powershell/utils/extensions.ts | 20 + powershell/utils/http-operation.ts | 300 +++++++++++++++ powershell/utils/info.ts | 55 +++ powershell/utils/programatic-operation.ts | 45 +++ powershell/utils/resolve-conflicts.ts | 60 +++ powershell/utils/schema.ts | 296 +++++++++++++++ powershell/utils/security-scheme.ts | 192 ++++++++++ powershell/utils/uid.ts | 5 + 20 files changed, 1464 insertions(+), 222 deletions(-) create mode 100644 powershell/utils/command-operation.ts create mode 100644 powershell/utils/extensions.ts create mode 100644 powershell/utils/http-operation.ts create mode 100644 powershell/utils/info.ts create mode 100644 powershell/utils/programatic-operation.ts create mode 100644 powershell/utils/resolve-conflicts.ts create mode 100644 powershell/utils/schema.ts create mode 100644 powershell/utils/security-scheme.ts create mode 100644 powershell/utils/uid.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 7301da27f71..79134309a6d 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -137,8 +137,8 @@ pipeline: llcsharp-v2: input: psnamer-v2 - # powershell-v2: - # input: psnamer-v2 + powershell-v2: + input: psnamer-v2 # --- extension powershell --- # creates high-level commands @@ -164,7 +164,7 @@ pipeline: # creates powershell cmdlets for high-level commands. (leverages llc# code) powershell: - input: add-azure-completers # and the generated c# files + input: add-azure-completers # and the generated c# files # --- extension llcsharp --- # generates c# files for http-operations @@ -176,7 +176,7 @@ pipeline: scope: scope-here powershell/text-transform: - input: powershell + input: powershell-v2 scope: scope-here llcsharp/emitter: diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 8c1e799ec8d..471f5122f42 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -377,8 +377,8 @@ export class NewProject extends codeDomProject { this.serviceNamespace.header = this.license; this.addNamespace(this.serviceNamespace); - //this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); - //this.supportNamespace.header = this.license; + this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); + this.supportNamespace.header = this.license; //this.addNamespace(this.supportNamespace); this.modelsExtensions = new NewModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 8fdea24e7c1..4cefd217511 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -268,7 +268,7 @@ export class NewModelExtensionsNamespace extends Namespace { } resolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private schemas: Dictionary>, private state: NewState, objectInitializer?: DeepPartial) { super('Models', parent); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); @@ -278,210 +278,212 @@ export class NewModelExtensionsNamespace extends Namespace { const resolver = (s: NewSchema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state); // Add typeconverters to model classes (partial) - for (const schema of values(schemas)) { - if (!schema || (schema.language.csharp && schema.language.csharp.skip)) { - continue; - } - - const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof ObjectImplementation) { - - // it's a class object. - const className = td.schema.details.csharp.name; - const interfaceName = td.schema.details.csharp.interfaceName || ''; - const converterClass = `${className}TypeConverter`; - - if (this.findClassByName(className).length > 0) { + for (const schemaGroup of values(schemas)) { + for (const schema of values(schemaGroup)) { + if (!schema || (schema.language.csharp && schema.language.csharp.skip)) { continue; } - // get the actual full namespace for the schema - const fullname = schema.language.csharp?.namespace || this.fullName; - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionModelExtensionsNamespace(this.outputFolder, fullname)); + const td = this.resolver.resolveTypeDeclaration(schema, true, state); + if (td instanceof ObjectImplementation) { - // create the model extensions for each object model - // 2. A partial interface with the type converter attribute - const modelInterface = new Interface(ns, interfaceName, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. - }); - modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + // it's a class object. + const className = td.schema.details.csharp.name; + const interfaceName = td.schema.details.csharp.interfaceName || ''; + const converterClass = `${className}TypeConverter`; - // 1. A partial class with the type converter attribute - const model = new Class(ns, className, undefined, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${className}.PowerShell` - }); + if (this.findClassByName(className).length > 0) { + continue; + } - // if the model is supposed to be use 'by-reference' we should create an I*Reference interface for that - // and add that interface to the extension class - if (schema.language.csharp?.byReference) { - const refInterface = `${interfaceName}_Reference`; - schema.language.csharp.referenceInterface = `${ns.fullName}.${refInterface}`; + // get the actual full namespace for the schema + const fullname = schema.language.csharp?.namespace || this.fullName; + const ns = this.subNamespaces[fullname] || this.add(new ApiVersionModelExtensionsNamespace(this.outputFolder, fullname)); - const referenceInterface = new Interface(ns, refInterface, { + // create the model extensions for each object model + // 2. A partial interface with the type converter attribute + const modelInterface = new Interface(ns, interfaceName, { partial: true, - description: `Reference for model ${fullname}`, + description: td.schema.details.csharp.description, fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. }); - referenceInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - referenceInterface.add(new InterfaceProperty('Id', dotnet.String, { setAccess: Access.Internal })); - model.interfaces.push(referenceInterface); + modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - // add it to the generic reference type. - // referenceType = referenceType || this.CreateReferenceType(); - // referenceType.interfaces.push(referenceInterface); - } + // 1. A partial class with the type converter attribute + const model = new Class(ns, className, undefined, { + partial: true, + description: td.schema.details.csharp.description, + fileName: `${className}.PowerShell` + }); + // if the model is supposed to be use 'by-reference' we should create an I*Reference interface for that + // and add that interface to the extension class + if (schema.language.csharp?.byReference) { + const refInterface = `${interfaceName}_Reference`; + schema.language.csharp.referenceInterface = `${ns.fullName}.${refInterface}`; - model.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { - static: Modifier.Static, - parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], - description: `Creates a new instance of , deserializing the content from a json string.`, - returnsDescription: 'an instance of the model class.' - })); + const referenceInterface = new Interface(ns, refInterface, { + partial: true, + description: `Reference for model ${fullname}`, + fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. + }); + referenceInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + referenceInterface.add(new InterfaceProperty('Id', dotnet.String, { setAccess: Access.Internal })); + model.interfaces.push(referenceInterface); - model.add(new LambdaMethod('ToJsonString', dotnet.String, new LiteralExpression(`ToJson(${dotnet.Null}, ${ClientRuntime.SerializationMode.IncludeAll})?.ToString()`), { - description: 'Serializes this instance to a json string.', - returnsDescription: 'a containing this model serialized to JSON text.' - })); + // add it to the generic reference type. + // referenceType = referenceType || this.CreateReferenceType(); + // referenceType.interfaces.push(referenceInterface); + } - const hashDeseralizer = new NewDeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); - const psDeseralizer = new NewDeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); - // + static FromJsonString(string json); - // + string ToJsonString() + model.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { + static: Modifier.Static, + parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], + description: `Creates a new instance of , deserializing the content from a json string.`, + returnsDescription: 'an instance of the model class.' + })); - // 3. A TypeConverter class - const typeConverter = new Class(ns, converterClass, PSTypeConverter, { - description: `A PowerShell PSTypeConverter to support converting to an instance of `, - fileName: `${className}.TypeConverter` - }); - typeConverter.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the parameter can be converted to the parameter', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false', - })); - typeConverter.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], description: 'NotImplemented -- this will return null', - returnsDescription: 'will always return null.' - })); - typeConverter.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, new LiteralExpression('CanConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - typeConverter.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression('ConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })); + model.add(new LambdaMethod('ToJsonString', dotnet.String, new LiteralExpression(`ToJson(${dotnet.Null}, ${ClientRuntime.SerializationMode.IncludeAll})?.ToString()`), { + description: 'Serializes this instance to a json string.', + returnsDescription: 'a containing this model serialized to JSON text.' + })); - typeConverter.add(new Method('CanConvertFrom', dotnet.Bool, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { description: `the instance to check if it can be converted to the type.` }), - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: `true if the instance could be converted to a type, otherwise false ` - })).add(function* () { - yield If('null == sourceValue', Return(dotnet.True)); + const hashDeseralizer = new NewDeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); + const psDeseralizer = new NewDeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; - - if (schema.language.default.uid === 'universal-parameter-type' || schema.language.csharp?.byReference) { - yield '// we allow string conversion too.'; - yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); - } + // + static FromJsonString(string json); + // + string ToJsonString() - yield If(IsAssignableFrom(PSObject, t), function* () { - yield '// we say yest to PSObjects'; - yield Return(dotnet.True); - }); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), function* () { - yield '// we say yest to Hashtables/dictionaries'; - yield Return(dotnet.True); + // 3. A TypeConverter class + const typeConverter = new Class(ns, converterClass, PSTypeConverter, { + description: `A PowerShell PSTypeConverter to support converting to an instance of `, + fileName: `${className}.TypeConverter` }); - - yield Try(If('null != sourceValue.ToJsonString()', Return(dotnet.True))); - yield Catch(undefined, '// Not one of our objects'); - - yield Try(function* () { - const t = new LocalVariable('text', dotnet.String, { initializer: 'sourceValue.ToString()?.Trim()' }); + typeConverter.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the parameter can be converted to the parameter', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false', + })); + typeConverter.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], description: 'NotImplemented -- this will return null', + returnsDescription: 'will always return null.' + })); + typeConverter.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, new LiteralExpression('CanConvertFrom(sourceValue)'), { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + })); + typeConverter.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression('ConvertFrom(sourceValue)'), { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], + description: 'Converts the parameter to the parameter using and ', + returnsDescription: `an instance of , or null if there is no suitable conversion.` + })); + + typeConverter.add(new Method('CanConvertFrom', dotnet.Bool, { + static: Modifier.Static, + parameters: [ + new Parameter('sourceValue', dotnet.Dynamic, { description: `the instance to check if it can be converted to the type.` }), + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: `true if the instance could be converted to a type, otherwise false ` + })).add(function* () { + yield If('null == sourceValue', Return(dotnet.True)); + + const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); yield t.declarationStatement; - yield Return(`${dotnet.True} == ${t.value}?.StartsWith("{") && ${dotnet.True} == ${t.value}?.EndsWith("}") && ${ClientRuntime.JsonNode.Parse(t)}.Type == ${ClientRuntime.JsonType.Object}`); - }); - yield Catch(undefined, '// Doesn\'t look like it can be treated as JSON'); - yield Return(dotnet.False); - }); + if (schema.language.default.uid === 'universal-parameter-type' || schema.language.csharp?.byReference) { + yield '// we allow string conversion too.'; + yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); + } - typeConverter.add(new Method('ConvertFrom', modelInterface, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { - description: `the value to convert into an instance of .` - }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })).add(function* () { - // null begets null - yield If('null == sourceValue', Return(dotnet.Null)); + yield If(IsAssignableFrom(PSObject, t), function* () { + yield '// we say yest to PSObjects'; + yield Return(dotnet.True); + }); + yield If(IsAssignableFrom(System.Collections.IDictionary, t), function* () { + yield '// we say yest to Hashtables/dictionaries'; + yield Return(dotnet.True); + }); - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; + yield Try(If('null != sourceValue.ToJsonString()', Return(dotnet.True))); + yield Catch(undefined, '// Not one of our objects'); - if (($this.state.project.azure && schema.language.default.uid === 'universal-parameter-type') || schema.language.csharp?.byReference) { - yield '// support direct string to id type conversion.'; - yield If(`${t.value} == typeof(${System.String})`, function* () { - yield Return(`new ${className} { Id = sourceValue }`); + yield Try(function* () { + const t = new LocalVariable('text', dotnet.String, { initializer: 'sourceValue.ToString()?.Trim()' }); + yield t.declarationStatement; + yield Return(`${dotnet.True} == ${t.value}?.StartsWith("{") && ${dotnet.True} == ${t.value}?.EndsWith("}") && ${ClientRuntime.JsonNode.Parse(t)}.Type == ${ClientRuntime.JsonType.Object}`); }); - } + yield Catch(undefined, '// Doesn\'t look like it can be treated as JSON'); - if (schema.language.csharp?.byReference) { - yield '// if Id is present with by-reference schemas, just return the type with Id '; - yield Try(Return(`new ${className} { Id = sourceValue.Id }`)); - yield Catch(undefined, '// Not an Id reference parameter'); - } + yield Return(dotnet.False); + }); - // if the type can be assigned directly, do that - yield If(IsAssignableFrom(td, t), Return('sourceValue')); + typeConverter.add(new Method('ConvertFrom', modelInterface, { + static: Modifier.Static, + parameters: [ + new Parameter('sourceValue', dotnet.Dynamic, { + description: `the value to convert into an instance of .` + }), + ], + description: 'Converts the parameter to the parameter using and ', + returnsDescription: `an instance of , or null if there is no suitable conversion.` + })).add(function* () { + // null begets null + yield If('null == sourceValue', Return(dotnet.Null)); + + const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); + yield t.declarationStatement; - // try using json first (either from string or toJsonString()) - yield Try(Return(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`)); - yield Catch(undefined, '// Unable to use JSON pattern'); + if (($this.state.project.azure && schema.language.default.uid === 'universal-parameter-type') || schema.language.csharp?.byReference) { + yield '// support direct string to id type conversion.'; + yield If(`${t.value} == typeof(${System.String})`, function* () { + yield Return(`new ${className} { Id = sourceValue }`); + }); + } - yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); + if (schema.language.csharp?.byReference) { + yield '// if Id is present with by-reference schemas, just return the type with Id '; + yield Try(Return(`new ${className} { Id = sourceValue.Id }`)); + yield Catch(undefined, '// Not an Id reference parameter'); + } - // null if not successful - yield Return(dotnet.Null); - }); + // if the type can be assigned directly, do that + yield If(IsAssignableFrom(td, t), Return('sourceValue')); + + // try using json first (either from string or toJsonString()) + yield Try(Return(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`)); + yield Catch(undefined, '// Unable to use JSON pattern'); + + yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); + yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); + + // null if not successful + yield Return(dotnet.Null); + }); + } } } } diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index 34b14a091d3..b4de4ebe2b3 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { HttpMethod, codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; //import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; -import { JsonType, processCodeModel, codemodel, components, command, http, ModelState, Schema as SchemaV3 } from '@azure-tools/codemodel-v3'; import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Schema } from '../llcsharp/exports'; @@ -16,6 +15,8 @@ import { verbs } from '../internal/verbs'; import { PwshModel } from '../utils/PwshModel'; import { IParameterPwsh } from '../utils/components'; import { NewModelState } from '../utils/model-state'; +import { Schema as SchemaV3 } from '../utils/schema'; +import { CommandOperation } from '../utils/command-operation'; type State = NewModelState; @@ -303,20 +304,20 @@ export /* @internal */ class Inferrer { } } - - isNameConflict(model: codemodel.Model, variant: CommandVariant, vname: string) { - for (const each of values(model.commands.operations)) { - if (each.details.default.name === vname) { - return true; - } - } - return false; - } + // skip-for-time-being + // isNameConflict(model: codemodel.Model, variant: CommandVariant, vname: string) { + // for (const each of values(model.commands.operations)) { + // if (each.details.default.name === vname) { + // return true; + // } + // } + // return false; + // } // for tracking unique operation identities operationIdentities = new Set(); - async addCommandOperation(vname: string, parameters: Array, operation: Operation, variant: CommandVariant, state: State): Promise { + async addCommandOperation(vname: string, parameters: Array, operation: Operation, variant: CommandVariant, state: State): Promise { // skip-for-time-being following code seems redundant ----- // let apiversion = ''; @@ -358,7 +359,7 @@ export /* @internal */ class Inferrer { // skip-for-time-being x-ms-metadata looks not supported any more. //const xmsMetadata = operation.pathExtensions ? operation.pathExtensions['x-ms-metadata'] ? clone(operation.pathExtensions['x-ms-metadata']) : {} : {}; - return state.model.commands.operations[`${length(state.model.commands.operations)}`] = new command.CommandOperation(operation.language.default.name, { + return state.model.commands.operations[`${length(state.model.commands.operations)}`] = new CommandOperation(operation.language.default.name, { asjob: operation.language.default.asjob ? true : false, extensions: { @@ -421,7 +422,7 @@ export /* @internal */ class Inferrer { //const polymorphicBodies = (body && body.schema && body.schema.details.default.polymorphicChildren && length(body.schema.details.default.polymorphicChildren)) ? (>body.schema.details.default.polymorphicChildren).joinWith(child => child.details.default.name) : ''; // wait! "update" should be "set" if it's a POST - if (variant.verb === 'Update' && operation.requests && operation.requests[0].protocol?.http?.method === http.HttpMethod.Put) { + if (variant.verb === 'Update' && operation.requests && operation.requests[0].protocol?.http?.method === HttpMethod.Put) { variant.verb = 'Set'; } diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 484e8d7f727..898178d4ca1 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -5,7 +5,6 @@ import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; //import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; -import { ModelState } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { System } from '@azure-tools/codegen-csharp'; diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index e64e184a206..220edeb1b55 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -4,14 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -import { Schema, codemodel, JsonType, processCodeModel, VirtualProperty, VirtualParameter, resolveParameterNames, ModelState, getAllProperties, getAllPublicVirtualProperties } from '@azure-tools/codemodel-v3'; +//import { VirtualParameter } from '@azure-tools/codemodel-v3'; import { getPascalIdentifier, removeSequentialDuplicates, pascalCase, fixLeadingNumber, deconstruct, selectName, EnglishPluralizationService, serialize } from '@azure-tools/codegen'; import { length, values, } from '@azure-tools/linq'; import { Host, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +//import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +import { CommandOperation } from '../utils/command-operation'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; - +import { VirtualParameter } from '../utils/command-operation'; function getPluralizationService(): EnglishPluralizationService { const result = new EnglishPluralizationService(); diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 785a2273b28..ca19bbb5c93 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -import { ModelState } from '@azure-tools/codemodel-v3'; +//import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize } from '@azure-tools/codegen'; import { items, keys, values, Dictionary, length } from '@azure-tools/linq'; diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts index 13e71a4e64b..12d8802b7b1 100644 --- a/powershell/plugins/powershell-v2.ts +++ b/powershell/plugins/powershell-v2.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codemodel } from '@azure-tools/codemodel-v3'; +//import { codemodel } from '@azure-tools/codemodel-v3'; import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; import { Host } from '@azure-tools/autorest-extension-base'; import { join } from 'path'; @@ -23,7 +23,7 @@ const sourceFileCSharp = 'source-file-csharp'; const resources = `${__dirname}/../../resources`; -async function copyRequiredFiles(project: Project | NewProject) { +async function copyRequiredFiles(project: NewProject) { const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; // Project assets diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index 20f3fa05386..66d946470c9 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -5,13 +5,14 @@ import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; import { Host, Channel, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames, ModelState, isMediaTypeMultipartFormData, VirtualParameter } from '@azure-tools/codemodel-v3'; +//import { allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames } from '@azure-tools/codemodel-v3'; import { deconstruct, removeProhibitedPrefix, removeSequentialDuplicates, pascalCase, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import * as linq from '@azure-tools/linq'; import { singularize } from '../internal/name-inferrer'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; +import { allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames } from '../utils/resolve-conflicts'; type State = NewModelState; diff --git a/powershell/utils/PwshModel.ts b/powershell/utils/PwshModel.ts index dd05c29465a..bae5a6932e1 100644 --- a/powershell/utils/PwshModel.ts +++ b/powershell/utils/PwshModel.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -import { CommandComponents } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +//import { CommandComponents } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; import { DeepPartial } from '@azure-tools/codegen'; +import { CommandComponents } from '../utils/command-operation'; export class PwshModel extends CodeModel { public commands = new CommandComponents(); diff --git a/powershell/utils/command-operation.ts b/powershell/utils/command-operation.ts new file mode 100644 index 00000000000..a1bbd0f804f --- /dev/null +++ b/powershell/utils/command-operation.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Components, IParameter, LanguageDetails } from './components'; +import { Extensions } from './extensions'; +import { HttpOperation } from './http-operation'; +import { ProgramaticOperationDetails, ProgrammaticOperation } from './programatic-operation'; +import { Schema, VirtualProperty } from './schema'; +import { DeepPartial } from '@azure-tools/codegen'; + +import { uid } from './uid'; +import { Dictionary } from '@azure-tools/linq'; + +export interface VirtualParameters { + body: Array; + operation: Array; +} + +export interface CommandOperationDetails extends ProgramaticOperationDetails { + virtualParameters?: VirtualParameters; +} + +export interface CompleterInfo { + script: string; + name: string; + description: string; +} + +export interface CommandOperation extends ProgrammaticOperation { + alias: Array; + verb: string; + noun: string; + variant: string; + category: string; + asjob: boolean; + callGraph: Array; +} + +export interface VirtualParameter { + name: string; + description: string; + required: boolean; + schema: Schema; + nameOptions: Array; + origin: VirtualProperty | IParameter; + alias: Array; + completerInfo?: CompleterInfo; +} + +export class CommandOperation extends Extensions implements CommandOperation { + public extensions = new Dictionary(); + public details: LanguageDetails; + + public responses = new Dictionary>(); + + constructor(name: string, initializer?: DeepPartial) { + super(); + this.details = { + default: { + uid: `command-operation:${uid()}`, + description: initializer?.description || '', + name, + } + }; + this.deprecated = false; + this.pure = true; + + this.apply(initializer); + } +} + +export interface CommandComponents extends Components { + +} + +export class CommandComponents extends Components { +} diff --git a/powershell/utils/components.ts b/powershell/utils/components.ts index 7dcb38cb51a..fb25f70e2d0 100644 --- a/powershell/utils/components.ts +++ b/powershell/utils/components.ts @@ -4,30 +4,215 @@ *--------------------------------------------------------------------------------------------*/ import { DeepPartial } from '@azure-tools/codegen'; import { Dictionary } from '@azure-tools/linq'; -import { components, Schema } from '@azure-tools/codemodel-v3'; import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { Extensions } from './extensions'; +import { Schema } from './schema'; +import { uid } from './uid'; +export interface IOperationBase { -export class IParameterPwsh extends components.IParameter { - constructor(public name: string, public schema: Schema, public newSchema: NewSchema, initializer?: DeepPartial) { +} + +export interface IParameter extends Extensions { + name: string; + schema: Schema; + description: string; + + allowEmptyValue: boolean; + deprecated: boolean; + required: boolean; + details: LanguageDetails; +} + +export class IParameter extends Extensions { + constructor(public name: string, public schema: Schema, initializer?: DeepPartial) { + super(); + this.description = ''; + this.deprecated = false; + this.required = false; + this.details = { + default: { + uid: `parameter:${uid()}`, + description: this.description, + name, + } + }; + this.allowEmptyValue = false; + this.apply(initializer); + } +} + +export class IParameterPwsh extends IParameter { + constructor(public name: string, public schema: Schema, public newSchema: NewSchema, initializer?: DeepPartial) { super(name, schema); } } -// export class IParameter extends Extensions { -// constructor(public name: string, public schema: Schema, initializer?: DeepPartial) { -// super(); -// this.description = ''; -// this.deprecated = false; -// this.required = false; -// this.details = { -// default: { -// uid: `parameter:${uid()}`, -// description: this.description, -// name, -// } -// }; -// this.allowEmptyValue = false; -// this.apply(initializer); -// } -// } +export interface IOperation extends IOperationBase { + operationId: string; + description: string; + + summary?: string; + deprecated: boolean; + + parameters: Array; +} + +export interface Components, TParameter extends IParameter> extends Extensions { + operations: Dictionary; + parameters: Dictionary; +} + +export class Components, TParameter extends IParameter> extends Extensions implements Components { + /** + * Dictionary of Operations in this model. + * + * This is intended to invert the original PathItems in the OAI model, and focus on operations, not endpoints. + */ + public operations = new Dictionary(); + + constructor(initializer?: DeepPartial>) { + super(); + this.apply(initializer); + } +} + +export interface ParameterDetails extends ImplementationDetails { + +} + +export interface ResponseDetails extends ImplementationDetails { + isErrorResponse: boolean; +} + +/** LanguageDetails contains a map of languages to details for a given node in the code-model */ +export interface LanguageDetails extends Dictionary { + default: T; + +} + +export interface ImplementationDetails extends Dictionary { + /** a unique id for correlation between cloned objects */ + uid: string; + + /** name used in actual implementation */ + name: string; + + /** description text */ + description: string; + + /** message used to go along with deprecation */ + deprecationMessage?: string; +} + +export enum ImplementationLocation { + Method = 'Method', + Client = 'Client', +} + +export class Example extends Extensions implements Example { + extensions = new Dictionary(); + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class ExternalDocumentation extends Extensions implements ExternalDocumentation { + extensions = new Dictionary(); + + constructor(public url: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class Link extends Extensions implements Link { + extensions = new Dictionary(); + parameters = new Dictionary(); + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class Server extends Extensions implements Server { + extensions = new Dictionary(); + variables = new Dictionary(); + + constructor(public url: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class ServerVariable extends Extensions implements ServerVariable { + extensions = new Dictionary(); + enum = new Array(); + + constructor(defaultValue: string, initializer?: DeepPartial) { + super(); + this.default = defaultValue; + this.apply(initializer); + } +} + +export class Tag extends Extensions implements Tag { + extensions = new Dictionary(); + + constructor(public name: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +/** + * @description common ways of serializing simple parameters + * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#style-values + */ + +export interface SecurityRequirement extends Dictionary { +} + +export interface Example extends Extensions { + summary?: string; + description?: string; + value?: any; + externalValue?: string; // uriref +} + +export interface ExternalDocumentation extends Extensions { + description?: string; + url: string; // uriref +} + +export interface Link extends Extensions { + operationRef?: string; // uriref + operationId?: string; + parameters: Dictionary; + requestBody?: any; + description?: string; + server?: Server; +} + +export interface Server extends Extensions { + + url: string; + description?: string; + variables: Dictionary; +} + +export interface ServerVariable extends Extensions { + enum: Array; + default: string; + description?: string; +} + +export interface Tag extends Extensions { + + name: string; + description?: string; + externalDocs?: ExternalDocumentation; +} diff --git a/powershell/utils/extensions.ts b/powershell/utils/extensions.ts new file mode 100644 index 00000000000..707de2c3eac --- /dev/null +++ b/powershell/utils/extensions.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Initializer, DeepPartial } from '@azure-tools/codegen'; +import { Dictionary } from '@azure-tools/linq'; + +export class Extensions extends Initializer implements Extensions { + extensions = new Dictionary(); + + constructor() { + super(); + } +} + +export interface Extensions { + /** additional metadata extensions */ + extensions: Dictionary; +} diff --git a/powershell/utils/http-operation.ts b/powershell/utils/http-operation.ts new file mode 100644 index 00000000000..ad0e989a692 --- /dev/null +++ b/powershell/utils/http-operation.ts @@ -0,0 +1,300 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Components, Example, ExternalDocumentation, ImplementationDetails, ImplementationLocation, IOperation, IOperationBase, IParameter, LanguageDetails, Link, ParameterDetails, ResponseDetails, SecurityRequirement, Server } from './components'; +import { Extensions } from './extensions'; +import { Schema } from './schema'; +import { SecurityScheme } from './security-scheme'; +import { DeepPartial } from '@azure-tools/codegen'; +import { Dictionary } from '@azure-tools/linq'; +import { uid } from './uid'; + +export interface HttpOperationDetails extends ImplementationDetails { +} + +/** + * An encoding attribute is introduced to give you control over the serialization of parts of multipart request bodies. + * This attribute is only applicable to multipart and application/x-www-form-urlencoded request bodies. +*/ +export class Encoding extends Extensions implements Encoding { + public headers = new Array
(); + + constructor(public key: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class Header extends Extensions implements Header { + + public content = new Array(); + + constructor(initializer?: DeepPartial
) { + super(); + this.apply(initializer); + } +} + +export class MediaType extends Extensions implements MediaType { + public encoding = new Array(); + public accepts = new Array(); + + constructor(public key: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class RequestBody extends Extensions implements RequestBody { + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class Response extends Extensions implements Response { + + public content = new Dictionary(); + public links = new Dictionary(); + public headers = new Array
(); + + constructor(public description: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export enum ParameterLocation { + Uri = 'uri', + Query = 'query', + Header = 'header', + Cookie = 'cookie', + Path = 'path', +} + +export enum EncodingStyle { + Matrix = 'matrix', + Label = 'label', + Simple = 'simple', + Form = 'form', + SpaceDelimited = 'spaceDelimited', + PipeDelimited = 'pipeDelimited', + DeepObject = 'deepObject' +} + +export type QueryEncodingStyle = + EncodingStyle.Form + | EncodingStyle.SpaceDelimited + | EncodingStyle.PipeDelimited + | EncodingStyle.DeepObject; +export type PathEncodingStyle = EncodingStyle.Matrix | EncodingStyle.Label | EncodingStyle.Simple; + +export interface Encoding extends Extensions { + key: string; + contentType?: string; + headers: Array
; + style?: QueryEncodingStyle; + explode?: boolean; + allowReserved?: boolean; +} + +export interface Header extends Extensions { + key: string; + schema: Schema; + explode?: boolean; + examples: Dictionary; + + description?: string; + required: boolean; + deprecated: boolean; + allowEmptyValue: boolean; + allowReserved: boolean; +} + +export interface MediaType extends Extensions { + key: string; + accepts: Array; // equivalent media types for this media type (ie, text/json, application/json) + examples: Array; + encoding: Array; + schema?: Schema; +} + +export interface RequestBody extends Extensions { + description?: string; + contentType: string; + schema: Schema; + required: boolean; +} + +export interface Response extends Extensions { + description: string; + headers: Array
; + content: Dictionary; + links: Dictionary; +} + +export interface HttpParameterDetails extends ParameterDetails { + location: ImplementationLocation; +} + +export enum HttpMethod { + Get = 'get', + Put = 'put', + Post = 'post', + Delete = 'delete', + Options = 'options', + Head = 'head', + Patch = 'patch', + Trace = 'trace' +} + +export interface NewResponse { + details: LanguageDetails; + responseCode: string; + description: string; + headers: Array
; + headerSchema?: Schema; + mimeTypes: Array; // accepted equivalent media types for this media type (ie, text/json, application/json) + schema?: Schema; +} + +export class NewResponse extends Extensions implements NewResponse { + public details: LanguageDetails; + + constructor(public responseCode: string, public description: string, public mimeTypes: Array, objectInitializer?: DeepPartial) { + super(); + this.details = { + default: { + uid: `response:${uid()}`, + isErrorResponse: false, + description: description || objectInitializer?.description || '', + name: `${responseCode} ${mimeTypes.join(' ')}`, + } + }; + this.headers = new Array
(); + this.apply(objectInitializer); + } +} + +export class HttpOperation extends Extensions implements HttpOperation { + public details: LanguageDetails; + public tags = new Array(); + public parameters = new Array(); + public responses = new Dictionary>(); + public callbacks = new Dictionary(); + public security = new Array(); + public servers = new Array(); + public deprecated = false; + + constructor(operationId: string, public baseUrl: string, public path: string, public method: HttpMethod, initializer?: DeepPartial) { + super(); + this.details = { + default: { + uid: `http-operation:${uid()}`, + description: initializer?.description || '', + name: operationId, + } + }; + + this.apply(initializer); + } +} + +export interface HttpOperation extends IOperation, Extensions { + details: LanguageDetails; + + tags: Array; + summary?: string; + + externalDocs?: ExternalDocumentation; + + parameters: Array; + requestBody?: RequestBody; + responses: Dictionary>; + + callbacks: Dictionary; + deprecated: boolean; + security: Array; + servers: Array; + + path: string; + baseUrl: string; + method: HttpMethod; + pathDescription?: string; + pathSummary?: string; + pathExtensions?: Dictionary; +} + +export interface HttpOperationParameter extends IParameter { + + in: ParameterLocation; + explode?: boolean; + + encoding?: Array; + mediaType?: string; + style: EncodingStyle; + examples?: Dictionary; + allowReserved?: boolean; +} + +export class HttpOperationParameter extends Extensions implements HttpOperationParameter { + + public details: LanguageDetails; + public deprecated = false; + public required = false; + public allowEmptyValue = false; + + constructor(public name: string, inWhere: ParameterLocation, implementation: ImplementationLocation, initializer?: DeepPartial) { + super(); + this.in = inWhere; + this.details = { + default: { + uid: `http-parameter:${uid()}`, + description: initializer?.description || '', + location: implementation, + name, + } + }; + this.required = inWhere === ParameterLocation.Path; + this.apply(initializer); + } +} + +export function isHttpOperation(operation: IOperationBase): operation is HttpOperation { + if ((operation).path) { + return true; + } + return false; +} + +export class Callback implements Callback { + constructor() { + // unimplemented. + } +} + +export interface Callback extends Dictionary { +} + +export interface HttpComponents extends Components { + + examples: Dictionary; + securitySchemes: Dictionary; + links: Dictionary; + callbacks: Dictionary; +} + +export class HttpComponents extends Components implements HttpComponents { + public examples = new Dictionary(); + public securitySchemes = new Dictionary(); + public links = new Dictionary(); + public callbacks = new Dictionary(); + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} diff --git a/powershell/utils/info.ts b/powershell/utils/info.ts new file mode 100644 index 00000000000..e2722389ed3 --- /dev/null +++ b/powershell/utils/info.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Extensions } from './extensions'; +import { Dictionary } from '@azure-tools/linq'; +import { DeepPartial } from '@azure-tools/codegen'; + +export class Contact extends Extensions implements Contact { + extensions = new Dictionary(); + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class Info extends Extensions implements Info { + extensions = new Dictionary(); + + constructor(public title: string, public version: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class License extends Extensions implements License { + extensions = new Dictionary(); + + constructor(public name: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export interface Contact extends Extensions { + name?: string; + url?: string; // uriref + email?: string; // email +} + +export interface Info extends Extensions { + title: string; + description?: string; + termsOfService?: string; // uriref + contact?: Contact; + license?: License; + version: string; +} + +export interface License extends Extensions { + name: string; + url?: string; // uriref +} diff --git a/powershell/utils/programatic-operation.ts b/powershell/utils/programatic-operation.ts new file mode 100644 index 00000000000..2873889bf26 --- /dev/null +++ b/powershell/utils/programatic-operation.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ImplementationDetails, IOperation, IParameter, LanguageDetails } from './components'; +import { Extensions } from './extensions'; +import { Schema } from './schema'; +import { Dictionary } from '@azure-tools/linq'; +import { uid } from './uid'; +import { DeepPartial } from '@azure-tools/codegen'; + +export interface ProgrammaticOperation extends IOperation { + responses: Dictionary>; + pure: boolean; // side-effect free? May be helpful for deciding how to generate code. +} + +export interface IntrinsicOperation extends ProgrammaticOperation { + +} + +export class IntrinsicOperation extends Extensions implements IntrinsicOperation { + public details: LanguageDetails; + + public responses = new Dictionary>(); + public operationType: 'IntrinsicOperation' = 'IntrinsicOperation'; + + constructor(name: string, deprecated: boolean, pure: boolean, initializer?: DeepPartial) { + super(); + this.details = { + default: { + uid: `intrinsic-operation:${uid()}`, + description: initializer?.description || '', + name, + } + }; + this.deprecated = deprecated; + this.pure = pure; + + this.apply(initializer); + } +} + +export interface ProgramaticOperationDetails extends ImplementationDetails { +} diff --git a/powershell/utils/resolve-conflicts.ts b/powershell/utils/resolve-conflicts.ts new file mode 100644 index 00000000000..ce9f4a6b62c --- /dev/null +++ b/powershell/utils/resolve-conflicts.ts @@ -0,0 +1,60 @@ +import { VirtualProperties } from './schema'; +import { VirtualParameters, VirtualParameter } from './command-operation'; +import { selectName } from '@azure-tools/codegen'; +import { values } from '@azure-tools/linq'; + +export function resolvePropertyNames(reservedNames: Iterable, virtualProperties: VirtualProperties) { + const usedNames = new Set(reservedNames); + + const allProps = values(virtualProperties.owned, virtualProperties.inherited, virtualProperties.inlined).toArray(); + + for (const prop of allProps) { + if (usedNames.has(prop.name)) { + prop.name = selectName(prop.nameOptions, usedNames); + } else { + usedNames.add(prop.name); + } + } + +} + +export function resolveParameterNames(reservedNames: Iterable, virtualParameters: VirtualParameters) { + const usedNames = new Set(reservedNames); + const collisions = new Set(); + + // we need to make sure we avoid name collisions. operation parameters get first crack. + for (const each of values(virtualParameters.operation)) { + if (usedNames.has(each.name)) { + collisions.add(each); + } else { + usedNames.add(each.name); + } + } + + // handle operation parameters + for (const each of collisions) { + each.name = selectName(each.nameOptions, usedNames); + } + collisions.clear(); + + // now do body parameters. + for (const each of values(virtualParameters.body)) { + if (usedNames.has(each.name)) { + collisions.add(each); + } else { + usedNames.add(each.name); + } + } + + for (const each of collisions) { + each.name = selectName(each.nameOptions, usedNames); + } +} + +export function allVirtualProperties(virtualProperties?: VirtualProperties) { + return virtualProperties ? values(virtualProperties.owned, virtualProperties.inherited, virtualProperties.inlined).toArray() : []; +} + +export function allVirtualParameters(virtualParameters?: VirtualParameters) { + return virtualParameters ? values(virtualParameters.operation, virtualParameters.body).toArray() : []; +} \ No newline at end of file diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts new file mode 100644 index 00000000000..ea040643a5e --- /dev/null +++ b/powershell/utils/schema.ts @@ -0,0 +1,296 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; + +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; + name: string; +} + +export enum Purpose { + Header = 'Header', +} + +export interface VirtualProperty { + /** The property that this represents */ + property: Property; + + /** The things that went into building the name */ + nameComponents: Array; + + /** Names To use in priority order */ + nameOptions: Array; + + /** 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; + + description: string; + + format?: PropertyFormat; + + required: boolean; + + sharedWith?: Array; +} + + +interface PropertyFormat { + suppressFormat?: boolean; + index?: number; + width?: number; + label?: string; +} + +export interface VirtualProperties { + owned: Array; + inherited: Array; + inlined: Array; +} + +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; +} + +export class Schema extends Extensions implements Schema { + public details: LanguageDetails; + public required = new Array(); + public enum = new Array(); + public allOf = new Array(); + public oneOf = new Array(); + public anyOf = new Array(); + public properties = new Dictionary(); + public extensions = new Dictionary(); + + constructor(name: string, initializer?: DeepPartial) { + super(); + this.details = { + default: { + uid: `schema:${uid()}`, + description: '', + name + } + }; + this.apply(initializer); + } +} + +export function getPolymorphicBases(schema: Schema): Array { + // are any of my parents polymorphic directly, or any of their parents? + return [...values(schema.allOf).where(parent => parent.discriminator ? true : false), ...values(schema.allOf).selectMany(getPolymorphicBases)]; +} + +export function getAllProperties(schema: Schema): Array { + return [...values(schema.allOf).selectMany(getAllProperties), ...values(schema.properties)]; +} + +export function getAllPublicVirtualProperties(virtualProperties?: VirtualProperties): Array { + const props = virtualProperties || { + owned: [], + inherited: [], + inlined: [] + }; + + return values(props.owned, props.inherited, props.inlined).where(each => !each.private).toArray(); +} + +export function getAllVirtualProperties(virtualProperties?: VirtualProperties): Array { + 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; + + /** 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; + public extensions = new Dictionary(); + + constructor(name: string, initializer?: DeepPartial) { + 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(); + public mapping = new Dictionary(); + + constructor(public propertyName: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export interface Discriminator extends Extensions { + propertyName: string; + mapping: Dictionary; +} + +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 === type : 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(); + public attribute = false; + public wrapped = false; + + constructor(initializer?: DeepPartial) { + 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; + + /* common properties */ + type?: JsonType; + title?: string; + description?: string; + format?: string; + nullable: boolean; + readOnly: boolean; + writeOnly: boolean; + deprecated: boolean; + required: Array; + + /* 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; + + /* properties with potential references */ + not?: Schema; + allOf: Array; + oneOf: Array; + anyOf: Array; + items?: Schema; + properties: Dictionary; + additionalProperties?: boolean | Schema; +} diff --git a/powershell/utils/security-scheme.ts b/powershell/utils/security-scheme.ts new file mode 100644 index 00000000000..5ad1d05e51b --- /dev/null +++ b/powershell/utils/security-scheme.ts @@ -0,0 +1,192 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Extensions } from './extensions'; +import { ParameterLocation } from './http-operation'; +import { Dictionary } from '@azure-tools/linq'; +import { DeepPartial } from '@azure-tools/codegen'; + +export enum Scheme { + Bearer = 'bearer' +} +export enum SecurityType { + ApiKey = 'apiKey', + Http = 'http', + OAuth2 = 'oauth2', + OpenIDConnect = 'openIdConnect' +} + +export class APIKeySecurityScheme extends Extensions implements APIKeySecurityScheme { + extensions = new Dictionary(); + + constructor(public name: string, inWhere: ParameterLocation, initializer?: DeepPartial) { + super(); + this.in = inWhere; + this.type = SecurityType.ApiKey; + this.apply(initializer); + } +} + +export class BearerHTTPSecurityScheme extends Extensions implements BearerHTTPSecurityScheme { + extensions = new Dictionary(); + scheme = Scheme.Bearer; + + constructor(initializer?: DeepPartial) { + super(); + this.type = SecurityType.Http; + this.apply(initializer); + } +} + +export class ImplicitOAuthFlow extends Extensions implements ImplicitOAuthFlow { + extensions = new Dictionary(); + scopes = new Dictionary(); + + constructor(public authorizationUrl: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export class NonBearerHTTPSecurityScheme extends Extensions implements NonBearerHTTPSecurityScheme { + extensions = new Dictionary(); + + constructor(public scheme: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + this.type = SecurityType.Http; + } +} + +export class OAuth2SecurityScheme extends Extensions implements OAuth2SecurityScheme { + extensions = new Dictionary(); + + constructor(public flows: OAuthFlows, initializer?: DeepPartial) { + super(); + this.type = SecurityType.OAuth2; + this.apply(initializer); + } + +} + +export class OAuthFlows extends Extensions implements OAuthFlows { + extensions = new Dictionary(); + + constructor(initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export interface OpenIdConnectSecurityScheme extends Extensions { + + type: SecurityType.OpenIDConnect; + openIdConnectUrl: string; // url + description?: string; +} + +export class OpenIdConnectSecurityScheme extends Extensions implements OpenIdConnectSecurityScheme { + extensions = new Dictionary(); + + constructor(public openIdConnectUrl: string, initializer?: DeepPartial) { + super(); + this.type = SecurityType.OpenIDConnect; + this.apply(initializer); + } +} + +export interface PasswordOAuthFlow extends Extensions { + + tokenUrl: string; // uriref + refreshUrl?: string; // uriref + scopes: Dictionary; +} + +export class PasswordOAuthFlow extends Extensions implements PasswordOAuthFlow { + extensions = new Dictionary(); + scopes = new Dictionary(); + + constructor(public tokenUrl: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export type HTTPSecurityScheme = NonBearerHTTPSecurityScheme | BearerHTTPSecurityScheme; +export type SecurityScheme = + APIKeySecurityScheme + | HTTPSecurityScheme + | OAuth2SecurityScheme + | OpenIdConnectSecurityScheme; + +export interface APIKeySecurityScheme extends Extensions { + + type: SecurityType.ApiKey; + name: string; + in: ParameterLocation; + description?: string; +} + +export class AuthorizationCodeOAuthFlow extends Extensions implements AuthorizationCodeOAuthFlow { + extensions = new Dictionary(); + scopes = new Dictionary(); + constructor(public authorizationUrl: string, tokenUrl: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} +export class ClientCredentialsFlow extends Extensions implements ClientCredentialsFlow { + extensions = new Dictionary(); + scopes = new Dictionary(); + constructor(public tokenUrl: string, initializer?: DeepPartial) { + super(); + this.apply(initializer); + } +} + +export interface AuthorizationCodeOAuthFlow extends Extensions { + authorizationUrl: string; // uriref + tokenUrl: string; // uriref + refreshUrl?: string; // uriref + scopes: Dictionary; +} + +export interface BearerHTTPSecurityScheme extends Extensions { + scheme: Scheme.Bearer; + bearerFormat?: string; + type: SecurityType.Http; + description?: string; +} + +export interface ClientCredentialsFlow extends Extensions { + tokenUrl: string; // uriref + refreshUrl?: string; // uriref + scopes: Dictionary; +} + +export interface ImplicitOAuthFlow extends Extensions { + authorizationUrl: string; // uriref + refreshUrl?: string; // uriref + scopes: Dictionary; +} + +export interface NonBearerHTTPSecurityScheme extends Extensions { + scheme: string; + description?: string; + type: SecurityType.Http; +} + +export interface OAuth2SecurityScheme extends Extensions { + type: SecurityType.OAuth2; + flows: OAuthFlows; + description?: string; +} + +export interface OAuthFlows extends Extensions { + implicit?: ImplicitOAuthFlow; + password?: PasswordOAuthFlow; + clientCredentials?: ClientCredentialsFlow; + authorizationCode?: AuthorizationCodeOAuthFlow; +} diff --git a/powershell/utils/uid.ts b/powershell/utils/uid.ts new file mode 100644 index 00000000000..dbeb7ffd9db --- /dev/null +++ b/powershell/utils/uid.ts @@ -0,0 +1,5 @@ +let n = 0; + +export function uid() { + return n++; +} \ No newline at end of file From 7e407b224812f94ea1fb812776a021c73fa6a47b Mon Sep 17 00:00:00 2001 From: derek Date: Mon, 13 Jul 2020 15:22:52 +0800 Subject: [PATCH 03/61] Reimplement CmdletClass based on modelerfour --- powershell/cmdlets/class.ts | 1261 ++++++++++++++++- powershell/cmdlets/namespace.ts | 4 +- powershell/internal/project.ts | 2 +- powershell/models/model-extensions.ts | 14 +- powershell/plugins/create-commands-v2.ts | 10 +- .../plugin-create-inline-properties.ts | 2 +- powershell/plugins/ps-namer-v2.ts | 2 +- powershell/utils/command-operation.ts | 7 +- powershell/utils/components.ts | 10 +- powershell/utils/http-operation.ts | 582 ++++---- powershell/utils/programatic-operation.ts | 3 +- powershell/utils/schema.ts | 229 +-- 12 files changed, 1688 insertions(+), 438 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 6b7c132b8cb..bf22d717ff5 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -3,8 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter } from '@azure-tools/codemodel'; import { command, getAllProperties, JsonType, http, getAllPublicVirtualProperties, getVirtualPropertyFromPropertyName, ParameterLocation, getAllVirtualProperties, VirtualParameter, VirtualProperty } from '@azure-tools/codemodel-v3'; +import { CommandOperation, VirtualParameter as NewVirtualParameter } from '../utils/command-operation'; +import { getAllProperties as NewGetAllProperties, getAllPublicVirtualProperties as NewGetAllPublicVirtualProperties, getVirtualPropertyFromPropertyName as NewGetVirtualPropertyFromPropertyName, VirtualProperty as NewVirtualProperty } from '../utils/schema'; import { escapeString, docComment, serialize, pascalCase, DeepPartial } from '@azure-tools/codegen'; import { items, values, Dictionary, length } from '@azure-tools/linq'; import { @@ -16,6 +18,7 @@ import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, Cmdle import { State, NewState } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; import { IParameter } from '@azure-tools/codemodel-v3/dist/code-model/components'; +import { IParameter as NewIParameter } from '../utils/components'; import { Variable, Local, ParameterModifier } from '@azure-tools/codegen-csharp'; import { getVirtualPropertyName } from '../llcsharp/model/model-class'; const PropertiesRequiringNew = new Set(['Host', 'Events']); @@ -153,6 +156,17 @@ export function addCompleterInfo(targetProperty: Property, parameter: VirtualPar } } +export function NewAddCompleterInfo(targetProperty: Property, parameter: NewVirtualParameter) { + if (parameter.completerInfo && parameter.completerInfo.script) { + targetProperty.add(new Attribute(ClientRuntime.CompleterInfoAttribute, { + parameters: [ + new LiteralExpression(`\nName = ${new StringExpression(parameter.completerInfo.name || '').value}`), + new LiteralExpression(`\nDescription =${new StringExpression(parameter.completerInfo.description || '').value}`), + new LiteralExpression(`\nScript = ${new StringExpression(parameter.completerInfo.script).value}`) + ] + })); + } +} export function addDefaultInfo(targetProperty: Property, parameter: any) { if (parameter.defaultInfo && parameter.defaultInfo.script) { @@ -172,15 +186,15 @@ export function addInfoAttribute(targetProperty: Property, pType: TypeDeclaratio while (pt.elementType) { switch (pt.elementType.schema.type) { case JsonType.Object: - if (pt.elementType.schema.details.csharp.interfaceImplementation) { + if (pt.elementType.schema.language.csharp.interfaceImplementation) { pt = { - declaration: pt.elementType.schema.details.csharp.interfaceImplementation.declaration, + declaration: pt.elementType.schema.language.csharp.interfaceImplementation.declaration, schema: pt.elementType.schema, }; } else { // arg! it's not done yet. Hope it's not polymorphic itself. pt = { - declaration: `${pt.elementType.schema.details.csharp.namespace}.${pt.elementType.schema.details.csharp.interfaceName}`, + declaration: `${pt.elementType.schema.language.csharp.namespace}.${pt.elementType.schema.language.csharp.interfaceName}`, schema: pt.elementType.schema, }; } @@ -196,13 +210,13 @@ export function addInfoAttribute(targetProperty: Property, pType: TypeDeclaratio } } const ptypes = new Array(); - if (pt.schema && pt.schema && pt.schema.details.csharp.byReference) { - ptypes.push(`typeof(${pt.schema.details.csharp.namespace}.${pt.schema.details.csharp.interfaceName}_Reference)`); + if (pt.schema && pt.schema && pt.schema.language.csharp.byReference) { + ptypes.push(`typeof(${pt.schema.language.csharp.namespace}.${pt.schema.language.csharp.interfaceName}_Reference)`); // do we need polymorphic types for by-resource ? Don't think so. } else { ptypes.push(`typeof(${pt.declaration})`); - if (pt.schema && pt.schema.details.csharp.classImplementation && pt.schema.details.csharp.classImplementation.discriminators) { - ptypes.push(...[...pt.schema.details.csharp.classImplementation.discriminators.values()].map(each => `typeof(${each.modelInterface.fullName})`)); + if (pt.schema && pt.schema.language.csharp.classImplementation && pt.schema.language.csharp.classImplementation.discriminators) { + ptypes.push(...[...pt.schema.language.csharp.classImplementation.discriminators.values()].map(each => `typeof(${each.modelInterface.fullName})`)); } } @@ -1411,6 +1425,1237 @@ export class CmdletClass extends Class { passThru.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); } + this.add(new Attribute(DescriptionAttribute, { parameters: [new StringExpression(this.description)] })); + this.add(new Attribute(GeneratedAttribute)); + if (operation.extensions && operation.extensions['x-ms-metadata'] && operation.extensions['x-ms-metadata'].profiles) { + const profileNames = Object.keys(operation.extensions && operation.extensions['x-ms-metadata'].profiles); + // wrap profile names + profileNames.forEach((element, index) => { + profileNames[index] = `"${element}"`; + }); + + this.add(new Attribute(ProfileAttribute, { parameters: [...profileNames] })); + } + } +} + +export class NewCmdletClass extends Class { + private cancellationToken!: Expression; + public state: NewState; + private readonly eventListener: EventListener; + private readonly dropBodyParameter: boolean; + private invocationInfo!: Property; + correlationId!: Field; + processRecordId!: Field; + defaultProfile!: Property; + private readonly thingsToSerialize: Array; + private bodyParameter?: Variable; + private bodyParameterInfo?: { type: TypeDeclaration; valueType: TypeDeclaration }; + private apProp?: Property; + private operation: CommandOperation; + private debugMode?: boolean; + private variantName: string; + private isViaIdentity: boolean; + private hasStreamOutput: boolean; + private outFileParameter?: Property; + + constructor(namespace: Namespace, operation: CommandOperation, state: NewState, objectInitializer?: DeepPartial) { + // generate the 'variant' part of the name + const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; + const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; + + const name = `${operation.details.csharp.verb}${variantName}`; + super(namespace, name, PSCmdlet); + this.dropBodyParameter = operation.details.csharp.dropBodyParameter ? true : false; + this.apply(objectInitializer); + this.operation = operation; + this.state = state; + this.thingsToSerialize = []; + this.variantName = variantName; + this.hasStreamOutput = false; + + this.interfaces.push(ClientRuntime.IEventListener); + this.eventListener = new EventListener(new LiteralExpression(`((${ClientRuntime.IEventListener})this)`), true); + + this.isViaIdentity = variantName.indexOf('ViaIdentity') > 0; + + } + + async init() { + + // basic stuff + this.addCommonStuff(); + + this.description = escapeString(this.operation.details.csharp.description); + const $this = this; + + this.add(new Method('BeginProcessing', dotnet.Void, { + override: Modifier.Override, + access: Access.Protected, + description: `(overrides the default BeginProcessing method in ${PSCmdlet})`, + *body() { + yield 'Module.Instance.SetProxyConfiguration(Proxy, ProxyCredential, ProxyUseDefaultCredentials);'; + yield If($this.$('Break'), `${ClientRuntime.AttachDebugger}.Break();`); + + yield $this.eventListener.syncSignal(Events.CmdletBeginProcessing); + } + })); + + // construct the class + this.NewAddClassAttributes(this.operation, this.variantName); + if (this.hasStreamOutput) { + this.outFileParameter = this.add(new Property('OutFile', System.String, { attributes: [], description: 'Path to write output file to.' })); + this.outFileParameter.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = true', 'HelpMessage = "Path to write output file to"'] })); + this.outFileParameter.add(new Attribute(ValidateNotNull)); + this.outFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); + } + + this.NewAddPowershellParameters(this.operation); + + // implement IEventListener + this.implementIEventListener(); + + // add constructors + this.implementConstructors(); + + // processRecord + this.NewImplementProcessRecord(this.operation); + + this.NewImplementProcessRecordAsync(this.operation); + this.debugMode = await this.state.getValue('debug', false); + + // json serialization + this.NewImplementSerialization(this.operation); + + for (const prop of this.properties) { + if (prop.name === 'Host') { + prop['new'] = Modifier.New; + } + } + + return this; + } + + public get headerComment(): string { + const header = super.headerComment; + const ops = ''; + + for (const httpOperation of values(this.operation.callGraph)) { + // ops = `${ops}\n[OpenAPI] ${httpOperation.operationId}=>${httpOperation.method.toUpperCase()}:"${httpOperation.path}"`; + // skip-for-time-being + // if (this.debugMode) { + // const m = (httpOperation.extensions && httpOperation.extensions['x-ms-metadata']) || (httpOperation.pathExtensions ? httpOperation.pathExtensions['x-ms-metadata'] : undefined); + // if (m) { + // ops = `${ops}\n [METADATA]\n${serialize(m)}`; + // } + + // ops = `${ops}\n [DETAILS]`; + // ops = `${ops}\n verb: ${this.operation.details.csharp.verb}`; + // ops = `${ops}\n subjectPrefix: ${this.operation.details.csharp.subjectPrefix}`; + // ops = `${ops}\n subject: ${this.operation.details.csharp.subject}`; + // ops = `${ops}\n variant: ${this.operation.details.csharp.name}`; + // } + } + + return ops ? `${header}\n${docComment(xmlize('remarks', ops))}` : header; + } + + private addCommonStuff() { + + // add a private copy of invocation information for our own uses. + const privateInvocationInfo = this.add(new Field('__invocationInfo', InvocationInfo, { description: 'A copy of the Invocation Info (necessary to allow asJob to clone this cmdlet)', access: Access.Private })); + this.invocationInfo = new Property('InvocationInformation', InvocationInfo, { description: 'Accessor for our copy of the InvocationInfo.' }); + this.invocationInfo.get = toExpression(`${privateInvocationInfo.value} = ${privateInvocationInfo.value} ?? this.MyInvocation `); + this.invocationInfo.set = new Statements(privateInvocationInfo.assign('value')); + this.add(this.invocationInfo); + + if (this.state.project.azure) { + this.correlationId = this.add(new Field('__correlationId', dotnet.String, { initialValue: 'System.Guid.NewGuid().ToString()', description: 'A unique id generatd for the this cmdlet when it is instantiated.', access: Access.Private })); + this.processRecordId = this.add(new Field('__processRecordId', dotnet.String, { description: 'A unique id generatd for the this cmdlet when ProcessRecord() is called.', access: Access.Private })); + } + + // pipeline property + this.add(new Property('Pipeline', ClientRuntime.HttpPipeline, { getAccess: Access.Private, setAccess: Access.Private, description: `The instance of the that the remote call will use.` })); + + // client API property (gs01: fill this in correctly) + const clientAPI = new ClassType(this.state.model.language.csharp?.namespace, this.state.model.language.csharp?.name || ''); + this.add(new LambdaProperty('Client', clientAPI, new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.ClientAPI`), { description: 'The reference to the client API class.' })); + + this.add(new Method('StopProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Interrupts currently running code within the command.' })).add(function* () { + yield `((${ClientRuntime.IEventListener})this).Cancel();`; + yield 'base.StopProcessing();'; + }); + + const $this = this; + this.add(new Method('EndProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Performs clean-up after the command execution' })).add(function* () { + // gs01: remember what you were doing here to make it so these can be parallelized... + yield ''; + yield $this.eventListener.syncSignal(Events.CmdletEndProcessing); + }); + + // debugging + const brk = this.add(new Property('Break', SwitchParameter, { attributes: [], description: 'Wait for .NET debugger to attach' })); + brk.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Wait for .NET debugger to attach"'] })); + brk.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + // Cmdlet Parameters for pipeline manipulations. + const prepend = this.add(new Property('HttpPipelinePrepend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be prepended to the front of the pipeline' })); + prepend.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be prepended to the front of the pipeline"'] })); + prepend.add(new Attribute(ValidateNotNull)); + prepend.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + const append = this.add(new Property('HttpPipelineAppend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be appended to the front of the pipeline' })); + append.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be appended to the front of the pipeline"'] })); + append.add(new Attribute(ValidateNotNull)); + append.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + const proxyCredential = this.add(new Property('ProxyCredential', PSCredential, { attributes: [], description: 'Credentials for a proxy server to use for the remote call' })); + proxyCredential.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Credentials for a proxy server to use for the remote call"'] })); + proxyCredential.add(new Attribute(ValidateNotNull)); + proxyCredential.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + const useDefaultCreds = this.add(new Property('ProxyUseDefaultCredentials ', SwitchParameter, { attributes: [], description: 'Use the default credentials for the proxy' })); + useDefaultCreds.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Use the default credentials for the proxy"'] })); + useDefaultCreds.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + const proxyUri = this.add(new Property('Proxy', System.Uri, { attributes: [], description: 'The URI for the proxy server to use' })); + proxyUri.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "The URI for the proxy server to use"'] })); + proxyUri.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + if (this.state.project.azure) { + this.defaultProfile = this.add(new Property('DefaultProfile', PSObject, { description: 'The credentials, account, tenant, and subscription used for communication with Azure' })); + this.defaultProfile.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "The credentials, account, tenant, and subscription used for communication with Azure."'] })); + this.defaultProfile.add(new Attribute(ValidateNotNull)); + this.defaultProfile.add(new Attribute(Alias, { parameters: ['"AzureRMContext"', '"AzureCredential"'] })); + this.defaultProfile.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Azure`] })); + } + } + + + private NewIsWritableCmdlet(operation: CommandOperation): boolean { + if (operation.callGraph[0].requests) { + switch (operation.callGraph[0].requests[0]?.protocol.http?.method.toLowerCase()) { + case 'put': + case 'post': + case 'delete': + case 'patch': + return true; + } + } + return false; + } + + + private NewImplementProcessRecord(operation: CommandOperation) { + const $this = this; + const writable = this.NewIsWritableCmdlet(operation); + + this.add(new Method('ProcessRecord', undefined, { access: Access.Protected, override: Modifier.Override, description: 'Performs execution of the command.' })).add(function* () { + yield $this.eventListener.syncSignal(Events.CmdletProcessRecordStart); + if ($this.state.project.azure) { + yield $this.processRecordId.assign('System.Guid.NewGuid().ToString()'); + } + yield Try(function* () { + yield '// work'; + const normal = new Statements(function* () { + const acr = new LocalVariable('asyncCommandRuntime', dotnet.Var, { initializer: AsyncCommandRuntime.new(dotnet.This, $this.cancellationToken) }); + yield Using(acr.declarationExpression, function* () { + yield `${acr}.Wait( ProcessRecordAsync(),${$this.cancellationToken});`; + }); + }); + + if (operation.asjob) { + const asjob = $this.add(new Property('AsJob', SwitchParameter, { description: 'when specified, runs this cmdlet as a PowerShell job' })); + asjob.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command as a job"'] })); + asjob.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + const nowait = $this.add(new Property('NoWait', SwitchParameter, { description: 'when specified, will make the remote call, and return an AsyncOperationResponse, letting the remote operation continue asynchronously.' })); + nowait.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command asynchronously"'] })); + nowait.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + + } + + const work: OneOrMoreStatements = operation.asjob ? function* () { + yield If('true == MyInvocation?.BoundParameters?.ContainsKey("AsJob")', function* () { + // clone the cmdlet instance, since the instance can be reused and overwrite data. + const instance = new LocalVariable('instance', dotnet.Var, { initializer: 'this.Clone()' }); + yield instance.declarationStatement; + + // create the job (which will set the CommandRuntime of the clone to the AsyncJob itself) + const job = new LocalVariable('job', dotnet.Var, { initializer: AsyncJob.new(instance, 'this.MyInvocation.Line, this.MyInvocation.MyCommand.Name, this._cancellationTokenSource.Token', 'this._cancellationTokenSource.Cancel') }); + yield job.declarationStatement; + + // add the job to the repository + yield `JobRepository.Add(${job});`; + + // invoke the cmdlet's PRA + const task = new LocalVariable('task', dotnet.Var, { initializer: `${instance}.ProcessRecordAsync()` }); + yield task.declarationStatement; + + // have the AsyncJob monitor the lifetime of the Task + yield `${job}.Monitor(${task});`; + + // return the job to the user now. + yield `WriteObject(${job});`; + + }); + yield Else(normal); + } : normal; + + if (writable) { + yield If(`ShouldProcess($"Call remote '${operation.callGraph[0].language.csharp?.name}' operation")`, work); + } else { + yield work; + } + }); + const aggregateException = new Parameter('aggregateException', System.AggregateException); + yield Catch(aggregateException, function* () { + yield '// unroll the inner exceptions to get the root cause'; + yield ForEach('innerException', new LiteralExpression(`${aggregateException.use}.Flatten().InnerExceptions`), function* () { + yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression('$"{innerException.GetType().Name} - {innerException.Message} : {innerException.StackTrace}"')); + yield '// Write exception out to error channel.'; + yield `WriteError( new ${ErrorRecord}(innerException,string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; + }); + }); + const exception = new Parameter('exception', System.Exception); + yield Catch(exception, function* () { + yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression(`$"{${exception.use}.GetType().Name} - {${exception.use}.Message} : {${exception.use}.StackTrace}"`)); + yield '// Write exception out to error channel.'; + yield `WriteError( new ${ErrorRecord}(${exception.use},string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; + }, { when: new LiteralExpression('(exception as System.Management.Automation.PipelineStoppedException)== null || (exception as System.Management.Automation.PipelineStoppedException).InnerException != null') }); + + yield Finally(function* () { + yield $this.eventListener.syncSignalNoCheck(Events.CmdletProcessRecordEnd); + }); + }); + + } + + + private NewImplementProcessRecordAsync(operation: CommandOperation) { + const $this = this; + const PAR = this.add(new Method('ProcessRecordAsync', System.Threading.Tasks.Task(), { + access: Access.Protected, async: Modifier.Async, + description: 'Performs execution of the command, working asynchronously if required.', + returnsDescription: `A that will be complete when handling of the method is completed.` + })); + + // we don't want to use SynchContext here. + PAR.push(Using('NoSynchronizationContext', '')); + + PAR.add(function* () { + if ($this.apProp && $this.bodyParameter && $this.bodyParameterInfo) { + // yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${$this.bodyParameterInfo.type.declaration},${$this.bodyParameterInfo.valueType.declaration}>(${$this.apProp.value},${$this.bodyParameter.Cast($this.bodyParameterInfo.type)});`; + let vt = $this.bodyParameterInfo.valueType.declaration; + if (vt.endsWith('SwitchParameter')) { + vt = 'bool'; + } + yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${vt}>(${$this.apProp.value},${$this.bodyParameter}.AdditionalProperties);`; + } + + // construct the call to the operation + yield $this.eventListener.signal(Events.CmdletProcessRecordAsyncStart); + + yield $this.eventListener.signal(Events.CmdletGetPipeline); + + const pipeline = $this.$('Pipeline'); + + if ($this.state.project.azure) { + yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, ${$this.correlationId}, ${$this.processRecordId}, this.ParameterSetName)`)); + } else { + yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, this.ParameterSetName)`)); + } + + yield If(IsNotNull($this.$('HttpPipelinePrepend')), pipeline.invokeMethod('Prepend', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelinePrepend')}) ?? ${$this.$('HttpPipelinePrepend')}`))); + yield If(IsNotNull($this.$('HttpPipelineAppend')), pipeline.invokeMethod('Append', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelineAppend')}) ?? ${$this.$('HttpPipelineAppend')}`))); + + yield '// get the client instance'; + const apiCall = operation.callGraph[0]; + + // find each parameter to the method, and find out where the value is going to come from. + const operationParameters = + values(apiCall.parameters). + // filter out constants and path parameters when using piping for identity + where(each => !(each.language.csharp?.constantValue) && each.language.default?.name !== '$host'/* && (!$this.isViaIdentity || each.in !== ParameterLocation.Path) */). + + select(p => { + return { + name: p.language.csharp?.name, + param: values($this.properties). + where(each => each.metadata.parameterDefinition). + first(each => each.metadata.parameterDefinition.details.csharp.uid === p.language.csharp?.uid), + isPathParam: $this.isViaIdentity && p.protocol.http?.in === ParameterLocation.Path + }; + + }). + select(each => { + if (each.param) { + + const httpParam = ((each.param.metadata.parameterDefinition)); + if (httpParam.required) { + return { + name: each.param, + expression: each.param, + isPathParam: each.isPathParam + }; + } + + const httpParamTD = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((httpParam.schema), httpParam.required, $this.state); + return { + name: each.param, + expression: toExpression(`this.InvocationInformation.BoundParameters.ContainsKey("${each.param.value}") ? ${each.param.value} : ${httpParamTD.defaultOfType}`), + isPathParam: each.isPathParam + }; + + } + + return { name: each.name, expression: dotnet.Null, isPathParam: each.isPathParam }; + }).toArray(); + + // is there a body parameter we should include? + if ($this.bodyParameter) { + operationParameters.push({ name: 'body', expression: $this.bodyParameter, isPathParam: false }); + } + + // create the response handlers + const responses = [...values(apiCall.responses)]; + + const callbackMethods = values(responses).toArray().map(each => new LiteralExpression(each.language.csharp?.name || '')); + + // make callback methods + for (const each of values(responses)) { + + const parameters = new Array(); + parameters.push(new Parameter('responseMessage', System.Net.Http.HttpResponseMessage, { description: `the raw response message as an ${System.Net.Http.HttpResponseMessage}.` })); + + if (each.language.csharp?.responseType) { + parameters.push(new Parameter('response', System.Threading.Tasks.Task({ declaration: each.language.csharp?.responseType }), { description: `the body result as a from the remote call` })); + } + if (each.language.csharp?.headerType) { + parameters.push(new Parameter('headers', System.Threading.Tasks.Task({ declaration: each.language.csharp.headerType }), { description: `the header result as a from the remote call` })); + } + + const override = `override${pascalCase(each.language.csharp?.name || '')}`; + const returnNow = new Parameter('returnNow', System.Threading.Tasks.Task(dotnet.Bool), { modifier: ParameterModifier.Ref, description: `/// Determines if the rest of the ${each.language.csharp?.name} method should be processed, or if the method should return immediately (set to true to skip further processing )` }); + const overrideResponseMethod = new PartialMethod(override, dotnet.Void, { + parameters: [...parameters, returnNow], + description: `${override} will be called before the regular ${each.language.csharp?.name} has been processed, allowing customization of what happens on that response. Implement this method in a partial class to enable this behavior`, + returnsDescription: `A that will be complete when handling of the method is completed.` + }); + $this.add(overrideResponseMethod); + + const responseMethod = new Method(`${each.language.csharp?.name}`, System.Threading.Tasks.Task(), { + access: Access.Private, + parameters, + async: Modifier.Async, + description: each.language.csharp?.description, + returnsDescription: `A that will be complete when handling of the method is completed.` + }); + responseMethod.push(Using('NoSynchronizationContext', '')); + + + responseMethod.add(function* () { + const skip = Local('_returnNow', `${System.Threading.Tasks.Task(dotnet.Bool).declaration}.FromResult(${dotnet.False})`); + yield skip.declarationStatement; + yield `${overrideResponseMethod.invoke(...parameters, `ref ${skip.value}`)};`; + yield `// if ${override} has returned true, then return right away.`; + yield If(And(IsNotNull(skip), `await ${skip}`), Return()); + + if (each.language.csharp?.isErrorResponse) { + // this should write an error to the error channel. + yield `// Error Response : ${each.protocol.http?.statusCodes[0]}`; + + + const unexpected = function* () { + yield '// Unrecognized Response. Create an error record based on what we have.'; + const ex = (each.language.csharp?.responseType) ? + Local('ex', `new ${ClientRuntime.name}.RestException<${each.language.csharp.responseType}>(responseMessage, await response)`) : + Local('ex', `new ${ClientRuntime.name}.RestException(responseMessage)`); + + yield ex.declarationStatement; + + yield `WriteError( new global::System.Management.Automation.ErrorRecord(${ex.value}, ${ex.value}.Code, global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) +{ + ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ex.value}.Message) { RecommendedAction = ${ex.value}.Action } +});`; + }; + if (each instanceof SchemaResponse) { + // the schema should be the error information. + // this supports both { error { message, code} } and { message, code} + + let props = getAllPublicVirtualProperties(each.schema.language.csharp?.virtualProperties); + const errorProperty = values(props).first(p => p.property.details.csharp.name === 'error'); + let ep = ''; + if (errorProperty) { + props = getAllPublicVirtualProperties(errorProperty.property.schema.details.csharp.virtualProperties); + ep = `${errorProperty.name}?.`; + } + + const codeProp = props.find(p => p.name.toLowerCase().indexOf('code') > -1); // first property with 'code' + const messageProp = props.find(p => p.name.toLowerCase().indexOf('message') > -1); // first property with 'message' + const actionProp = props.find(p => p.name.toLowerCase().indexOf('action') > -1); // first property with 'action' + + if (codeProp && messageProp) { + const lcode = new LocalVariable('code', dotnet.Var, { initializer: `(await response)?.${ep}${codeProp.name}` }); + const lmessage = new LocalVariable('message', dotnet.Var, { initializer: `(await response)?.${ep}${messageProp.name}` }); + const laction = actionProp ? new LocalVariable('action', dotnet.Var, { initializer: `(await response)?.${ep}${actionProp.name} ?? ${System.String.Empty}` }) : undefined; + yield lcode; + yield lmessage; + yield laction; + + yield If(Or(IsNull(lcode), (IsNull(lmessage))), unexpected); + yield Else(`WriteError( new global::System.Management.Automation.ErrorRecord(new global::System.Exception($"[{${lcode}}] : {${lmessage}}"), ${lcode}?.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) +{ + ErrorDetails = new global::System.Management.Automation.ErrorDetails(${lmessage}) { RecommendedAction = ${laction || System.String.Empty} } +});` + + ); + return; + } else { + yield unexpected; + return; + } + } else { + yield unexpected; + return; + } + } + + yield `// ${each.language.csharp?.name} - response for ${each.protocol.http?.statusCodes[0]} / ${values(each.protocol.http?.mediaTypes).join('/')}`; + + if ('schema' in each) { + const schema = (each).schema; + + if (apiCall.language.csharp?.pageable) { + const pageable = apiCall.language.csharp.pageable; + yield '// response should be returning an array of some kind. +Pageable'; + yield `// ${pageable.responseType} / ${pageable.itemName || ''} / ${pageable.nextLinkName || ''}`; + switch (pageable.responseType) { + // the result is (or works like a x-ms-pageable) + // skip-for-time-being + // case 'pageable': + // case 'nested-array': { + // const valueProperty = schema.properties[pageable.itemName]; + // const nextLinkProperty = schema.properties[pageable.nextLinkName]; + // if (valueProperty && nextLinkProperty) { + // // it's pageable! + // const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('await response') }); + // yield result.declarationStatement; + // // write out the current contents + // const vp = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); + // if (vp) { + // yield `WriteObject(${result.value}.${vp.name},true);`; + // } + // const nl = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, nextLinkProperty.serializedName); + // if (nl) { + // const nextLinkName = `${result.value}.${nl.name}`; + // yield (If(`${nextLinkName} != null`, + // If('responseMessage.RequestMessage is System.Net.Http.HttpRequestMessage requestMessage ', function* () { + // yield `requestMessage = requestMessage.Clone(new global::System.Uri( ${nextLinkName} ),${ClientRuntime.Method.Get} );`; + // yield $this.eventListener.signal(Events.FollowingNextLink); + // yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}_Call`, ...[toExpression('requestMessage'), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + // }) + // )); + // } + // return; + // } else if (valueProperty) { + // // it's just a nested array + // const p = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); + // if (p) { + // yield `WriteObject((await response).${p.name}, true);`; + // } + // return; + // } + // } + // break; + + // it's just an array, + case 'array': + // just write-object(enumerate) with the output + yield 'WriteObject(await response, true);'; + return; + } + // ok, let's see if the response type + } + const props = getAllPublicVirtualProperties(schema.language.csharp?.virtualProperties); + const outValue = (length(props) === 1) ? `(await response).${props[0].name}` : '(await response)'; + + + // we expect to get back some data from this call. + + const rType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(schema, true, $this.state); + yield `// (await response) // should be ${rType.declaration}`; + if ($this.hasStreamOutput && $this.outFileParameter) { + const outfile = $this.outFileParameter; + const provider = Local('provider'); + provider.initializer = undefined; + const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(${outfile.value}, out ${provider.declarationExpression})`); + yield paths.declarationStatement; + yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid output path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); + yield If(`${paths.value}.Count > 1`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple output paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); + + if (rType.declaration === System.IO.Stream.declaration) { + // this is a stream output. write to outfile + const stream = Local('stream', 'await response'); + yield Using(stream.declarationExpression, function* () { + const fileStream = Local('fileStream', `global::System.IO.File.OpenWrite(${paths.value}[0])`); + yield Using(fileStream.declarationExpression, `await ${stream.value}.CopyToAsync(${fileStream.value});`); + }); + } else { + // assuming byte array output (via outValue) + yield `global::System.IO.File.WriteAllBytes(${paths.value}[0],${outValue});`; + } + + yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { + // no return type. Let's just return ... true? + yield 'WriteObject(true);'; + }); + return; + } + + // let's just return the result object (or unwrapped result object) + yield `WriteObject(${outValue});`; + return; + } + + yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { + // no return type. Let's just return ... true? + yield 'WriteObject(true);'; + }); + }); + $this.add(responseMethod); + } + + yield Try(function* () { + // make the call. + + const actualCall = function* () { + yield $this.eventListener.signal(Events.CmdletBeforeAPICall); + const idOpParams = operationParameters.filter(each => !each.isPathParam); + // skip-for-time-being, viaidentity + // const idschema = values($this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); + + + // if ($this.isViaIdentity) { + // const identityFromPathParams = function* () { + // yield '// try to call with PATH parameters from Input Object'; + + // if (idschema) { + // const allVPs = getAllPublicVirtualProperties(idschema.details.csharp.virtualProperties); + // const props = [...values(idschema.properties)]; + + // const idOpParams = operationParameters.map(each => { + // const pascalName = pascalCase(`${each.name}`); + + // if (!each.isPathParam) { + // return { + // name: undefined, + // value: valueOf(each.expression) + // }; + // } + // const match = props.find(p => pascalCase(p.serializedName) === pascalName); + // if (match) { + + // const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType; + // // match up vp name + // const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName); + // if (vp) { + // return { + // name: `InputObject.${vp.name}`, + // value: `InputObject.${vp.name} ?? ${defaultOfType}` + // }; + // } + // // fall back! + + // console.error(`Unable to match identity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalCase(match.details.csharp.name)}').`); + // return { + // name: `InputObject.${pascalCase(match.details.csharp.name)}`, + // value: `InputObject.${pascalCase(match.details.csharp.name)} ?? ${defaultOfType}` + // }; + // } + // console.error(`Unable to match idenity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalName}')`); + // return { + // name: `InputObject.${pascalName}`, + // value: `InputObject.${pascalName}` + // }; + // }); + // for (const opParam of idOpParams) { + // if (opParam.name) { + // yield If(IsNull(opParam.name), `ThrowTerminatingError( new ${ErrorRecord}(new global::System.Exception("InputObject has null value for ${opParam.name}"),string.Empty, ${ErrorCategory('InvalidArgument')}, InputObject) );`); + // } + // } + // yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...idOpParams.map(each => toExpression(each.value)), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + + // } + // }; + + // if (idschema && values(idschema.properties).first(each => each.details.csharp.uid === 'universal-parameter:resource identity')) { + // yield If('InputObject?.Id != null', `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}ViaIdentity`, ...[toExpression('InputObject.Id'), ...idOpParams.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`); + // yield Else(identityFromPathParams); + // } else { + // yield identityFromPathParams; + // } + // } else { + yield `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}`, ...[...operationParameters.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + //} + yield $this.eventListener.signal(Events.CmdletAfterAPICall); + }; + + if ($this.state.project.azure && operationParameters.find(each => each.expression && each.expression.value === 'SubscriptionId') && $this.operation.details.csharp.verb.toLowerCase() === 'get') { + yield 'foreach( var SubscriptionId in this.SubscriptionId )'; + yield BlockStatement(actualCall); + } else { + yield actualCall; + } + }); + const ure = new Parameter('urexception', { declaration: `${ClientRuntime.fullName}.UndeclaredResponseException` }); + yield Catch(ure, function* () { + yield `WriteError(new global::System.Management.Automation.ErrorRecord(${ure.value}, ${ure.value}.StatusCode.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(',')}}) +{ + ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ure.value}.Message) { RecommendedAction = ${ure.value}.Action } +});`; + }); + yield Finally(function* () { + yield $this.eventListener.signalNoCheck(Events.CmdletProcessRecordAsyncEnd); + }); + }); + } + + + private NewImplementSerialization(operation: CommandOperation) { + const $this = this; + // clone + if (operation.asjob) { + const clone = this.add(new Method('Clone', this, { + description: 'Creates a duplicate instance of this cmdlet (via JSON serialization).', + returnsDescription: `a duplicate instance of ${this.name}`, + })); + + clone.add(function* () { + const i = new LocalVariable('clone', dotnet.Var, { + initializer: $this.new() + }); + yield i.declarationStatement; + + if ($this.state.project.azure) { + for (const f of [$this.correlationId, $this.processRecordId, $this.defaultProfile]) { + yield `${i.value}.${f} = this.${f};`; + } + } + for (const f of [$this.invocationInfo, 'Proxy', 'Pipeline', 'AsJob', 'Break', 'ProxyCredential', 'ProxyUseDefaultCredentials', 'HttpPipelinePrepend', 'HttpPipelineAppend',]) { + yield `${i.value}.${f} = this.${f};`; + } + + for (const f of $this.thingsToSerialize) { + yield `${i.value}.${f} = this.${f};`; + } + + // _name = this._name, + //_parametersBody = this._parametersBody, + //_resourceGroupName = this._resourceGroupName, + //_subscriptionId = this._subscriptionId, + + yield Return(i); + }); + } + } + private implementConstructors() { + // default constructor + this.add(new Constructor(this, { description: `Intializes a new instance of the cmdlet class.` })); + } + + private implementIEventListener() { + const $this = this; + const cts = this.add(new Field('_cancellationTokenSource', System.Threading.CancellationTokenSource, { + access: Access.Private, + initialValue: new LiteralExpression(`new ${System.Threading.CancellationTokenSource.declaration}()`), + description: `The for this operation.` + })); + this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Token`, System.Threading.CancellationToken, new LiteralExpression(`${cts.value}.Token`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation token.' })); + this.cancellationToken = toExpression(`((${ClientRuntime.IEventListener})this).Token`); + this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Cancel`, System.Action(), new LiteralExpression(`${cts.value}.Cancel`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation delegate. Stops the cmdlet when called.' })); + + const id = new Parameter('id', dotnet.String, { description: 'The message id' }); + const token = new Parameter('token', System.Threading.CancellationToken, { description: 'The message cancellation token. When this call is cancelled, this should be true' }); + const messageData = new Parameter('messageData', System.Func(ClientRuntime.EventData), { description: 'Detailed message data for the message event.' }); + const signalMethod = this.add(new Method(`${ClientRuntime.IEventListener}.Signal`, System.Threading.Tasks.Task(), { + async: Modifier.Async, + parameters: [id, token, messageData], + access: Access.Default, + description: 'Handles/Dispatches events during the call to the REST service.', + returnsDescription: `A that will be complete when handling of the message is completed.` + })); + signalMethod.push(Using('NoSynchronizationContext', '')); + + signalMethod.add(function* () { + yield If(`${token.value}.IsCancellationRequested`, Return()); + + // if the + + const sw = Switch(id, [ + TerminalCase(Events.Verbose.value, function* () { + yield `WriteVerbose($"{(messageData().Message ?? ${System.String.Empty})}");`; + yield Return(); + }), + + TerminalCase(Events.Warning.value, function* () { + yield `WriteWarning($"{(messageData().Message ?? ${System.String.Empty})}");`; + yield Return(); + }), + TerminalCase(Events.Information.value, function* () { + if ($this.operation.asjob) { + yield '// When an operation supports asjob, Information messages must go thru verbose.'; + yield `WriteVerbose($"INFORMATION: {(messageData().Message ?? ${System.String.Empty})}");`; + } + else { + const data = new LocalVariable('data', dotnet.Var, { initializer: new LiteralExpression(`${messageData.use}()`) }); + yield data.declarationStatement; + yield 'WriteInformation(data, new[] { data.Message });'; + } + yield Return(); + + }), + TerminalCase(Events.Debug.value, function* () { + yield `WriteDebug($"{(messageData().Message ?? ${System.String.Empty})}");`; + yield Return(); + }), + TerminalCase(Events.Error.value, function* () { + yield 'WriteError(new global::System.Management.Automation.ErrorRecord( new global::System.Exception(messageData().Message), string.Empty, global::System.Management.Automation.ErrorCategory.NotSpecified, null ) );'; + yield Return(); + }), + ]); + + if ($this.operation.asjob) { + // if we support -AsJob, we support -NoWait + sw.add(Case(Events.DelayBeforePolling.value, function* () { + yield If('true == MyInvocation?.BoundParameters?.ContainsKey("NoWait")', function* () { + yield 'var data = messageData();'; + yield 'if (data.ResponseMessage is System.Net.Http.HttpResponseMessage response)'; + yield '{'; + yield ' var asyncOperation = response.GetFirstHeader(@"Azure-AsyncOperation");'; + yield ' var location = response.GetFirstHeader(@"Location");'; + yield ' var uri = global::System.String.IsNullOrEmpty(asyncOperation) ? global::System.String.IsNullOrEmpty(location) ? response.RequestMessage.RequestUri.AbsoluteUri : location : asyncOperation;'; + yield ` WriteObject(new ${ClientRuntime}.PowerShell.AsyncOperationResponse { Target = uri });`; + + yield ' // do nothing more. '; + yield ' data.Cancel();'; + yield ' return;'; + yield '}'; + }); + })); + } + + // the whole switch statement + yield sw; + + if ($this.state.project.azure) { + // in azure mode, we signal the AzAccount module with every event that makes it here. + yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`; + yield If(`${token.value}.IsCancellationRequested`, Return()); + } + yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`; + // any handling of the signal on our side... + }); + } + + + private NewAddPowershellParameters(operation: CommandOperation) { + const vps = operation.details.csharp.virtualParameters || { + body: [], + operation: [], + }; + + for (const parameter of values(operation.parameters)) { + // these are the parameters that this command expects + parameter.schema; + const td = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema, true, this.state); + + if (parameter.details.csharp.constantValue) { + // this parameter has a constant value -- SKIP IT + continue; + } + + if (parameter.details.csharp.fromHost) { + // the parameter is expected to be gotten from the host.(ie, Az.Accounts) + + const hostParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { + metadata: { + parameterDefinition: parameter.details.csharp.httpParameter + }, + description: parameter.details.csharp.description, + })); + this.thingsToSerialize.push(hostParameter); + // in the BeginProcessing, we should tell it to go get the value for this property from the common module + this.$('BeginProcessing').add(hostParameter.assignPrivate(new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.GetParameter(this.MyInvocation, ${this.correlationId.value}, "${parameter.name}") as string`))); + continue; + } + const $this = this; + + if (parameter.details.csharp.apiversion) { + // Api-version parameters for azure are a custom implementation + this.add(new Property(parameter.details.csharp.name, td, { + getAccess: Access.Internal, + setAccess: Access.Private, + metadata: { + parameterDefinition: parameter.details.csharp.httpParameter + }, + description: parameter.details.csharp.description, + *get() { + const metadata = operation.extensions['x-ms-metadata']; + const profiles = >metadata.profiles || new Dictionary(); + + yield Switch(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Profile`, function* () { + for (const { key: profileName, value: apiVersion } of items(profiles)) { + yield TerminalCase(`"${profileName}"`, Return(`"${apiVersion}"`)); + } + yield TerminalDefaultCase(Return(`"${metadata.apiVersions[0]}"`)); + }); + } + })); + continue; + } + + if (this.dropBodyParameter && parameter.details.csharp.isBodyParameter) { + // we're supposed to use parameters for the body parameter instead of a big object + const expandedBodyParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { + description: parameter.details.csharp.description, + + initializer: (parameter.schema.type === SchemaType.Array) ? 'null' : `new ${parameter.schema.language.csharp?.fullname}()`, + setAccess: Access.Private, + getAccess: Access.Private, + })); + this.thingsToSerialize.push(expandedBodyParameter); + + for (const vParam of vps.body) { + const vSchema = vParam.schema; + vParam.origin; + const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); + + // we need to know if the actual underlying property is actually nullable. + const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, (vParam.origin).property.language.csharp?.required, this.state).isNullable; + + const cmdletParameter = new Property(vParam.name, propertyType, { + get: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ + // get: toExpression(`null == ${expandedBodyParameter.value}.${vParam.origin.name} ? ${propertyType.defaultOfType} : (${propertyType.declaration}) ${expandedBodyParameter.value}.${vParam.origin.name}`), + set: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), + new: PropertiesRequiringNew.has(vParam.name) ? Modifier.New : Modifier.None + }); + + if (vParam.schema.language.csharp?.byReference) { + // this parameter's schema is marked as 'by-reference' which means we should + // tag it with an ExportAs attribute for the I*Reference type. + cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.language.csharp.referenceInterface})`] })); + } + + if (vParam.schema.type === SchemaType.Array) { + //skip-for-time-being + // if ((vParam.schema). && vParam.schema.items.details.csharp.byReference) { + // cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.items.details.csharp.referenceInterface}[])`] })); + // } + cmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); + } + //skip-for-time-being + // if (vSchema.additionalProperties) { + // // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. + // // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary + // // if it's a standalone dictionary, we can just use hashtable instead + // if (length(vSchema.properties) === 0) { + // // it's a pure dictionary + // // add an attribute for changing the exported type. + // cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); + // } else { + // // it's a hybrid. We need to add an additional property that puts its items into the target container + + // } + + // } + + const desc = (vParam.description || '.').replace(/[\r?\n]/gm, ''); + cmdletParameter.description = desc; + + // check if this parameter is a byte array, which would indicate that it should really be a file input + if (cmdletParameter.type.declaration === dotnet.Binary.declaration) { + // set the generated parameter to internal + cmdletParameter.setAccess = Access.Internal; + cmdletParameter.getAccess = Access.Internal; + + // create a InputFileXXX for the parameter + const ifname = vParam.name.toLowerCase() === 'value' ? 'InputFile' : pascalCase([vParam.name, 'Input', 'File']); + + const inputFileParameter = new Property(ifname, dotnet.String, { + // get: toExpression(`${expandedBodyParameter.value}.${vParam.origin.name}${vParam.required ? '' : ` ?? ${propertyType.defaultOfType}`}`), + set: function* () { + const provider = Local('provider'); + provider.initializer = undefined; + const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(value, out ${provider.declarationExpression})`); + yield paths.declarationStatement; + yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid input path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); + yield If(`${paths.value}.Count > 1`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple input paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); + yield cmdletParameter.assign(`global::System.IO.File.ReadAllBytes(${paths.value}[0])`); + }, + description: `Input File for ${cmdletParameter.name} (${escapeString(desc)})` + }); + + inputFileParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "Input File for ${cmdletParameter.name} (${escapeString(desc || '.')})"`)] })); + inputFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); + + $this.add(inputFileParameter); + } else { + cmdletParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(desc || '.')}"`)] })); + cmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); + addInfoAttribute(cmdletParameter, propertyType, !!vParam.required, false, desc, (vParam.origin).property.serializedName); + NewAddCompleterInfo(cmdletParameter, vParam); + addDefaultInfo(cmdletParameter, vParam); + } + + const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; + if (isEnum || hasEnum) { + cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + } + // add aliases if there is any + if (length(vParam.alias) > 0) { + cmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); + } + + this.add(cmdletParameter); + } + // skip-for-time-being + // if (parameter.schema.additionalProperties) { + // // if there is an additional properties on this type + // // add a hashtable parameter for additionalProperties + // let apPropName = ''; + // const options = ['AdditionalProperties', 'MoreProperties', 'ExtendedProperties', 'Properties']; + // for (const n of options) { + // if (this.properties.find(each => each.name === n)) { + // continue; + // } + // apPropName = n; + // break; + // } + + // this.apProp = this.add(new Property(apPropName, System.Collections.Hashtable)); + // this.apProp.add(new Attribute(ParameterAttribute, { + // parameters: ['Mandatory = false', 'HelpMessage = "Additional Parameters"'] + // })); + // this.bodyParameterInfo = { + // type: { + // declaration: parameter.schema.details.csharp.fullname + // }, + // valueType: parameter.schema.additionalProperties === true ? System.Object : this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema.additionalProperties, true, this.state) + // }; + // } + + this.bodyParameter = expandedBodyParameter; + continue; + } + } + + // skip-for-time-being + // if (this.isViaIdentity) { + // // add in the pipeline parameter for the identity + + // const idschema = values(this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); + // const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state); + // const idParam = this.add(new BackedProperty('InputObject', idtd, { + // description: 'Identity Parameter' + // })); + // const parameters = [new LiteralExpression('Mandatory = true'), new LiteralExpression('HelpMessage = "Identity Parameter"'), new LiteralExpression('ValueFromPipeline = true')]; + // idParam.add(new Attribute(ParameterAttribute, { parameters })); + // idParam.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Path`] })); + // } + for (const vParam of values(vps.operation)) { + if (vParam.name === 'Host') { + // skip 'Host' + continue; + } + const vSchema = vParam.schema; + const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); + + + const origin = vParam.origin; + + const regularCmdletParameter = (this.state.project.azure && vParam.name === 'SubscriptionId' && operation.details.csharp.verb.toLowerCase() === 'get') ? + + // special case for subscription id + this.add(new BackedProperty(vParam.name, dotnet.StringArray, { + metadata: { + parameterDefinition: origin.details.csharp.httpParameter + }, + description: vParam.description + })) : + + // everything else + this.add(new BackedProperty(vParam.name, propertyType, { + metadata: { + parameterDefinition: origin.details.csharp.httpParameter + }, + description: vParam.description + })); + + // skip-for-time-being + // if (vSchema.additionalProperties) { + // // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. + // // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary + // // if it's a standalone dictionary, we can just use hashtable instead + // if (length(vSchema.properties) === 0) { + // // it's a pure dictionary + // // change the property type to hashtable. + // // add an attribute to change the exported type. + // regularCmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); + // } else { + // // it's a hybrid. We need to add an additional property that puts its items into the target container + + // } + + // } + + this.thingsToSerialize.push(regularCmdletParameter); + + const parameters = [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(vParam.description) || '.'}"`)]; + if (origin.details.csharp.isBodyParameter) { + parameters.push(new LiteralExpression('ValueFromPipeline = true')); + this.bodyParameter = regularCmdletParameter; + } + regularCmdletParameter.add(new Attribute(ParameterAttribute, { parameters })); + if (vParam.schema.type === SchemaType.Array) { + regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); + } + + addInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); + NewAddCompleterInfo(regularCmdletParameter, vParam); + addDefaultInfo(regularCmdletParameter, vParam); + + // add aliases if there is any + if (length(vParam.alias) > 0) { + regularCmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); + } + + const httpParam = origin.details.csharp.httpParameter; + const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; + + // skip-for-time-being + // const cat = values(operation.callGraph[0].parameters). + // where(each => !(each.details.csharp.constantValue)). + // first(each => each.details.csharp.uid === uid); + + // if (cat) { + // regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase(cat.in)}`] })); + // } + + + if (origin.details.csharp.completer) { + // add the completer to this class and tag this parameter with the completer. + // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); + } + + const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; + if (isEnum || hasEnum) { + regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + } + } + const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); + if (ifmatch) { + //no sure why there is an empty block + } + + } + + + private NewAddClassAttributes(operation: CommandOperation, variantName: string) { + const cmdletAttribParams: Array = [ + category[operation.details.csharp.verb] ? verbEnum(category[operation.details.csharp.verb], operation.details.csharp.verb) : `"${operation.details.csharp.verb}"`, + new StringExpression(variantName) + ]; + + if (this.NewIsWritableCmdlet(operation)) { + cmdletAttribParams.push('SupportsShouldProcess = true'); + } + + if (operation.details.csharp.hidden) { + this.add(new Attribute(InternalExportAttribute)); + const noun = `${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; + const cmdletName = `${operation.details.csharp.verb}-${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; + this.state.message({ Channel: Channel.Debug, Text: `[DIRECTIVE] Applied 'hidden' directive to ${cmdletName}. Added attribute ${InternalExportAttribute.declaration} to cmdlet.` }); + } + + this.add(new Attribute(CmdletAttribute, { parameters: cmdletAttribParams })); + + // add alias attribute if there is any aliases for this cmdlet + if (length(operation.details.csharp.alias) > 0) { + this.add(new Attribute(Alias, { parameters: operation.details.csharp.alias.map((x: string) => '"' + x + '"') })); + } + + let shouldAddPassThru = false; + // set to hold the output types + const outputTypes = new Set(); + for (const httpOperation of values(operation.callGraph)) { + const pageableInfo = httpOperation.language.csharp?.pageable; + const v = httpOperation.responses && httpOperation.responses.length > 0 && httpOperation.responses[0] instanceof SchemaResponse; + for (const schema of values(httpOperation.responses).selectNonNullable(each => (each).schema)) { + + const props = NewGetAllProperties(schema); + + // does the target type just wrap a single output? + const resultSchema = length(props) !== 1 ? schema : props[0].schema; + + // make sure return type for boolean stays boolean! + if (resultSchema.type === SchemaType.Boolean) { + outputTypes.add(`typeof(${dotnet.Bool})`); + } else { + const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state); + + if (typeDeclaration.declaration === System.IO.Stream.declaration || typeDeclaration.declaration === dotnet.Binary.declaration) { + // if this is a stream, skip the output type. + this.hasStreamOutput = true; + shouldAddPassThru = true; + outputTypes.add(`typeof(${dotnet.Bool})`); + } else { + + let type = ''; + if (typeDeclaration instanceof ArrayOf) { + type = typeDeclaration.elementTypeDeclaration; + } else if (!(typeDeclaration.schema instanceof NewSchema) && pageableInfo && pageableInfo.responseType === 'pageable') { + if (typeDeclaration === undefined || typeDeclaration.schema.properties[pageableInfo.itemName] === undefined) { + //skip-for-time-being, since operationId does not support in m4 any more + //throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); + throw new Error('An error needs to be more specific'); + } + const nestedSchema = typeDeclaration.schema.properties[pageableInfo.itemName].schema; + // skip-for-time-being + //const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); + //type = (nestedTypeDeclaration).elementTypeDeclaration; + } else { + type = typeDeclaration.declaration; + } + // check if this is a stream output + if (type) { + outputTypes.add(`typeof(${type})`); + } + } + } + + } + } + + // if any response does not return, + // the cmdlet should have a PassThru parameter + shouldAddPassThru = shouldAddPassThru || values(operation.callGraph) + .selectMany(httpOperation => values(httpOperation.responses)) + //.selectMany(responsesItem => responsesItem.value) + .any(value => value instanceof SchemaResponse); + if (outputTypes.size === 0) { + outputTypes.add(`typeof(${dotnet.Bool})`); + } + + this.add(new Attribute(OutputTypeAttribute, { parameters: [...outputTypes] })); + if (shouldAddPassThru) { + const passThru = this.add(new Property('PassThru', SwitchParameter, { description: 'When specified, forces the cmdlet return a \'bool\' given that there isn\'t a return type by default.' })); + passThru.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Returns true when the command succeeds"'] })); + passThru.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); + } + this.add(new Attribute(DescriptionAttribute, { parameters: [new StringExpression(this.description)] })); this.add(new Attribute(GeneratedAttribute)); if (operation.extensions && operation.extensions['x-ms-metadata'] && operation.extensions['x-ms-metadata'].profiles) { diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index e5df54cd73b..96e05ae6ff4 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -6,7 +6,7 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime } from '../llcsharp/exports'; import { State, NewState } from '../internal/state'; -import { CmdletClass } from './class'; +import { CmdletClass, NewCmdletClass } from './class'; import { DeepPartial } from '@azure-tools/codegen'; export class CmdletNamespace extends Namespace { @@ -56,7 +56,7 @@ export class NewCmdletNamespace extends Namespace { continue; } // skip-for-time-being - //this.addClass(await new CmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); + this.addClass(await new NewCmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); } return this; } diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 471f5122f42..0eae54dc905 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -379,7 +379,7 @@ export class NewProject extends codeDomProject { this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); this.supportNamespace.header = this.license; - //this.addNamespace(this.supportNamespace); + this.addNamespace(this.supportNamespace); this.modelsExtensions = new NewModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); this.modelsExtensions.header = this.license; diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 4cefd217511..751d99a4943 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -5,7 +5,7 @@ import { Schema as NewSchema } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; -import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; +import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, NewObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; import { State, NewState } from '../internal/state'; import { PSObject, PSTypeConverter, TypeConverterAttribute } from '../internal/powershell-declarations'; import { join } from 'path'; @@ -285,11 +285,11 @@ export class NewModelExtensionsNamespace extends Namespace { } const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof ObjectImplementation) { + if (td instanceof NewObjectImplementation) { // it's a class object. - const className = td.schema.details.csharp.name; - const interfaceName = td.schema.details.csharp.interfaceName || ''; + const className = td.schema.language.csharp?.name || ''; + const interfaceName = td.schema.language.csharp?.interfaceName || ''; const converterClass = `${className}TypeConverter`; if (this.findClassByName(className).length > 0) { @@ -304,7 +304,7 @@ export class NewModelExtensionsNamespace extends Namespace { // 2. A partial interface with the type converter attribute const modelInterface = new Interface(ns, interfaceName, { partial: true, - description: td.schema.details.csharp.description, + description: td.schema.language.csharp?.description, fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. }); modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); @@ -312,7 +312,7 @@ export class NewModelExtensionsNamespace extends Namespace { // 1. A partial class with the type converter attribute const model = new Class(ns, className, undefined, { partial: true, - description: td.schema.details.csharp.description, + description: td.schema.language.csharp?.description, fileName: `${className}.PowerShell` }); @@ -341,7 +341,7 @@ export class NewModelExtensionsNamespace extends Namespace { model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { static: Modifier.Static, parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], - description: `Creates a new instance of , deserializing the content from a json string.`, + description: `Creates a new instance of , deserializing the content from a json string.`, returnsDescription: 'an instance of the model class.' })); diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index b4de4ebe2b3..7490a1d3b08 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -13,9 +13,9 @@ import { Lazy } from '@azure-tools/tasks'; import { clone } from '@azure-tools/linq'; import { verbs } from '../internal/verbs'; import { PwshModel } from '../utils/PwshModel'; -import { IParameterPwsh } from '../utils/components'; +import { IParameter } from '../utils/components'; import { NewModelState } from '../utils/model-state'; -import { Schema as SchemaV3 } from '../utils/schema'; +//import { Schema as SchemaV3 } from '../utils/schema'; import { CommandOperation } from '../utils/command-operation'; type State = NewModelState; @@ -276,7 +276,7 @@ export /* @internal */ class Inferrer { // if this has a body with it, let's add that parameter if (body && body.schema) { op.details.default.hasBody = true; - op.parameters.push(new IParameterPwsh(bodyParameterName, new SchemaV3('not used'), body.schema, { + op.parameters.push(new IParameter(bodyParameterName, body.schema, { details: { default: { description: body.schema.language.default.description, @@ -291,7 +291,7 @@ export /* @internal */ class Inferrer { if (body.schema.type === SchemaType.Object) { const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); opExpanded.details.default.dropBodyParameter = true; - opExpanded.parameters.push(new IParameterPwsh(`${bodyParameterName}Body`, new SchemaV3('not used'), body.schema, { + opExpanded.parameters.push(new IParameter(`${bodyParameterName}Body`, body.schema, { details: { default: { description: body.schema.language.default.description, @@ -396,7 +396,7 @@ export /* @internal */ class Inferrer { return each; }), // skip-for-time-being, this callGraph is used in the header comments - callGraph: [], + callGraph: [operation], }); } diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 220edeb1b55..1bd46a69f02 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -309,7 +309,7 @@ function createVirtualParameters(operation: CommandOperation) { if (dropBodyParameter && parameter.details.default.isBodyParameter) { // the client will make a hidden body parameter for this, and we're expected to fill it. - const vps = parameter.schema.details.default.virtualProperties; + const vps = parameter.schema.language.default.virtualProperties; if (vps) { for (const virtualProperty of [...vps.inherited, ...vps.owned, ...vps.inlined]) { // dolauli add virtual parameter for virtual property diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index 66d946470c9..79b536b8fd7 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -55,7 +55,7 @@ async function tweakModel(state: State): Promise { // make sure recursively that every details field has csharp for (const { index, instance } of linq.visitor(state.model)) { - if (index === 'language' && instance.default && !instance.csharp) { + if (index === 'details' && instance.default && !instance.csharp) { instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); } } diff --git a/powershell/utils/command-operation.ts b/powershell/utils/command-operation.ts index a1bbd0f804f..66e9bcf10ae 100644 --- a/powershell/utils/command-operation.ts +++ b/powershell/utils/command-operation.ts @@ -5,10 +5,11 @@ import { Components, IParameter, LanguageDetails } from './components'; import { Extensions } from './extensions'; -import { HttpOperation } from './http-operation'; import { ProgramaticOperationDetails, ProgrammaticOperation } from './programatic-operation'; -import { Schema, VirtualProperty } from './schema'; +import { VirtualProperty } from './schema'; +import { Schema } from '@azure-tools/codemodel'; import { DeepPartial } from '@azure-tools/codegen'; +import { Operation } from '@azure-tools/codemodel'; import { uid } from './uid'; import { Dictionary } from '@azure-tools/linq'; @@ -35,7 +36,7 @@ export interface CommandOperation extends ProgrammaticOperation { variant: string; category: string; asjob: boolean; - callGraph: Array; + callGraph: Array; } export interface VirtualParameter { diff --git a/powershell/utils/components.ts b/powershell/utils/components.ts index fb25f70e2d0..81b6a5b3f7c 100644 --- a/powershell/utils/components.ts +++ b/powershell/utils/components.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { DeepPartial } from '@azure-tools/codegen'; import { Dictionary } from '@azure-tools/linq'; -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { Schema } from '@azure-tools/codemodel'; import { Extensions } from './extensions'; -import { Schema } from './schema'; +//import { Schema } from './schema'; import { uid } from './uid'; export interface IOperationBase { @@ -42,11 +42,7 @@ export class IParameter extends Extensions { } } -export class IParameterPwsh extends IParameter { - constructor(public name: string, public schema: Schema, public newSchema: NewSchema, initializer?: DeepPartial) { - super(name, schema); - } -} + export interface IOperation extends IOperationBase { operationId: string; description: string; diff --git a/powershell/utils/http-operation.ts b/powershell/utils/http-operation.ts index ad0e989a692..1d893c86dbe 100644 --- a/powershell/utils/http-operation.ts +++ b/powershell/utils/http-operation.ts @@ -1,71 +1,71 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Components, Example, ExternalDocumentation, ImplementationDetails, ImplementationLocation, IOperation, IOperationBase, IParameter, LanguageDetails, Link, ParameterDetails, ResponseDetails, SecurityRequirement, Server } from './components'; -import { Extensions } from './extensions'; -import { Schema } from './schema'; -import { SecurityScheme } from './security-scheme'; -import { DeepPartial } from '@azure-tools/codegen'; -import { Dictionary } from '@azure-tools/linq'; -import { uid } from './uid'; - -export interface HttpOperationDetails extends ImplementationDetails { -} - -/** - * An encoding attribute is introduced to give you control over the serialization of parts of multipart request bodies. - * This attribute is only applicable to multipart and application/x-www-form-urlencoded request bodies. -*/ -export class Encoding extends Extensions implements Encoding { - public headers = new Array
(); - - constructor(public key: string, initializer?: DeepPartial) { - super(); - this.apply(initializer); - } -} - -export class Header extends Extensions implements Header { - - public content = new Array(); - - constructor(initializer?: DeepPartial
) { - super(); - this.apply(initializer); - } -} - -export class MediaType extends Extensions implements MediaType { - public encoding = new Array(); - public accepts = new Array(); - - constructor(public key: string, initializer?: DeepPartial) { - super(); - this.apply(initializer); - } -} - -export class RequestBody extends Extensions implements RequestBody { - - constructor(initializer?: DeepPartial) { - super(); - this.apply(initializer); - } -} - -export class Response extends Extensions implements Response { - - public content = new Dictionary(); - public links = new Dictionary(); - public headers = new Array
(); - - constructor(public description: string, initializer?: DeepPartial) { - super(); - this.apply(initializer); - } -} +// /*--------------------------------------------------------------------------------------------- +// * Copyright (c) Microsoft Corporation. All rights reserved. +// * Licensed under the MIT License. See License.txt in the project root for license information. +// *--------------------------------------------------------------------------------------------*/ + +// import { Components, Example, ExternalDocumentation, ImplementationDetails, ImplementationLocation, IOperation, IOperationBase, IParameter, LanguageDetails, Link, ParameterDetails, ResponseDetails, SecurityRequirement, Server } from './components'; +// import { Extensions } from './extensions'; +// import { Schema } from './schema'; +// import { SecurityScheme } from './security-scheme'; +// import { DeepPartial } from '@azure-tools/codegen'; +// import { Dictionary } from '@azure-tools/linq'; +// import { uid } from './uid'; + +// export interface HttpOperationDetails extends ImplementationDetails { +// } + +// /** +// * An encoding attribute is introduced to give you control over the serialization of parts of multipart request bodies. +// * This attribute is only applicable to multipart and application/x-www-form-urlencoded request bodies. +// */ +// export class Encoding extends Extensions implements Encoding { +// public headers = new Array
(); + +// constructor(public key: string, initializer?: DeepPartial) { +// super(); +// this.apply(initializer); +// } +// } + +// export class Header extends Extensions implements Header { + +// public content = new Array(); + +// constructor(initializer?: DeepPartial
) { +// super(); +// this.apply(initializer); +// } +// } + +// export class MediaType extends Extensions implements MediaType { +// public encoding = new Array(); +// public accepts = new Array(); + +// constructor(public key: string, initializer?: DeepPartial) { +// super(); +// this.apply(initializer); +// } +// } + +// export class RequestBody extends Extensions implements RequestBody { + +// constructor(initializer?: DeepPartial) { +// super(); +// this.apply(initializer); +// } +// } + +// export class Response extends Extensions implements Response { + +// public content = new Dictionary(); +// public links = new Dictionary(); +// public headers = new Array
(); + +// constructor(public description: string, initializer?: DeepPartial) { +// super(); +// this.apply(initializer); +// } +// } export enum ParameterLocation { Uri = 'uri', @@ -75,226 +75,226 @@ export enum ParameterLocation { Path = 'path', } -export enum EncodingStyle { - Matrix = 'matrix', - Label = 'label', - Simple = 'simple', - Form = 'form', - SpaceDelimited = 'spaceDelimited', - PipeDelimited = 'pipeDelimited', - DeepObject = 'deepObject' -} - -export type QueryEncodingStyle = - EncodingStyle.Form - | EncodingStyle.SpaceDelimited - | EncodingStyle.PipeDelimited - | EncodingStyle.DeepObject; -export type PathEncodingStyle = EncodingStyle.Matrix | EncodingStyle.Label | EncodingStyle.Simple; - -export interface Encoding extends Extensions { - key: string; - contentType?: string; - headers: Array
; - style?: QueryEncodingStyle; - explode?: boolean; - allowReserved?: boolean; -} - -export interface Header extends Extensions { - key: string; - schema: Schema; - explode?: boolean; - examples: Dictionary; - - description?: string; - required: boolean; - deprecated: boolean; - allowEmptyValue: boolean; - allowReserved: boolean; -} - -export interface MediaType extends Extensions { - key: string; - accepts: Array; // equivalent media types for this media type (ie, text/json, application/json) - examples: Array; - encoding: Array; - schema?: Schema; -} - -export interface RequestBody extends Extensions { - description?: string; - contentType: string; - schema: Schema; - required: boolean; -} - -export interface Response extends Extensions { - description: string; - headers: Array
; - content: Dictionary; - links: Dictionary; -} - -export interface HttpParameterDetails extends ParameterDetails { - location: ImplementationLocation; -} - -export enum HttpMethod { - Get = 'get', - Put = 'put', - Post = 'post', - Delete = 'delete', - Options = 'options', - Head = 'head', - Patch = 'patch', - Trace = 'trace' -} - -export interface NewResponse { - details: LanguageDetails; - responseCode: string; - description: string; - headers: Array
; - headerSchema?: Schema; - mimeTypes: Array; // accepted equivalent media types for this media type (ie, text/json, application/json) - schema?: Schema; -} - -export class NewResponse extends Extensions implements NewResponse { - public details: LanguageDetails; - - constructor(public responseCode: string, public description: string, public mimeTypes: Array, objectInitializer?: DeepPartial) { - super(); - this.details = { - default: { - uid: `response:${uid()}`, - isErrorResponse: false, - description: description || objectInitializer?.description || '', - name: `${responseCode} ${mimeTypes.join(' ')}`, - } - }; - this.headers = new Array
(); - this.apply(objectInitializer); - } -} - -export class HttpOperation extends Extensions implements HttpOperation { - public details: LanguageDetails; - public tags = new Array(); - public parameters = new Array(); - public responses = new Dictionary>(); - public callbacks = new Dictionary(); - public security = new Array(); - public servers = new Array(); - public deprecated = false; - - constructor(operationId: string, public baseUrl: string, public path: string, public method: HttpMethod, initializer?: DeepPartial) { - super(); - this.details = { - default: { - uid: `http-operation:${uid()}`, - description: initializer?.description || '', - name: operationId, - } - }; - - this.apply(initializer); - } -} - -export interface HttpOperation extends IOperation, Extensions { - details: LanguageDetails; - - tags: Array; - summary?: string; - - externalDocs?: ExternalDocumentation; - - parameters: Array; - requestBody?: RequestBody; - responses: Dictionary>; - - callbacks: Dictionary; - deprecated: boolean; - security: Array; - servers: Array; - - path: string; - baseUrl: string; - method: HttpMethod; - pathDescription?: string; - pathSummary?: string; - pathExtensions?: Dictionary; -} - -export interface HttpOperationParameter extends IParameter { - - in: ParameterLocation; - explode?: boolean; - - encoding?: Array; - mediaType?: string; - style: EncodingStyle; - examples?: Dictionary; - allowReserved?: boolean; -} - -export class HttpOperationParameter extends Extensions implements HttpOperationParameter { - - public details: LanguageDetails; - public deprecated = false; - public required = false; - public allowEmptyValue = false; - - constructor(public name: string, inWhere: ParameterLocation, implementation: ImplementationLocation, initializer?: DeepPartial) { - super(); - this.in = inWhere; - this.details = { - default: { - uid: `http-parameter:${uid()}`, - description: initializer?.description || '', - location: implementation, - name, - } - }; - this.required = inWhere === ParameterLocation.Path; - this.apply(initializer); - } -} - -export function isHttpOperation(operation: IOperationBase): operation is HttpOperation { - if ((operation).path) { - return true; - } - return false; -} - -export class Callback implements Callback { - constructor() { - // unimplemented. - } -} - -export interface Callback extends Dictionary { -} - -export interface HttpComponents extends Components { - - examples: Dictionary; - securitySchemes: Dictionary; - links: Dictionary; - callbacks: Dictionary; -} - -export class HttpComponents extends Components implements HttpComponents { - public examples = new Dictionary(); - public securitySchemes = new Dictionary(); - public links = new Dictionary(); - public callbacks = new Dictionary(); - - constructor(initializer?: DeepPartial) { - super(); - this.apply(initializer); - } -} +// export enum EncodingStyle { +// Matrix = 'matrix', +// Label = 'label', +// Simple = 'simple', +// Form = 'form', +// SpaceDelimited = 'spaceDelimited', +// PipeDelimited = 'pipeDelimited', +// DeepObject = 'deepObject' +// } + +// export type QueryEncodingStyle = +// EncodingStyle.Form +// | EncodingStyle.SpaceDelimited +// | EncodingStyle.PipeDelimited +// | EncodingStyle.DeepObject; +// export type PathEncodingStyle = EncodingStyle.Matrix | EncodingStyle.Label | EncodingStyle.Simple; + +// export interface Encoding extends Extensions { +// key: string; +// contentType?: string; +// headers: Array
; +// style?: QueryEncodingStyle; +// explode?: boolean; +// allowReserved?: boolean; +// } + +// export interface Header extends Extensions { +// key: string; +// schema: Schema; +// explode?: boolean; +// examples: Dictionary; + +// description?: string; +// required: boolean; +// deprecated: boolean; +// allowEmptyValue: boolean; +// allowReserved: boolean; +// } + +// export interface MediaType extends Extensions { +// key: string; +// accepts: Array; // equivalent media types for this media type (ie, text/json, application/json) +// examples: Array; +// encoding: Array; +// schema?: Schema; +// } + +// export interface RequestBody extends Extensions { +// description?: string; +// contentType: string; +// schema: Schema; +// required: boolean; +// } + +// export interface Response extends Extensions { +// description: string; +// headers: Array
; +// content: Dictionary; +// links: Dictionary; +// } + +// export interface HttpParameterDetails extends ParameterDetails { +// location: ImplementationLocation; +// } + +// export enum HttpMethod { +// Get = 'get', +// Put = 'put', +// Post = 'post', +// Delete = 'delete', +// Options = 'options', +// Head = 'head', +// Patch = 'patch', +// Trace = 'trace' +// } + +// export interface NewResponse { +// details: LanguageDetails; +// responseCode: string; +// description: string; +// headers: Array
; +// headerSchema?: Schema; +// mimeTypes: Array; // accepted equivalent media types for this media type (ie, text/json, application/json) +// schema?: Schema; +// } + +// export class NewResponse extends Extensions implements NewResponse { +// public details: LanguageDetails; + +// constructor(public responseCode: string, public description: string, public mimeTypes: Array, objectInitializer?: DeepPartial) { +// super(); +// this.details = { +// default: { +// uid: `response:${uid()}`, +// isErrorResponse: false, +// description: description || objectInitializer?.description || '', +// name: `${responseCode} ${mimeTypes.join(' ')}`, +// } +// }; +// this.headers = new Array
(); +// this.apply(objectInitializer); +// } +// } + +// export class HttpOperation extends Extensions implements HttpOperation { +// public details: LanguageDetails; +// public tags = new Array(); +// public parameters = new Array(); +// public responses = new Dictionary>(); +// public callbacks = new Dictionary(); +// public security = new Array(); +// public servers = new Array(); +// public deprecated = false; + +// constructor(operationId: string, public baseUrl: string, public path: string, public method: HttpMethod, initializer?: DeepPartial) { +// super(); +// this.details = { +// default: { +// uid: `http-operation:${uid()}`, +// description: initializer?.description || '', +// name: operationId, +// } +// }; + +// this.apply(initializer); +// } +// } + +// export interface HttpOperation extends IOperation, Extensions { +// details: LanguageDetails; + +// tags: Array; +// summary?: string; + +// externalDocs?: ExternalDocumentation; + +// parameters: Array; +// requestBody?: RequestBody; +// responses: Dictionary>; + +// callbacks: Dictionary; +// deprecated: boolean; +// security: Array; +// servers: Array; + +// path: string; +// baseUrl: string; +// method: HttpMethod; +// pathDescription?: string; +// pathSummary?: string; +// pathExtensions?: Dictionary; +// } + +// export interface HttpOperationParameter extends IParameter { + +// in: ParameterLocation; +// explode?: boolean; + +// encoding?: Array; +// mediaType?: string; +// style: EncodingStyle; +// examples?: Dictionary; +// allowReserved?: boolean; +// } + +// export class HttpOperationParameter extends Extensions implements HttpOperationParameter { + +// public details: LanguageDetails; +// public deprecated = false; +// public required = false; +// public allowEmptyValue = false; + +// constructor(public name: string, inWhere: ParameterLocation, implementation: ImplementationLocation, initializer?: DeepPartial) { +// super(); +// this.in = inWhere; +// this.details = { +// default: { +// uid: `http-parameter:${uid()}`, +// description: initializer?.description || '', +// location: implementation, +// name, +// } +// }; +// this.required = inWhere === ParameterLocation.Path; +// this.apply(initializer); +// } +// } + +// export function isHttpOperation(operation: IOperationBase): operation is HttpOperation { +// if ((operation).path) { +// return true; +// } +// return false; +// } + +// export class Callback implements Callback { +// constructor() { +// // unimplemented. +// } +// } + +// export interface Callback extends Dictionary { +// } + +// export interface HttpComponents extends Components { + +// examples: Dictionary; +// securitySchemes: Dictionary; +// links: Dictionary; +// callbacks: Dictionary; +// } + +// export class HttpComponents extends Components implements HttpComponents { +// public examples = new Dictionary(); +// public securitySchemes = new Dictionary(); +// public links = new Dictionary(); +// public callbacks = new Dictionary(); + +// constructor(initializer?: DeepPartial) { +// super(); +// this.apply(initializer); +// } +// } diff --git a/powershell/utils/programatic-operation.ts b/powershell/utils/programatic-operation.ts index 2873889bf26..98c8fe7ede1 100644 --- a/powershell/utils/programatic-operation.ts +++ b/powershell/utils/programatic-operation.ts @@ -5,7 +5,8 @@ import { ImplementationDetails, IOperation, IParameter, LanguageDetails } from './components'; import { Extensions } from './extensions'; -import { Schema } from './schema'; +//import { Schema } from './schema'; +import { Schema } from '@azure-tools/codemodel'; import { Dictionary } from '@azure-tools/linq'; import { uid } from './uid'; import { DeepPartial } from '@azure-tools/codegen'; diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index ea040643a5e..583fb10fad7 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -8,6 +8,7 @@ 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 } from '@azure-tools/codemodel'; export interface PropertyDetails extends ImplementationDetails { required: boolean; @@ -94,36 +95,42 @@ export interface SchemaDetails extends ImplementationDetails { suppressFormat?: boolean; } -export class Schema extends Extensions implements Schema { - public details: LanguageDetails; - public required = new Array(); - public enum = new Array(); - public allOf = new Array(); - public oneOf = new Array(); - public anyOf = new Array(); - public properties = new Dictionary(); - public extensions = new Dictionary(); - - constructor(name: string, initializer?: DeepPartial) { - super(); - this.details = { - default: { - uid: `schema:${uid()}`, - description: '', - name - } - }; - this.apply(initializer); - } -} +// export class Schema extends Extensions implements Schema { +// public details: LanguageDetails; +// public required = new Array(); +// public enum = new Array(); +// public allOf = new Array(); +// public oneOf = new Array(); +// public anyOf = new Array(); +// public properties = new Dictionary(); +// public extensions = new Dictionary(); + +// constructor(name: string, initializer?: DeepPartial) { +// super(); +// this.details = { +// default: { +// uid: `schema:${uid()}`, +// description: '', +// name +// } +// }; +// this.apply(initializer); +// } +// } export function getPolymorphicBases(schema: Schema): Array { // are any of my parents polymorphic directly, or any of their parents? - return [...values(schema.allOf).where(parent => parent.discriminator ? true : false), ...values(schema.allOf).selectMany(getPolymorphicBases)]; + // skip-for-time-being + // return [...values(schema).where(parent => parent.discriminator ? true : false), ...values(schema.allOf).selectMany(getPolymorphicBases)]; + return []; } export function getAllProperties(schema: Schema): Array { - return [...values(schema.allOf).selectMany(getAllProperties), ...values(schema.properties)]; + if (schema instanceof ObjectSchema) { + return [...values(schema.parents ? schema.parents.immediate : []).selectMany(getAllProperties), ...values(schema.properties)]; + } else { + return []; + } } export function getAllPublicVirtualProperties(virtualProperties?: VirtualProperties): Array { @@ -156,35 +163,35 @@ export function getVirtualPropertyFromPropertyName(virtualProperties: VirtualPro } -export interface Property extends Extensions { - details: LanguageDetails; - - /** 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; - public extensions = new Dictionary(); - - constructor(name: string, initializer?: DeepPartial) { - super(); - this.serializedName = name; - this.details = { - default: { - readOnly: false, - uid: `property:${uid()}`, - description: initializer?.description || '', - name, - required: false - } - }; - this.apply(initializer); - } -} +// export interface Property extends Extensions { +// details: LanguageDetails; + +// /** 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; +// public extensions = new Dictionary(); + +// constructor(name: string, initializer?: DeepPartial) { +// 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(); @@ -211,7 +218,7 @@ export enum JsonType { } export function isJsonType(type: JsonType, schema?: Schema): schema is Schema { - return schema ? schema.type === type : false; + return schema ? schema.type === SchemaType.Object : false; } export function isSchemaObject(schema?: Schema): schema is Schema { @@ -237,60 +244,60 @@ export interface XML extends Extensions { wrapped: boolean; } -export interface Schema extends Extensions { - - details: LanguageDetails; - - /* common properties */ - type?: JsonType; - title?: string; - description?: string; - format?: string; - nullable: boolean; - readOnly: boolean; - writeOnly: boolean; - deprecated: boolean; - required: Array; - - /* 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; - - /* properties with potential references */ - not?: Schema; - allOf: Array; - oneOf: Array; - anyOf: Array; - items?: Schema; - properties: Dictionary; - additionalProperties?: boolean | Schema; -} +// export interface Schema extends Extensions { + +// details: LanguageDetails; + +// /* common properties */ +// type?: JsonType; +// title?: string; +// description?: string; +// format?: string; +// nullable: boolean; +// readOnly: boolean; +// writeOnly: boolean; +// deprecated: boolean; +// required: Array; + +// /* 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; + +// /* properties with potential references */ +// not?: Schema; +// allOf: Array; +// oneOf: Array; +// anyOf: Array; +// items?: Schema; +// properties: Dictionary; +// additionalProperties?: boolean | Schema; +// } From 4aa82aced65b9d579840df344f60fd3dd44e4e66 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Jul 2020 16:35:53 +0800 Subject: [PATCH 04/61] Add support for basic types like integer/number/array/boolean/.etc --- powershell/cmdlets/class.ts | 24 +- powershell/internal/project.ts | 4 +- powershell/llcsharp/model/interface.ts | 4 +- .../llcsharp/model/model-class-serializer.ts | 6 +- powershell/llcsharp/model/model-class.ts | 4 +- powershell/llcsharp/model/namespace.ts | 18 +- powershell/llcsharp/operation/method.ts | 2 +- powershell/llcsharp/operation/parameter.ts | 10 +- powershell/llcsharp/schema/Uuid.ts | 19 +- powershell/llcsharp/schema/array.ts | 309 +++++++++++++++--- powershell/llcsharp/schema/binary.ts | 78 ++++- powershell/llcsharp/schema/boolean.ts | 20 +- powershell/llcsharp/schema/byte-array.ts | 107 +++++- powershell/llcsharp/schema/char.ts | 35 +- powershell/llcsharp/schema/date-time.ts | 182 ++++++++++- powershell/llcsharp/schema/date.ts | 10 +- powershell/llcsharp/schema/duration.ts | 62 +++- powershell/llcsharp/schema/enum.ts | 26 +- .../schema/extended-type-declaration.ts | 50 ++- powershell/llcsharp/schema/integer.ts | 39 ++- powershell/llcsharp/schema/object.ts | 8 +- powershell/llcsharp/schema/primitive.ts | 188 ++++++++++- powershell/llcsharp/schema/schema-resolver.ts | 118 ++++--- powershell/llcsharp/schema/string.ts | 4 +- powershell/models/model-extensions.ts | 2 +- powershell/plugins/plugin-tweak-model.ts | 1 + 26 files changed, 1170 insertions(+), 160 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index bf22d717ff5..08f0f989406 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter } from '@azure-tools/codemodel'; +import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter, ObjectSchema } from '@azure-tools/codemodel'; import { command, getAllProperties, JsonType, http, getAllPublicVirtualProperties, getVirtualPropertyFromPropertyName, ParameterLocation, getAllVirtualProperties, VirtualParameter, VirtualProperty } from '@azure-tools/codemodel-v3'; import { CommandOperation, VirtualParameter as NewVirtualParameter } from '../utils/command-operation'; import { getAllProperties as NewGetAllProperties, getAllPublicVirtualProperties as NewGetAllPublicVirtualProperties, getVirtualPropertyFromPropertyName as NewGetVirtualPropertyFromPropertyName, VirtualProperty as NewVirtualProperty } from '../utils/schema'; @@ -13,7 +13,7 @@ import { Access, Attribute, BackedProperty, Catch, Class, ClassType, Constructor, dotnet, Else, Expression, Finally, ForEach, If, LambdaProperty, LiteralExpression, LocalVariable, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Property, Return, Statements, BlockStatement, StringExpression, Switch, System, TerminalCase, toExpression, Try, Using, valueOf, Field, IsNull, Or, ExpressionOrLiteral, TerminalDefaultCase, xmlize, TypeDeclaration, And, IsNotNull, PartialMethod, Case } from '@azure-tools/codegen-csharp'; -import { ClientRuntime, EventListener, Schema, ArrayOf, EnumImplementation } from '../llcsharp/exports'; +import { ClientRuntime, EventListener, Schema, ArrayOf, NewArrayOf, EnumImplementation, NewEnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; import { State, NewState } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; @@ -2408,10 +2408,10 @@ export class NewCmdletClass extends Class { addDefaultInfo(cmdletParameter, vParam); } - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; + const isEnum = propertyType.schema.language.csharp?.enum !== undefined; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { - cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } // add aliases if there is any if (length(vParam.alias) > 0) { @@ -2549,10 +2549,10 @@ export class NewCmdletClass extends Class { // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); } - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; + const isEnum = propertyType.schema.language.csharp?.enum !== undefined; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { - regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } } const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); @@ -2614,15 +2614,15 @@ export class NewCmdletClass extends Class { } else { let type = ''; - if (typeDeclaration instanceof ArrayOf) { + if (typeDeclaration instanceof NewArrayOf) { type = typeDeclaration.elementTypeDeclaration; - } else if (!(typeDeclaration.schema instanceof NewSchema) && pageableInfo && pageableInfo.responseType === 'pageable') { - if (typeDeclaration === undefined || typeDeclaration.schema.properties[pageableInfo.itemName] === undefined) { + } else if (pageableInfo && pageableInfo.responseType === 'pageable') { + if (typeDeclaration === undefined || (typeDeclaration.schema).properties?.[pageableInfo.itemName] === undefined) { //skip-for-time-being, since operationId does not support in m4 any more //throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); throw new Error('An error needs to be more specific'); } - const nestedSchema = typeDeclaration.schema.properties[pageableInfo.itemName].schema; + const nestedSchema = (typeDeclaration.schema).properties?.[pageableInfo.itemName].schema; // skip-for-time-being //const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); //type = (nestedTypeDeclaration).elementTypeDeclaration; diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 0eae54dc905..c031248bcdf 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, Boolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; +import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; import { State, NewState } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; import { EnumNamespace, NewEnumNamespace } from '../enums/namespace'; @@ -61,7 +61,7 @@ export class PSSchemaResolver extends SchemaDefinitionResolver { export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { inResolve = false; - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): EnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { const before = this.inResolve; try { // skip-for-time-being diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index 15d40c5f1fe..e09576d5969 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -10,7 +10,7 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, Language } from '@azure-tools/codemodel'; import { State, NewState } from '../generator'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ModelClass, NewModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; @@ -223,7 +223,7 @@ export class ModelInterface extends Interface implements EnhancedTypeDeclaration } } -export class NewModelInterface extends Interface implements EnhancedTypeDeclaration { +export class NewModelInterface extends Interface implements NewEnhancedTypeDeclaration { get schema(): NewSchema { return this.classImplementation.schema; } diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index eb2ac30e105..7a6e7b48498 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -24,7 +24,7 @@ import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; import { ModelClass } from './model-class'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; import { ModelProperty } from './property'; @@ -72,7 +72,7 @@ export class SerializationPartialClass extends Initializer { } export class NewSerializationPartialClass extends Initializer { - constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } @@ -216,7 +216,7 @@ export class DeserializerPartialClass extends SerializationPartialClass { export class NewDeserializerPartialClass extends NewSerializationPartialClass { private beforeDeserialize!: Method; private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 7c01b6196a6..b3f613542c1 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -9,7 +9,7 @@ import { items, values } from '@azure-tools/linq'; import { Access, Class, Constructor, Expression, ExpressionOrLiteral, Field, If, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Statements, System, TypeDeclaration, valueOf, Variable, BackedProperty, Property, Virtual, toExpression, StringExpression, LiteralExpression, Attribute } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { State, NewState } from '../generator'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; import { ModelInterface, NewModelInterface } from './interface'; import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-json'; @@ -493,7 +493,7 @@ export class ModelClass extends Class implements EnhancedTypeDeclaration { } } -export class NewModelClass extends Class implements EnhancedTypeDeclaration { +export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); } diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 583cd624e20..c651d1befb2 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -9,13 +9,13 @@ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { State, NewState } from '../generator'; -import { EnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../schema/schema-resolver'; import { EnumClass } from '../enums/enum'; import * as validation from '../validations'; -import { ModelInterface } from './interface'; +import { ModelInterface, NewModelInterface } from './interface'; import { ModelClass, NewModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -116,7 +116,7 @@ export class ModelsNamespace extends Namespace { } return td; } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): EnhancedTypeDeclaration { + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -135,14 +135,14 @@ export class ModelsNamespace extends Namespace { const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; + return schema.language.csharp?.interfaceImplementation; } if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { return td; } - if (td instanceof EnumImplementation) { + if (td instanceof NewEnumImplementation) { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { @@ -193,7 +193,7 @@ export class NewModelsNamespace extends Namespace { return 'Models'; } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): EnhancedTypeDeclaration { + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -212,14 +212,14 @@ export class NewModelsNamespace extends Namespace { const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; + return schema.language.csharp?.interfaceImplementation; } if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { return td; } - if (td instanceof EnumImplementation) { + if (td instanceof NewEnumImplementation) { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 2684e51e14b..58a7c338950 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -291,7 +291,7 @@ export class NewOperationMethod extends Method { public contextParameter!: Parameter; public senderParameter!: Parameter; public resourceUri!: Parameter; - public callbacks = new Array(); + public callbacks = new Array(); protected callName: string; diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index ada0719dbf0..77daa09a41d 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -15,7 +15,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { HttpOperationParameter, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { State, NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; @@ -68,7 +68,7 @@ export class OperationParameter extends Parameter implements EnhancedVariable { } export class NewOperationParameter extends Parameter implements EnhancedVariable { - public typeDeclaration: EnhancedTypeDeclaration; + public typeDeclaration: NewEnhancedTypeDeclaration; public param: NewHttpOperationParameter; @@ -206,10 +206,10 @@ export class CallbackParameter extends Parameter { } export class NewCallbackParameter extends Parameter { - responseType: (EnhancedTypeDeclaration) | null; - headerType: (EnhancedTypeDeclaration) | null; + responseType: (NewEnhancedTypeDeclaration) | null; + headerType: (NewEnhancedTypeDeclaration) | null; - constructor(name: string, responseType: (EnhancedTypeDeclaration) | null, headerType: (EnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, responseType: (NewEnhancedTypeDeclaration) | null, headerType: (NewEnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { // regular pipeline style. (callback happens after the pipline is called) if (responseType) { if (headerType) { diff --git a/powershell/llcsharp/schema/Uuid.ts b/powershell/llcsharp/schema/Uuid.ts index 03b3d9a23cf..55486b5dedf 100644 --- a/powershell/llcsharp/schema/Uuid.ts +++ b/powershell/llcsharp/schema/Uuid.ts @@ -6,7 +6,8 @@ import { nameof } from '@azure-tools/codegen'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { String } from './string'; +import { StringSchema } from '@azure-tools/codemodel'; +import { String, NewString } from './string'; export class Uuid extends String { constructor(schema: Schema, isRequired: boolean) { @@ -23,3 +24,19 @@ export class Uuid extends String { return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$");`; } } + +export class NewUuid extends NewString { + constructor(schema: StringSchema, isRequired: boolean) { + super(schema, isRequired); + } + + get declaration(): string { + return 'string'; + } + public validatePresence(eventListener: Variable, property: Variable): string { + return this.isRequired ? `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim() : ''; + } + validateValue(eventListener: Variable, property: Variable): string { + return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$");`; + } +} diff --git a/powershell/llcsharp/schema/array.ts b/powershell/llcsharp/schema/array.ts index 1c1be135f89..16794ca1772 100644 --- a/powershell/llcsharp/schema/array.ts +++ b/powershell/llcsharp/schema/array.ts @@ -19,7 +19,7 @@ import { Schema as NewSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; export class ArrayOf implements EnhancedTypeDeclaration { public isXmlAttribute = false; @@ -28,26 +28,16 @@ export class ArrayOf implements EnhancedTypeDeclaration { return toExpression('null /* arrayOf */'); } - constructor(public schema: Schema | NewSchema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { + constructor(public schema: Schema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { } protected get isWrapped(): boolean { - if (this.schema instanceof NewSchema) { - return this.schema.serialization?.xml && this.schema.serialization?.xml.wrapped || false; - } else { - return this.schema.xml && this.schema.xml.wrapped || false; - } - + return this.schema.xml && this.schema.xml.wrapped || false; } protected get wrapperName(): string | undefined { - if (this.schema instanceof NewSchema) { - return this.schema.serialization?.xml && this.isWrapped ? this.schema.serialization.xml.name : undefined; - } else { - return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; - } - + return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; } protected get serializedName(): string | undefined { @@ -66,6 +56,249 @@ export class ArrayOf implements EnhancedTypeDeclaration { return `${this.elementType.declaration}[]`; } + get encode(): string { + return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; + } + + get convertObjectMethod() { + try { + const v = pushTempVar(); + const i = pushTempVar(); + // return `${v} => ${v} is string || !(${v} is global::System.Collections.IEnumerable) ? new ${this.declaration} { ${this.elementType.convertObjectMethod}(${v}) } : System.Linq.Enumerable.ToArray( System.Linq.Enumerable.Select( System.Linq.Enumerable.OfType((global::System.Collections.IEnumerable)${v}), ${this.elementType.convertObjectMethod}))` + return `${v} => TypeConverterExtensions.SelectToArray<${this.elementTypeDeclaration}>(${v}, ${this.elementType.convertObjectMethod})`; + } finally { + popTempVar(); + popTempVar(); + } + } + + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + // json array + const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; + return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonArray}>("${serializedName}"), out var ${tmp}) ? ${this.deserializeFromNode(mediaType, tmp, toExpression('null'))} : ${defaultValue}`); + } + + case KnownMediaType.Xml: { + // XElement/XElement + const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; + if (this.isWrapped) { + // wrapped xml arrays will have a container around them. + return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}?.Element("${this.serializedName || serializedName}")`, defaultValue)}`); + } else { + // whereas non-wrapped will have all the elements in the container directly. + return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}`, defaultValue)}`); + } + } + } + return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + try { + const tmp = pushTempVar(); + const each = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: { + // const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp} , (${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}) ) )`; + + const deser = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(tmp, `(${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}`)); + + return toExpression(`If( ${valueOf(node)} as ${ClientRuntime.JsonArray}, out var ${tmp}) ? ${System.Func(this).new(`()=> ${valueOf(deser)} )`)}() : ${defaultValue}`); + } + case KnownMediaType.Xml: { + // XElement should be a container of items, right? + // if the reference doesn't define an XML schema then use its default name + //const defaultName = this.elementType.schema.details.csharp.name; + //const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp}.Elements("${this.elementType.schema.xml ? this.elementType.schema.xml.name || defaultName : defaultName}"), (${each})=> ${this.elementType.deserializeFromNode(mediaType, each, toExpression('null'))} ) )`; + + //return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? new System.Func<${this.elementType.declaration}[]>(()=> ${deser} )() : ${defaultValue}`); + } + } + } finally { + popTempVar(); + popTempVar(); + } + return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + switch (mediaType) { + case KnownMediaType.Json: { + return this.deserializeFromNode(mediaType, ClientRuntime.JsonArray.Parse(content), defaultValue); + } + case KnownMediaType.Xml: { + return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); + } + } + return undefined; + } + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + switch (mediaType) { + case KnownMediaType.Xml: + case KnownMediaType.Json: { + return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); + } + } + return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + + try { + const each = pushTempVar(); + + switch (mediaType) { + case KnownMediaType.Json: { + const serArray = `global::System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}))`; + return toExpression(`null != ${value} ? new ${ClientRuntime.XNodeArray}(${serArray}) : null`); + } + + case KnownMediaType.Xml: { + if (this.isWrapped) { + const name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; + return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); + } else { + throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); + } + } + case KnownMediaType.Cookie: + case KnownMediaType.QueryParameter: + return toExpression(`(null != ${value} && ${value}.Length > 0 ? "${value}=" + ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current, each) => current + "," + ( ${this.encode}(each?.ToString()??${System.String.Empty}) ))) : ${System.String.Empty})`); + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + return toExpression(`(null != ${value} ? ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); + } + } finally { + popTempVar(); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + try { + const each = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: { + return System.Net.Http.StringContent.new( + `${(this.serializeToNode(mediaType, value, '', mode))}`, + System.Text.Encoding.UTF8); + } + case KnownMediaType.Xml: { + // if the reference doesn't define an XML schema then use its default name + const defaultName = this.elementType.schema.details.csharp.name; + return System.Net.Http.StringContent.new(Ternery( + IsNotNull(value), + `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, + System.String.Empty + ), System.Text.Encoding.UTF8); + } + + case KnownMediaType.Cookie: + case KnownMediaType.QueryParameter: + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + return toExpression(`(null != ${value} ? ${this.encode}(System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); + } + + } finally { + popTempVar(); + } + + return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + try { + const each = pushTempVar(); + const tmp = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const $this = this; + return If(`null != ${value}`, function* () { + const t = new LocalVariable(tmp, dotnet.Var, { initializer: `new ${ClientRuntime.XNodeArray}()` }); + yield t.declarationStatement; + yield ForEach(each, toExpression(value), `AddIf(${$this.elementType.serializeToNode(mediaType, each, '', mode)} ,${tmp}.Add);`); + yield `${container}.Add("${serializedName}",${tmp});`; + }); + } + case KnownMediaType.Xml: + if (this.isWrapped) { + return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; + } else { + return If(`null != ${value}`, ForEach(each, toExpression(value), `AddIf(${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}, ${container}.Add);`)); + } + } + } finally { + popTempVar(); + popTempVar(); + } + return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { + if (this.isRequired) { + return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `; + } + return ''; + } + validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { + // check if the underlyingType has validation. + if (!this.elementType.validateValue(eventListener, new LocalVariable(`${property} [{ __i }]`, dotnet.Var))) { + return ''; + } + + return ` + if (${ property} != null ) { + for (int __i = 0; __i < ${ property}.Length; __i++) { + ${ this.elementType.validateValue(eventListener, new LocalVariable(`${property}[__i]`, dotnet.Var))} + } + } + `.trim(); + } +} + +export class NewArrayOf implements NewEnhancedTypeDeclaration { + public isXmlAttribute = false; + public isNullable = true; + get defaultOfType() { + return toExpression('null /* arrayOf */'); + } + + constructor(public schema: NewSchema, public isRequired: boolean, public elementType: NewEnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { + } + + + protected get isWrapped(): boolean { + return this.schema.serialization?.xml && this.schema.serialization?.xml.wrapped || false; + } + + protected get wrapperName(): string | undefined { + return this.schema.serialization?.xml && this.isWrapped ? this.schema.serialization.xml.name : undefined; + } + + protected get serializedName(): string | undefined { + return this.schema.serialization?.xml ? this.schema.serialization.xml.name : undefined; + } + get elementTypeDeclaration(): string { + return this.elementType.declaration; + } + + get declaration(): string { + return `${this.elementType.declaration}[]`; + } + get encode(): string { this.schema.extensions = this.schema.extensions || {}; return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; @@ -170,20 +403,14 @@ export class ArrayOf implements EnhancedTypeDeclaration { const serArray = `global::System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}))`; return toExpression(`null != ${value} ? new ${ClientRuntime.XNodeArray}(${serArray}) : null`); } - // skip-for-time-being - // case KnownMediaType.Xml: { - // if (this.isWrapped) { - // let name = ''; - // if (this.elementType.schema instanceof NewSchema) { - // name = this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || serializedName : serializedName; - // } else { - // name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; - // } - // return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); - // } else { - // throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); - // } - // } + case KnownMediaType.Xml: { + if (this.isWrapped) { + const name = this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || serializedName : serializedName; + return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); + } else { + throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); + } + } case KnownMediaType.Cookie: case KnownMediaType.QueryParameter: return toExpression(`(null != ${value} && ${value}.Length > 0 ? "${value}=" + ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current, each) => current + "," + ( ${this.encode}(each?.ToString()??${System.String.Empty}) ))) : ${System.String.Empty})`); @@ -208,16 +435,15 @@ export class ArrayOf implements EnhancedTypeDeclaration { `${(this.serializeToNode(mediaType, value, '', mode))}`, System.Text.Encoding.UTF8); } - // skip-for-time-being - // case KnownMediaType.Xml: { - // // if the reference doesn't define an XML schema then use its default name - // const defaultName = this.elementType.schema.details.csharp.name; - // return System.Net.Http.StringContent.new(Ternery( - // IsNotNull(value), - // `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, - // System.String.Empty - // ), System.Text.Encoding.UTF8); - // } + case KnownMediaType.Xml: { + // if the reference doesn't define an XML schema then use its default name + const defaultName = this.elementType.schema.language.csharp?.name || ''; + return System.Net.Http.StringContent.new(Ternery( + IsNotNull(value), + `${this.serializeToNode(mediaType, value, this.schema.serialization?.xml ? this.schema.serialization.xml?.name || defaultName : defaultName, mode)}).ToString()`, + System.String.Empty + ), System.Text.Encoding.UTF8); + } case KnownMediaType.Cookie: case KnownMediaType.QueryParameter: @@ -252,11 +478,7 @@ export class ArrayOf implements EnhancedTypeDeclaration { } case KnownMediaType.Xml: if (this.isWrapped) { - if (this.elementType.schema instanceof NewSchema) { - return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; - } else { - return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; - } + return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.serialization?.xml ? this.elementType.schema.serialization?.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; } else { return If(`null != ${value}`, ForEach(each, toExpression(value), `AddIf(${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}, ${container}.Add);`)); } @@ -289,3 +511,4 @@ export class ArrayOf implements EnhancedTypeDeclaration { `.trim(); } } + diff --git a/powershell/llcsharp/schema/binary.ts b/powershell/llcsharp/schema/binary.ts index a0cf767083d..da9c9a0bf8a 100644 --- a/powershell/llcsharp/schema/binary.ts +++ b/powershell/llcsharp/schema/binary.ts @@ -10,7 +10,8 @@ import { Expression, ExpressionOrLiteral, toExpression } from '@azure-tools/code import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { BinarySchema } from '@azure-tools/codemodel'; export class Binary implements EnhancedTypeDeclaration { public isXmlAttribute = false; @@ -86,3 +87,78 @@ export class Binary implements EnhancedTypeDeclaration { return ''; } } + +export class NewBinary implements NewEnhancedTypeDeclaration { + public isXmlAttribute = false; + constructor(public schema: BinarySchema, public isRequired: boolean) { + } + + get convertObjectMethod() { + return 'i=>i'; + } + public isNullable = true; + + get defaultOfType() { + return toExpression('null /* binary type */'); + } + + get declaration(): string { + return System.IO.Stream.declaration; + } + + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + if (mediaType === KnownMediaType.Stream) { + // dunno. + } + if (mediaType === KnownMediaType.Json) { + return toExpression('null /* no need to deserialize a stream here */ '); + } + return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return undefined; + } + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return toExpression(`${valueOf(content)}.Content.ReadAsStreamAsync()`); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + if (mediaType === KnownMediaType.Stream) { + return toExpression(System.Net.Http.StreamContent.new(value)); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + if (mediaType === KnownMediaType.Json) { + return `/* shouldn't need to serialize binary for a ${mediaType} */`; + } + return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; + } + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } + + public validatePresence(eventListener: Variable, property: Variable): string { + if (this.isRequired) { + return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); + } + return ''; + } +} diff --git a/powershell/llcsharp/schema/boolean.ts b/powershell/llcsharp/schema/boolean.ts index 8890200beaf..8942f25e507 100644 --- a/powershell/llcsharp/schema/boolean.ts +++ b/powershell/llcsharp/schema/boolean.ts @@ -6,7 +6,8 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Primitive } from './primitive'; +import { Schema as NewSchema, BooleanSchema } from '@azure-tools/codemodel'; +import { Primitive, NewPrimitive } from './primitive'; export class Boolean extends Primitive { isXmlAttribute = false; @@ -24,3 +25,20 @@ export class Boolean extends Primitive { return ''; } } + +export class NewBoolean extends NewPrimitive { + isXmlAttribute = false; + jsonType = ClientRuntime.JsonBoolean; + + constructor(schema: BooleanSchema, public isRequired: boolean) { + super(schema); + } + + get declaration(): string { + return `bool${this.isRequired ? '' : '?'}`; + } + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } +} diff --git a/powershell/llcsharp/schema/byte-array.ts b/powershell/llcsharp/schema/byte-array.ts index 8025bd4c016..9d36914c92b 100644 --- a/powershell/llcsharp/schema/byte-array.ts +++ b/powershell/llcsharp/schema/byte-array.ts @@ -10,8 +10,9 @@ import { If } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; +import { Schema as NewSchema, ByteArraySchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; export class ByteArray implements EnhancedTypeDeclaration { @@ -117,3 +118,107 @@ export class ByteArray implements EnhancedTypeDeclaration { return ''; } } + +export class NewByteArray implements NewEnhancedTypeDeclaration { + public isXmlAttribute = false; + + get declaration(): string { + return 'byte[]'; + } + + get convertObjectMethod() { + return 'i => i'; + } + + public isNullable = true; + + get defaultOfType() { + return toExpression('null /* byte array */'); + } + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + try { + const tmp = pushTempVar(); + + switch (mediaType) { + case KnownMediaType.Xml: { + return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}")?.Value, out var ${tmp}) ? System.Convert.FromBase64String(${tmp}.Replace("_","/").Replace("-","+").PadRight( ${tmp}.Length + ${tmp}.Length * 3 % 4, '=')) : ${defaultValue}`); + } + case KnownMediaType.Json: { + return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmp}) ? System.Convert.FromBase64String( ((string)${tmp}).Replace("_","/").Replace("-","+").PadRight( ((string)${tmp}).Length + ((string)${tmp}).Length * 3 % 4, '=') ) : null`); + } + case KnownMediaType.Header: { + //const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; + return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? System.Convert.FromBase64String(${tmp}) : ${defaultValue}`); + } + } + } finally { + popTempVar(); + } + return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + return toExpression(`${ClientRuntime.JsonString.new(`System.Convert.ToBase64String(${value})`)}`); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + /** emits an expression serialize this to the value required by the container */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); + } + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}*/`); + } + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + try { + const b = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Xml: { + return `AddIf( null != ${value} ? ${System.Xml.Linq.XElement.new(serializedName, System.Convert.ToBase64String(value))} : null, ${container}.Add);`; + } + + case KnownMediaType.Json: { + return `AddIf( null != ${value} ? ${System.Convert.ToBase64String(value)} : null ,(v)=> ${container}.Add( "${serializedName}",v) );`; + } + + case KnownMediaType.Header: { + return If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}", ${System.Convert.ToBase64String(value)});`); + } + } + + } finally { + popTempVar(); + } + return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; + } + + constructor(public schema: ByteArraySchema, public isRequired: boolean) { + } + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } + + public validatePresence(eventListener: Variable, property: Variable): string { + if (this.isRequired) { + return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); + } + return ''; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/char.ts b/powershell/llcsharp/schema/char.ts index 9444296135b..68c576b39a8 100644 --- a/powershell/llcsharp/schema/char.ts +++ b/powershell/llcsharp/schema/char.ts @@ -6,7 +6,8 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Primitive } from './primitive'; +import { Schema as NewSchema, SchemaType, ChoiceSchema, ChoiceValue } from '@azure-tools/codemodel'; +import { Primitive, NewPrimitive } from './primitive'; import { length } from '@azure-tools/linq'; export class Char extends Primitive { @@ -40,3 +41,35 @@ ${this.validateEnum(property)} return '// todo validate enum choices'; } } + +export class NewChar extends NewPrimitive { + public isXmlAttribute = false; + private choices?: Array; + jsonType = ClientRuntime.JsonString; + + constructor(schema: NewSchema, public isRequired: boolean) { + super(schema); + this.choices = schema.type === SchemaType.Choice ? (schema).choices : undefined; + } + + get declaration(): string { + return `char${this.isRequired ? '' : ' ?'}`; + } + + get convertObjectMethod() { + return 'global::System.Convert.Char'; + } + + validateValue(eventListener: Variable, property: Variable): string { + return ` +${this.validateEnum(property)} + `.trim(); + } + + private validateEnum(property: Variable): string { + if (!this.choices) { + return ''; + } + return '// todo validate enum choices'; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/date-time.ts b/powershell/llcsharp/schema/date-time.ts index cfca85c32ca..165b1095f66 100644 --- a/powershell/llcsharp/schema/date-time.ts +++ b/powershell/llcsharp/schema/date-time.ts @@ -11,7 +11,8 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Primitive } from './primitive'; +import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema } from '@azure-tools/codemodel'; +import { Primitive, NewPrimitive } from './primitive'; export class DateTime extends Primitive { public isXmlAttribute = false; @@ -105,6 +106,98 @@ export class DateTime extends Primitive { } } +export class NewDateTime extends NewPrimitive { + public isXmlAttribute = false; + public jsonType = ClientRuntime.JsonString; + // public DateFormat = new StringExpression('yyyy-MM-dd'); + public DateTimeFormat = new StringExpression('yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss.fffffffK'); + + get encode(): string { + return (this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding']) ? '' : 'global::System.Uri.EscapeDataString'; + } + + get declaration(): string { + return `global::System.DateTime${this.isRequired ? '' : '?'}`; + } + protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; + } + protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; + } + + get convertObjectMethod() { + return '(v) => v is global::System.DateTime _v ? _v : global::System.Xml.XmlConvert.ToDateTime( v.ToString() , global::System.Xml.XmlDateTimeSerializationMode.Unspecified)'; + } + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + return this.isRequired ? + toExpression(`(${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : + toExpression(`null != ${value} ? (${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); + + case KnownMediaType.Xml: + return this.isRequired ? + toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : + toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); + + case KnownMediaType.Cookie: + case KnownMediaType.QueryParameter: + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + return toExpression(this.isRequired ? + `"${serializedName}=" + ${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)` : + `(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))` + ); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + switch (mediaType) { + case KnownMediaType.Json: + // container : JsonObject + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; + + case KnownMediaType.Xml: + // container : XElement + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; + + case KnownMediaType.Header: + // container : HttpRequestHeaders + return this.isRequired ? + `${valueOf(container)}.Add("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));` : + If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));`); + + case KnownMediaType.QueryParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : + `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; + + case KnownMediaType.UriParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : + `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; + } + return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + constructor(schema: DateTimeSchema, public isRequired: boolean) { + super(schema); + } + // public static string DateFormat = "yyyy-MM-dd"; + // public static string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; + // public static string DateTimeRfc1123Format = "R"; + // public static JsonString CreateDate(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateFormat, CultureInfo.InvariantCulture)) : null; + // public static JsonString CreateDateTime(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeFormat, CultureInfo.InvariantCulture)) : null; + // public static JsonString CreateDateTimeRfc1123(DateTime ? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeRfc1123Format, CultureInfo.InvariantCulture)) : null; + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } +} + export class DateTime1123 extends DateTime { public DateTimeFormat = new StringExpression('R'); constructor(schema: Schema, isRequired: boolean) { @@ -112,6 +205,13 @@ export class DateTime1123 extends DateTime { } } +export class NewDateTime1123 extends NewDateTime { + public DateTimeFormat = new StringExpression('R'); + constructor(schema: DateTimeSchema, isRequired: boolean) { + super(schema, isRequired); + } +} + export class UnixTime extends Primitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; @@ -149,7 +249,7 @@ export class UnixTime extends Primitive { return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); } - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); + // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); case KnownMediaType.Cookie: case KnownMediaType.Header: @@ -189,3 +289,81 @@ export class UnixTime extends Primitive { return `global::System.DateTime${this.isRequired ? '' : '?'}`; } } + +export class NewUnixTime extends NewPrimitive { + public isXmlAttribute = false; + public jsonType = ClientRuntime.JsonNumber; + + private EpochDate = System.DateTime.new('1970', '1', '1', '0', '0', '0', System.DateTimeKind.Utc); + + get encode(): string { + return (this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding']) ? '' : 'global::System.Uri.EscapeDataString'; + } + + + protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; + } + protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + return this.isRequired ? + this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`).Cast(ClientRuntime.JsonNode) : + Ternery(IsNotNull(value), this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds)??0)`).Cast(ClientRuntime.JsonNode), dotnet.Null); + + case KnownMediaType.Xml: + return this.isRequired ? + toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : + toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); + + case KnownMediaType.QueryParameter: + if (this.isRequired) { + return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); + } else { + return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); + } + + // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); + + case KnownMediaType.Cookie: + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + return toExpression(this.isRequired ? + `(${value}.ToString())` : + `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` + ); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to the value required by the container */ + _serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + return super.serializeToNode(mediaType, new LiteralExpression(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`), serializedName, mode); + } + + get q(): string { + return this.isRequired ? '' : '?'; + } + + get longType(): string { + return this.isRequired ? 'long' : 'long?'; + } + + + constructor(schema: UnixTimeSchema, public isRequired: boolean) { + super(schema); + } + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } + + get declaration(): string { + return `global::System.DateTime${this.isRequired ? '' : '?'}`; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/date.ts b/powershell/llcsharp/schema/date.ts index dbfeb5f6bf1..0b231bd8b8e 100644 --- a/powershell/llcsharp/schema/date.ts +++ b/powershell/llcsharp/schema/date.ts @@ -5,7 +5,8 @@ import { StringExpression } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { DateTime } from './date-time'; +import { Schema as NewSchema, DateTimeSchema } from '@azure-tools/codemodel'; +import { DateTime, NewDateTime } from './date-time'; export class Date extends DateTime { public DateTimeFormat = new StringExpression('yyyy-MM-dd'); @@ -13,3 +14,10 @@ export class Date extends DateTime { super(schema, isRequired); } } + +export class NewDate extends NewDateTime { + public DateTimeFormat = new StringExpression('yyyy-MM-dd'); + constructor(schema: DateTimeSchema, isRequired: boolean) { + super(schema, isRequired); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/duration.ts b/powershell/llcsharp/schema/duration.ts index db32fa8e191..1203f8fb816 100644 --- a/powershell/llcsharp/schema/duration.ts +++ b/powershell/llcsharp/schema/duration.ts @@ -8,7 +8,8 @@ import { Expression, ExpressionOrLiteral, toExpression, System, valueOf } from ' import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { Primitive } from './primitive'; +import { Schema as NewSchema, DurationSchema } from '@azure-tools/codemodel'; +import { Primitive, NewPrimitive } from './primitive'; import { ClientRuntime } from '../clientruntime'; export class Duration extends Primitive { @@ -69,3 +70,62 @@ export class Duration extends Primitive { return ''; } } + +export class NewDuration extends NewPrimitive { + public isXmlAttribute = false; + public jsonType = ClientRuntime.JsonString; + + constructor(public schema: DurationSchema, public isRequired: boolean) { + super(schema); + } + + get encode(): string { + return (this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding']) ? '' : 'global::System.Uri.EscapeDataString'; + } + + get declaration(): string { + return `global::System.TimeSpan${this.isRequired ? '' : '?'}`; + } + + protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `global::System.Xml.XmlConvert.ToTimeSpan( ${tmpValue} )`; + } + + get convertObjectMethod() { + return '(v) => v is global::System.TimeSpan _v ? _v : global::System.Xml.XmlConvert.ToTimeSpan( v.ToString() )'; + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + if (!this.isRequired) { + return toExpression(`(null != ${value} ? ${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}: null)`).Cast(ClientRuntime.JsonNode); + } + return toExpression(`${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}`).Cast(ClientRuntime.JsonNode); + + case KnownMediaType.QueryParameter: + if (this.isRequired) { + return toExpression(`"${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value}))`); + } else { + return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})))`); + } + } + return toExpression(`/* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + switch (mediaType) { + case KnownMediaType.Json: + // container : JsonObject + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; + } + return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } + + validateValue(eventListener: Variable, property: Variable): string { + return ''; + } + public validatePresence(eventListener: Variable, property: Variable): string { + return ''; + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/enum.ts b/powershell/llcsharp/schema/enum.ts index 258b96b42b7..fdd7f4d1088 100644 --- a/powershell/llcsharp/schema/enum.ts +++ b/powershell/llcsharp/schema/enum.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Schema } from '../code-model'; -import { String } from './string'; +import { StringSchema } from '@azure-tools/codemodel'; +import { String, NewString } from './string'; import { dotnet, toExpression } from '@azure-tools/codegen-csharp'; export class EnumImplementation extends String { @@ -28,3 +29,26 @@ export class EnumImplementation extends String { get declaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}${this.isRequired ? '' : '?'}`; } } + +export class NewEnumImplementation extends NewString { + public isXmlAttribute = false; + get isNullable(): boolean { + return !this.isRequired; + } + + constructor(schema: StringSchema, isRequired: boolean) { + + super(schema, isRequired); + } + + get defaultOfType() { + return this.isRequired ? toExpression(`((${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.name}${this.isRequired ? '' : '?'})"")`) : dotnet.Null; + } + + get convertObjectMethod() { + return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.name}.CreateFrom`; + } + + + get declaration(): string { return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.name}${this.isRequired ? '' : '?'}`; } +} diff --git a/powershell/llcsharp/schema/extended-type-declaration.ts b/powershell/llcsharp/schema/extended-type-declaration.ts index f518fd8818e..0a0c59d327f 100644 --- a/powershell/llcsharp/schema/extended-type-declaration.ts +++ b/powershell/llcsharp/schema/extended-type-declaration.ts @@ -49,7 +49,7 @@ export interface EnhancedTypeDeclaration extends TypeDeclaration { isXmlAttribute: boolean; /** the underlying schema for this type declarartion. */ - schema: Schema | NewSchema; + schema: Schema; isNullable: boolean; @@ -59,3 +59,51 @@ export interface EnhancedTypeDeclaration extends TypeDeclaration { /** emits the code required to validate that this has a permissable value */ validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements; } + +export interface NewEnhancedTypeDeclaration extends TypeDeclaration { + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression; + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression; + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; + + /** emits an expression serialize this to the value required by the container */ + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression; + + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression; + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements; + + /** defaultOfType */ + readonly defaultOfType: Expression; + + readonly convertObjectMethod: string; // "global::System.Convert.ToString"; + + /** is a value for this required */ + isRequired: boolean; + + /** when encoding as xml, is this encoded as an attribute */ + isXmlAttribute: boolean; + + /** the underlying schema for this type declarartion. */ + schema: NewSchema; + + isNullable: boolean; + + /** emits the code required to validate that this is set to a value */ + validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements; + + /** emits the code required to validate that this has a permissable value */ + validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements; +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/integer.ts b/powershell/llcsharp/schema/integer.ts index d293093ab3a..d6673cb5de5 100644 --- a/powershell/llcsharp/schema/integer.ts +++ b/powershell/llcsharp/schema/integer.ts @@ -7,7 +7,8 @@ import { nameof } from '@azure-tools/codegen'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Primitive } from './primitive'; +import { NumberSchema } from '@azure-tools/codemodel'; +import { Primitive, NewPrimitive } from './primitive'; export class Numeric extends Primitive { public isXmlAttribute = false; @@ -45,3 +46,39 @@ ${this.validateMultipleOf(eventListener, property)} } } +export class NewNumeric extends NewPrimitive { + public isXmlAttribute = false; + public jsonType = ClientRuntime.JsonNumber; + + constructor(schema: NumberSchema, public isRequired: boolean, protected numericType: string) { + super(schema); + } + get declaration(): string { + return `${this.numericType}`; + } + validateValue(eventListener: Variable, property: Variable): string { + return ` +${this.validateMinimum(eventListener, property)} +${this.validateMaximum(eventListener, property)} +${this.validateExclusiveMinimum(eventListener, property)} +${this.validateExclusiveMaximum(eventListener, property)} +${this.validateMultipleOf(eventListener, property)} +`.trim(); + } + protected validateMinimum(eventListener: Variable, property: Variable): string { + return (this.schema).minimum && !(this.schema).exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThanOrEqual(${nameof(property.value)},${property},${(this.schema).minimum});` : ''; + } + protected validateMaximum(eventListener: Variable, property: Variable): string { + return (this.schema).maximum && !(this.schema).exclusiveMaximum ? `await ${eventListener}.AssertIsLessThanOrEqual(${nameof(property.value)},${property},${(this.schema).maximum});` : ''; + } + protected validateExclusiveMinimum(eventListener: Variable, property: Variable): string { + return (this.schema).minimum && (this.schema).exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThan(${nameof(property.value)},${property},${(this.schema).minimum});` : ''; + } + protected validateExclusiveMaximum(eventListener: Variable, property: Variable): string { + return (this.schema).maximum && (this.schema).exclusiveMaximum ? `await ${eventListener}.AssertIsLessThan(${nameof(property.value)},${property},${(this.schema).maximum});` : ''; + } + protected validateMultipleOf(eventListener: Variable, property: Variable): string { + return (this.schema).multipleOf ? `await ${eventListener}.AssertIsMultipleOf(${nameof(property.value)},${property},${(this.schema).multipleOf});` : ''; + } + +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/object.ts b/powershell/llcsharp/schema/object.ts index d651fa13d62..bb9dce1cad5 100644 --- a/powershell/llcsharp/schema/object.ts +++ b/powershell/llcsharp/schema/object.ts @@ -14,9 +14,9 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, ObjectSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; export class ObjectImplementation implements EnhancedTypeDeclaration { public isXmlAttribute = false; @@ -181,7 +181,7 @@ export class ObjectImplementation implements EnhancedTypeDeclaration { } -export class NewObjectImplementation implements EnhancedTypeDeclaration { +export class NewObjectImplementation implements NewEnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { @@ -330,7 +330,7 @@ export class NewObjectImplementation implements EnhancedTypeDeclaration { isRequired = false; - constructor(public schema: NewSchema) { + constructor(public schema: ObjectSchema) { } public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { diff --git a/powershell/llcsharp/schema/primitive.ts b/powershell/llcsharp/schema/primitive.ts index 393f0f6a72b..50c34b01c93 100644 --- a/powershell/llcsharp/schema/primitive.ts +++ b/powershell/llcsharp/schema/primitive.ts @@ -14,7 +14,8 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { Schema as NewSchema, PrimitiveSchema } from '@azure-tools/codemodel'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; let tmpVar: number | undefined; let max = 0; @@ -186,7 +187,7 @@ export abstract class Primitive implements EnhancedTypeDeclaration { return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); } - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); + // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); case KnownMediaType.Cookie: case KnownMediaType.Header: @@ -230,3 +231,186 @@ export abstract class Primitive implements EnhancedTypeDeclaration { return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); } } + +export abstract class NewPrimitive implements NewEnhancedTypeDeclaration { + abstract isRequired: boolean; + abstract isXmlAttribute: boolean; + abstract declaration: string; + abstract jsonType: ClassType; + get isNullable(): boolean { + return !this.isRequired; + } + + get encode(): string { + return (this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding']) ? '' : 'global::System.Uri.EscapeDataString'; + } + + get defaultOfType() { + return toExpression(`default(${this.declaration})`); + } + + get convertObjectMethod() { + const v = pushTempVar(); + const result = `(${v})=> (${this.baseType}) global::System.Convert.ChangeType(${v}, typeof(${this.baseType}))`; + popTempVar(); + + return result; + } + + constructor(public schema: PrimitiveSchema) { + } + /** validatePresence on primitives is generally not required; the nullability determines requiredness... */ + public validatePresence(eventListener: Variable, property: Variable): string { + return ''; + } + + abstract validateValue(eventListener: Variable, property: Variable): string; + protected get baseType(): string { + return this.declaration.replace('?', ''); + } + + protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `(${this.declaration})${tmpValue}`; + } + + protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { + return `(${this.declaration})${tmpValue}`; + } + + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: { + // JsonObject + const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; + return toExpression(`If( ${valueOf(container)}?.PropertyT<${this.jsonType}>("${serializedName}"), out var ${tmp}) ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); + } + + case KnownMediaType.Xml: { + // XElement/XElement or XElement/XAttribute + const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; + + return toExpression(this.isXmlAttribute ? + `If( ${valueOf(container)}?.Attribute("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : + `If( ${valueOf(container)}?.Element("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); + } + + case KnownMediaType.Header: { + // HttpResponseHeaders + const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; + return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${this.baseType}.TryParse( ${tmp}, out ${this.baseType} ${tmp}Value ) ? ${tmp}Value : ${defaultValue} : ${defaultValue}`); + } + } + return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); + } + + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + try { + const tmp = pushTempVar(); + switch (mediaType) { + case KnownMediaType.Json: + // node should be a json type + return toExpression(`${node} is ${this.jsonType} ${tmp} ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); + + case KnownMediaType.Xml: + // XElement or XAttribute + return toExpression( + this.isXmlAttribute ? + `${node} is ${System.Xml.Linq.XAttribute} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : + `${node} is ${System.Xml.Linq.XElement} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)}: ${defaultValue}`); + } + } finally { + popTempVar(); + } + return toExpression(`null /* deserializeFromContainer doens't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + try { + const tmp = pushTempVar(); + + switch (mediaType) { + case KnownMediaType.UriParameter: { + return toExpression(`${this.baseType}.TryParse( ${valueOf(content)}, out ${this.baseType} ${tmp} ) ? ${tmp} : ${defaultValue}`); + + } + } + } finally { + popTempVar(); + } + return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); + } + + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); + } + + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + switch (mediaType) { + case KnownMediaType.Json: + return this.isRequired ? + this.jsonType.new(value).Cast(ClientRuntime.JsonNode) : + Ternery(IsNotNull(value), this.jsonType.new(`(${this.baseType})${value}`).Cast(ClientRuntime.JsonNode), dotnet.Null); + + case KnownMediaType.Xml: + return this.isRequired ? + toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : + toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); + + case KnownMediaType.QueryParameter: + if (this.isRequired) { + return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); + } else { + return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); + } + + // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); + + case KnownMediaType.Cookie: + case KnownMediaType.Header: + case KnownMediaType.Text: + case KnownMediaType.UriParameter: + return toExpression(this.isRequired ? + `(${value}.ToString())` : + `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` + ); + } + return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); + } + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + switch (mediaType) { + case KnownMediaType.Json: + // container : JsonObject + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; + + case KnownMediaType.Xml: + // container : XElement + return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; + + case KnownMediaType.Header: + // container : HttpRequestHeaders + return this.isRequired ? + `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : + If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}.ToString());`); + + case KnownMediaType.QueryParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `${serializedName}={${value}.ToString()}` : + `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; + + case KnownMediaType.UriParameter: + // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter + return this.isRequired ? + `${serializedName}={${value}.ToString()}` : + `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}"}`; + } + return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 209c0fc847f..a7ab9d51377 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,25 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; -import { ArrayOf } from './array'; -import { Binary } from './binary'; -import { Boolean } from './boolean'; -import { ByteArray } from './byte-array'; -import { Char } from './char'; -import { Date } from './date'; -import { DateTime, DateTime1123, UnixTime } from './date-time'; -import { Duration } from './duration'; -import { EnumImplementation } from './enum'; -import { Numeric } from './integer'; +import { ArrayOf, NewArrayOf } from './array'; +import { Binary, NewBinary } from './binary'; +import { Boolean, NewBoolean } from './boolean'; +import { ByteArray, NewByteArray } from './byte-array'; +import { Char, NewChar } from './char'; +import { Date, NewDate } from './date'; +import { DateTime, DateTime1123, UnixTime, NewDateTime, NewDateTime1123, NewUnixTime } from './date-time'; +import { Duration, NewDuration } from './duration'; +import { EnumImplementation, NewEnumImplementation } from './enum'; +import { Numeric, NewNumeric } from './integer'; import { ObjectImplementation, NewObjectImplementation } from './object'; import { String, NewString } from './string'; -import { Uuid } from './Uuid'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { Uuid, NewUuid } from './Uuid'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { PwshModel } from '../../utils/PwshModel'; import { NewModelState } from '../../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; @@ -153,76 +153,74 @@ export class SchemaDefinitionResolver { } export class NewSchemaDefinitionResolver { - private readonly cache = new Map(); - private add(schema: NewSchema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { + private readonly cache = new Map(); + private add(schema: NewSchema, value: NewEnhancedTypeDeclaration): NewEnhancedTypeDeclaration { this.cache.set(schema.language?.csharp?.fullname || '', value); return value; } - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): EnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } // determine if we need a new model class for the type or just a known type object switch (schema.type) { - // case SchemaType.Array: { - // // can be recursive! - // // handle boolean arrays as booleans (powershell will try to turn it into switches!) - // const ar = schema; - // const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(schema.items, true, state.path('items')); - // return new ArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); - // } + case SchemaType.Array: { + // can be recursive! + // handle boolean arrays as booleans (powershell will try to turn it into switches!) + const ar = schema; + const elementType = (ar.elementType.type === SchemaType.Boolean) ? new NewBoolean(schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items')); + return new NewArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); + } case SchemaType.Object: { const result = schema.language.csharp && this.cache.get(schema.language.csharp.fullname || ''); if (result) { return result; } - return this.add(schema, new NewObjectImplementation(schema)); + return this.add(schema, new NewObjectImplementation(schema)); } case SchemaType.String: { return new NewString(schema, required); } - // case JsonType.Boolean: - // return new Boolean(schema, required); - - // case JsonType.Integer: - // switch (schema.format) { - // case IntegerFormat.Int64: - // case IntegerFormat.None: - // return new Numeric(schema, required, required ? 'long' : 'long?'); - // case IntegerFormat.UnixTime: - // return new UnixTime(schema, required); - // case IntegerFormat.Int32: - // return new Numeric(schema, required, required ? 'int' : 'int?'); - // } - // // fallback to int if the format isn't recognized - // return new Numeric(schema, required, required ? 'int' : 'int?'); - - // case JsonType.Number: - // switch (schema.format) { - // case NumberFormat.None: - // case NumberFormat.Double: - // return new Numeric(schema, required, required ? 'double' : 'double?'); - // case NumberFormat.Float: - // return new Numeric(schema, required, required ? 'float' : 'float?'); - // case NumberFormat.Decimal: - // return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); - // } - // // fallback to float if the format isn't recognized - // return new Numeric(schema, required, required ? 'float' : 'float?'); - - // case undefined: - // if (schema.extensions && schema.extensions['x-ms-enum']) { - // return new EnumImplementation(schema, required); - // } - - // "any" case - // this can happen when a model is just an all-of something else. (sub in the other type?) + case SchemaType.Boolean: + return new NewBoolean(schema, required); + + case SchemaType.Integer: + switch ((schema).precision) { + case 64: + return new NewNumeric(schema, required, required ? 'long' : 'long?'); + // skip-for-time-being + // case IntegerFormat.UnixTime: + // return new UnixTime(schema, required); + case 32: + return new NewNumeric(schema, required, required ? 'int' : 'int?'); + } + // fallback to int if the format isn't recognized + return new NewNumeric(schema, required, required ? 'int' : 'int?'); + + case SchemaType.Number: + switch ((schema).precision) { + case 64: + return new NewNumeric(schema, required, required ? 'double' : 'double?'); + case 32: + new NewNumeric(schema, required, required ? 'float' : 'float?'); + case 128: + return new NewNumeric(schema, required, required ? 'decimal' : 'decimal?'); + } + // fallback to float if the format isn't recognized + return new NewNumeric(schema, required, required ? 'float' : 'float?'); + case undefined: + if (schema.extensions && schema.extensions['x-ms-enum']) { + return new NewEnumImplementation(schema, required); + } + + // "any" case + // this can happen when a model is just an all-of something else. (sub in the other type?) break; } diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index b88355984d4..110a9d4ee46 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -14,7 +14,7 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; /** A ETD for the c# string type. */ @@ -210,7 +210,7 @@ ${this.validateEnum(eventListener, property)} } /** A ETD for the c# string type. */ -export class NewString implements EnhancedTypeDeclaration { +export class NewString implements NewEnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 751d99a4943..477c19d8e36 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -414,7 +414,7 @@ export class NewModelExtensionsNamespace extends Namespace { const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); yield t.declarationStatement; - if (schema.language.default.uid === 'universal-parameter-type' || schema.language.csharp?.byReference) { + if (schema.language.default.uid || schema.language.csharp?.byReference) { yield '// we allow string conversion too.'; yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); } diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index ca19bbb5c93..9750101ed49 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -78,6 +78,7 @@ async function tweakModelV2(state: State): Promise { const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); universalId.apiVersions = universalId.apiVersions || []; state.model.schemas.objects = state.model.schemas.objects || []; + (universalId.language.default).uid = true; state.model.schemas.objects.push(universalId); model.commands = { From 2b2bcd128433e6ef885e69c55644c5009a78266c Mon Sep 17 00:00:00 2001 From: LucasYao93 <53558334+LucasYao93@users.noreply.github.com> Date: Wed, 15 Jul 2020 17:10:41 +0800 Subject: [PATCH 05/61] Add test cases for upgrade. --- tests-upgrade/.gitignore | 1 + tests-upgrade/README.md | 2 + .../basic-get-delete-put-patch/readme.md | 10 + .../basic-get-delete-put-patch/swagger.json | 89 ++ tests-upgrade/basic-get-delete/readme.md | 10 + tests-upgrade/basic-get-delete/swagger.json | 65 + .../basic-get-response-operation/readme.md | 10 + .../basic-get-response-operation/swagger.json | 56 + tests-upgrade/basic-get/readme.md | 10 + tests-upgrade/basic-get/swagger.json | 53 + .../basic-response-multioperation/readme.md | 10 + .../swagger.json | 104 ++ tests-upgrade/basic-spec-required/readme.md | 10 + .../basic-spec-required/swagger.json | 22 + tests-upgrade/basic-spec-root/readme.md | 10 + tests-upgrade/basic-spec-root/swagger.json | 39 + .../component-definitions-combined/readme.md | 10 + .../swagger.json | 96 ++ .../component-definitions-local/readme.md | 10 + .../component-definitions-local/swagger.json | 126 ++ tests-upgrade/component-multiparam/readme.md | 10 + .../component-multiparam/swagger.json | 213 +++ .../component-param-inbody/readme.md | 10 + .../component-param-inbody/swagger.json | 78 + .../component-param-localremote/readme.md | 10 + .../component-param-localremote/swagger.json | 210 +++ .../component-param-remote/readme.md | 10 + .../component-param-remote/swagger.json | 201 +++ tests-upgrade/component-param/readme.md | 10 + tests-upgrade/component-param/swagger.json | 151 ++ .../datamodels-datatypes-array/readme.md | 10 + .../datamodels-datatypes-array/swagger.json | 102 ++ .../datamodels-datatypes-integer/readme.md | 10 + .../datamodels-datatypes-integer/swagger.json | 81 ++ .../datamodels-datatypes-mixedtypes/readme.md | 10 + .../swagger.json | 83 ++ .../datamodels-datatypes-nullable/readme.md | 10 + .../swagger.json | 87 ++ .../datamodels-datatypes-string/readme.md | 10 + .../datamodels-datatypes-string/swagger.json | 86 ++ tests-upgrade/readme.azure.noprofile.md | 47 + tests-upgrade/sample-swagger.json | 1266 +++++++++++++++++ 42 files changed, 3448 insertions(+) create mode 100644 tests-upgrade/.gitignore create mode 100644 tests-upgrade/README.md create mode 100644 tests-upgrade/basic-get-delete-put-patch/readme.md create mode 100644 tests-upgrade/basic-get-delete-put-patch/swagger.json create mode 100644 tests-upgrade/basic-get-delete/readme.md create mode 100644 tests-upgrade/basic-get-delete/swagger.json create mode 100644 tests-upgrade/basic-get-response-operation/readme.md create mode 100644 tests-upgrade/basic-get-response-operation/swagger.json create mode 100644 tests-upgrade/basic-get/readme.md create mode 100644 tests-upgrade/basic-get/swagger.json create mode 100644 tests-upgrade/basic-response-multioperation/readme.md create mode 100644 tests-upgrade/basic-response-multioperation/swagger.json create mode 100644 tests-upgrade/basic-spec-required/readme.md create mode 100644 tests-upgrade/basic-spec-required/swagger.json create mode 100644 tests-upgrade/basic-spec-root/readme.md create mode 100644 tests-upgrade/basic-spec-root/swagger.json create mode 100644 tests-upgrade/component-definitions-combined/readme.md create mode 100644 tests-upgrade/component-definitions-combined/swagger.json create mode 100644 tests-upgrade/component-definitions-local/readme.md create mode 100644 tests-upgrade/component-definitions-local/swagger.json create mode 100644 tests-upgrade/component-multiparam/readme.md create mode 100644 tests-upgrade/component-multiparam/swagger.json create mode 100644 tests-upgrade/component-param-inbody/readme.md create mode 100644 tests-upgrade/component-param-inbody/swagger.json create mode 100644 tests-upgrade/component-param-localremote/readme.md create mode 100644 tests-upgrade/component-param-localremote/swagger.json create mode 100644 tests-upgrade/component-param-remote/readme.md create mode 100644 tests-upgrade/component-param-remote/swagger.json create mode 100644 tests-upgrade/component-param/readme.md create mode 100644 tests-upgrade/component-param/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-array/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-array/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-integer/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-integer/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-mixedtypes/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-mixedtypes/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-nullable/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-nullable/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-string/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-string/swagger.json create mode 100644 tests-upgrade/readme.azure.noprofile.md create mode 100644 tests-upgrade/sample-swagger.json diff --git a/tests-upgrade/.gitignore b/tests-upgrade/.gitignore new file mode 100644 index 00000000000..dc9b2375c7a --- /dev/null +++ b/tests-upgrade/.gitignore @@ -0,0 +1 @@ +generated \ No newline at end of file diff --git a/tests-upgrade/README.md b/tests-upgrade/README.md new file mode 100644 index 00000000000..d77d3941d22 --- /dev/null +++ b/tests-upgrade/README.md @@ -0,0 +1,2 @@ +### Description +Add test case for autorest powershell upgrade. \ No newline at end of file diff --git a/tests-upgrade/basic-get-delete-put-patch/readme.md b/tests-upgrade/basic-get-delete-put-patch/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-get-delete-put-patch/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-get-delete-put-patch/swagger.json b/tests-upgrade/basic-get-delete-put-patch/swagger.json new file mode 100644 index 00000000000..1e492fbdb81 --- /dev/null +++ b/tests-upgrade/basic-get-delete-put-patch/swagger.json @@ -0,0 +1,89 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Deletes the workspace", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "responses": { + "202": { + "description": "Accepted" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-get-delete/readme.md b/tests-upgrade/basic-get-delete/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-get-delete/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-get-delete/swagger.json b/tests-upgrade/basic-get-delete/swagger.json new file mode 100644 index 00000000000..99515cde797 --- /dev/null +++ b/tests-upgrade/basic-get-delete/swagger.json @@ -0,0 +1,65 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags":[ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Delete the workspace.", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-get-response-operation/readme.md b/tests-upgrade/basic-get-response-operation/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-get-response-operation/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-get-response-operation/swagger.json b/tests-upgrade/basic-get-response-operation/swagger.json new file mode 100644 index 00000000000..58b0c253858 --- /dev/null +++ b/tests-upgrade/basic-get-response-operation/swagger.json @@ -0,0 +1,56 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-get/readme.md b/tests-upgrade/basic-get/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-get/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-get/swagger.json b/tests-upgrade/basic-get/swagger.json new file mode 100644 index 00000000000..5480c062852 --- /dev/null +++ b/tests-upgrade/basic-get/swagger.json @@ -0,0 +1,53 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-response-multioperation/readme.md b/tests-upgrade/basic-response-multioperation/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-response-multioperation/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-response-multioperation/swagger.json b/tests-upgrade/basic-response-multioperation/swagger.json new file mode 100644 index 00000000000..115b3af19eb --- /dev/null +++ b/tests-upgrade/basic-response-multioperation/swagger.json @@ -0,0 +1,104 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Deletes the workspace", + "responses": { + "200": { + "description": "OK - Deleted the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "responses": { + "200": { + "description": "OK - Updated the workspace." + }, + "202": { + "description": "Accepted" + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-spec-required/readme.md b/tests-upgrade/basic-spec-required/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-spec-required/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-spec-required/swagger.json b/tests-upgrade/basic-spec-required/swagger.json new file mode 100644 index 00000000000..eb4665e888a --- /dev/null +++ b/tests-upgrade/basic-spec-required/swagger.json @@ -0,0 +1,22 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-spec-root/readme.md b/tests-upgrade/basic-spec-root/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-spec-root/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-spec-root/swagger.json b/tests-upgrade/basic-spec-root/swagger.json new file mode 100644 index 00000000000..fccc4fc3f57 --- /dev/null +++ b/tests-upgrade/basic-spec-root/swagger.json @@ -0,0 +1,39 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + } +} \ No newline at end of file diff --git a/tests-upgrade/component-definitions-combined/readme.md b/tests-upgrade/component-definitions-combined/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-definitions-combined/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-definitions-combined/swagger.json b/tests-upgrade/component-definitions-combined/swagger.json new file mode 100644 index 00000000000..1330299ffdf --- /dev/null +++ b/tests-upgrade/component-definitions-combined/swagger.json @@ -0,0 +1,96 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ExtendedErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required":[ + "message", + "code" + ], + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer", + "minimum": 100, + "maximum": 600 + } + } + }, + "ExtendedErrorModel": { + "allOf": [ + { + "$ref": "#/definitions/BasicErrorModel" + }, + { + "type": "object", + "required": [ + "rootCause" + ], + "properties": { + "rootCause": { + "type": "string" + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-definitions-local/readme.md b/tests-upgrade/component-definitions-local/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-definitions-local/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-definitions-local/swagger.json b/tests-upgrade/component-definitions-local/swagger.json new file mode 100644 index 00000000000..3f8d3819459 --- /dev/null +++ b/tests-upgrade/component-definitions-local/swagger.json @@ -0,0 +1,126 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/xxxx-xxxx-xxxx/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListBySubscription", + "description": "Gets all the workspaces within a subscription.", + "responses": { + "200": { + "description": "OK - Returns an array of workspaces." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + } + }, + "definitions": { + "ErrorDetail": { + "title": "Error details.", + "type": "object", + "properties": { + "code": { + "description": "The error's code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "target": { + "description": "Indicates which property in the request is responsible for the error.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorInfo": { + "title": "The code and message for an error.", + "type": "object", + "properties": { + "code": { + "description": "A machine readable error code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "details": { + "description": "error details.", + "type": "array", + "items": { + "$ref": "#/definitions/ErrorDetail" + } + }, + "innererror": { + "description": "Inner error details if they exist.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorResponse": { + "title": "Error response.", + "description": "Contains details when the response code indicates an error.", + "type": "object", + "properties": { + "error": { + "description": "The error details.", + "$ref": "#/definitions/ErrorInfo" + } + }, + "required": [ + "error" + ] + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-multiparam/readme.md b/tests-upgrade/component-multiparam/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-multiparam/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-multiparam/swagger.json b/tests-upgrade/component-multiparam/swagger.json new file mode 100644 index 00000000000..ce72f5a4f15 --- /dev/null +++ b/tests-upgrade/component-multiparam/swagger.json @@ -0,0 +1,213 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK - Deleted the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK - Updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation." + }, + "ResourceGroupName": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + }, + "PeeringNameParameter": { + "name": "peeringName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace vNet peering.", + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-param-inbody/readme.md b/tests-upgrade/component-param-inbody/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-inbody/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-inbody/swagger.json b/tests-upgrade/component-param-inbody/swagger.json new file mode 100644 index 00000000000..5f514f3db2e --- /dev/null +++ b/tests-upgrade/component-param-inbody/swagger.json @@ -0,0 +1,78 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/workspaces": { + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "parameters": [ + { + "name": "workspace", + "in": "body", + "required": true, + "description": "The workspace to create or update.", + "schema": { + "required": [ + "properties" + ], + "properties": { + "name": { + "type": "string", + "description": "Workspace name" + }, + "location": { + "type": "string", + "description": "Workspace region" + } + } + } + } + ], + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } + } \ No newline at end of file diff --git a/tests-upgrade/component-param-localremote/readme.md b/tests-upgrade/component-param-localremote/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-localremote/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-localremote/swagger.json b/tests-upgrade/component-param-localremote/swagger.json new file mode 100644 index 00000000000..2ee6b92080d --- /dev/null +++ b/tests-upgrade/component-param-localremote/swagger.json @@ -0,0 +1,210 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Deleted the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "parameters": { + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation." + }, + "ResourceGroupName": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + }, + "PeeringNameParameter": { + "name": "peeringName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace vNet peering.", + "x-ms-parameter-location": "method" + } + } + } \ No newline at end of file diff --git a/tests-upgrade/component-param-remote/readme.md b/tests-upgrade/component-param-remote/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-remote/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-remote/swagger.json b/tests-upgrade/component-param-remote/swagger.json new file mode 100644 index 00000000000..eed1f4fca06 --- /dev/null +++ b/tests-upgrade/component-param-remote/swagger.json @@ -0,0 +1,201 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Deleted the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation." + }, + "ResourceGroupName": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + }, + "PeeringNameParameter": { + "name": "peeringName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace vNet peering.", + "x-ms-parameter-location": "method" + } + } + } \ No newline at end of file diff --git a/tests-upgrade/component-param/readme.md b/tests-upgrade/component-param/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param/swagger.json b/tests-upgrade/component-param/swagger.json new file mode 100644 index 00000000000..731b8c5688d --- /dev/null +++ b/tests-upgrade/component-param/swagger.json @@ -0,0 +1,151 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroup/{resourceGroup}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Gets the workspace.", + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Deleted the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + } + ], + "responses": { + "200": { + "description": "OK - Created or updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + }, + { + "$ref": "#/parameters/ResourceGroupName" + } + ], + "responses": { + "200": { + "description": "OK - Updated the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "parameters": { + "ResourceGroupName":{ + "name": "resourceGroup", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90 + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-array/readme.md b/tests-upgrade/datamodels-datatypes-array/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-array/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-array/swagger.json b/tests-upgrade/datamodels-datatypes-array/swagger.json new file mode 100644 index 00000000000..6e69cbf3baa --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-array/swagger.json @@ -0,0 +1,102 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace.", + "schema":{ + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "ErrorDetail": { + "type": "array", + "items":{ + "type": "integer" + }, + "uniqueItems": true + }, + "ErrorList": { + "type": "array", + "items": { + "$ref": "#/definitions/ErrorDetail" + }, + "minItems": 1, + "maxItems": 10 + }, + "ErrorCode": { + "type": "array", + "items": { + "type":"array", + "items": { + "type": "integer" + } + } + }, + "Workspace":{ + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "sku": { + "type": "string" + }, + "location": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-integer/readme.md b/tests-upgrade/datamodels-datatypes-integer/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-integer/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-integer/swagger.json b/tests-upgrade/datamodels-datatypes-integer/swagger.json new file mode 100644 index 00000000000..a08d8d9e3c8 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-integer/swagger.json @@ -0,0 +1,81 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/BasicErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required":[ + "message", + "code" + ], + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer", + "minimum": 99, + "maximum": 600, + "exclusiveMinimum": true, + "exclusiveMaximum": true, + "multipleOf": 10 + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-mixedtypes/readme.md b/tests-upgrade/datamodels-datatypes-mixedtypes/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-mixedtypes/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-mixedtypes/swagger.json b/tests-upgrade/datamodels-datatypes-mixedtypes/swagger.json new file mode 100644 index 00000000000..a9dca898e4e --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-mixedtypes/swagger.json @@ -0,0 +1,83 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/BasicErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required":[ + "message", + "code" + ], + "properties": { + "message": { + "type": "string" + }, + "code": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-nullable/readme.md b/tests-upgrade/datamodels-datatypes-nullable/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-nullable/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-nullable/swagger.json b/tests-upgrade/datamodels-datatypes-nullable/swagger.json new file mode 100644 index 00000000000..e3832914d01 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-nullable/swagger.json @@ -0,0 +1,87 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/BasicErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required":[ + "message", + "code" + ], + "properties": { + "datetime": { + "type": "string", + "format": "date-time" + }, + "host": { + "type": "string", + "pattern":"^\\d{3}-\\d{2}-\\d{4}$", + "nullable": true + }, + "message": { + "type": "string", + "minLength": 3, + "maxLength": 300 + }, + "code": { + "type": "integer" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-string/readme.md b/tests-upgrade/datamodels-datatypes-string/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-string/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-string/swagger.json b/tests-upgrade/datamodels-datatypes-string/swagger.json new file mode 100644 index 00000000000..f1f9d58cb9d --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-string/swagger.json @@ -0,0 +1,86 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/BasicErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required":[ + "message", + "code" + ], + "properties": { + "datetime": { + "type": "string", + "format": "date-time" + }, + "host": { + "type": "string", + "pattern":"^\\d{3}-\\d{2}-\\d{4}$" + }, + "message": { + "type": "string", + "minLength": 3, + "maxLength": 300 + }, + "code": { + "type": "integer" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/readme.azure.noprofile.md b/tests-upgrade/readme.azure.noprofile.md new file mode 100644 index 00000000000..82284693a17 --- /dev/null +++ b/tests-upgrade/readme.azure.noprofile.md @@ -0,0 +1,47 @@ +# Azure PowerShell AutoRest Configuration + +> Values +``` yaml +azure: true +powershell: true +license-header: MICROSOFT_MIT_NO_VERSION +branch: master +repo: https://github.com/Azure/azure-rest-api-specs/blob/$(branch) +metadata: + authors: Microsoft Corporation + owners: Microsoft Corporation + description: 'Microsoft Azure PowerShell: $(service-name) cmdlets' + copyright: Microsoft Corporation. All rights reserved. + tags: Azure ResourceManager ARM PSModule $(service-name) + companyName: Microsoft Corporation + requireLicenseAcceptance: true + licenseUri: https://aka.ms/azps-license + projectUri: https://github.com/Azure/azure-powershell +``` + +> Names +``` yaml +prefix: Az +subject-prefix: $(service-name) +module-name: $(prefix).$(service-name) +namespace: Microsoft.Azure.PowerShell.Cmdlets.$(service-name) +``` + +> Folders +``` yaml +clear-output-folder: true +output-folder: . +``` + +> Directives +``` yaml +directive: + - where: + subject: Operation + hide: true + - where: + parameter-name: SubscriptionId + set: + default: + script: '(Get-AzContext).Subscription.Id' +``` \ No newline at end of file diff --git a/tests-upgrade/sample-swagger.json b/tests-upgrade/sample-swagger.json new file mode 100644 index 00000000000..8db4896d3dd --- /dev/null +++ b/tests-upgrade/sample-swagger.json @@ -0,0 +1,1266 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "x-ms-examples": { + "Get a workspace": { + "$ref": "./examples/WorkspaceGet.json" + }, + "Get a workspace with custom parameters": { + "$ref": "./examples/WorkspaceGetParameters.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Deletes the workspace.", + "x-ms-examples": { + "Delete a workspace": { + "$ref": "./examples/WorkspaceDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "204": { + "description": "NoContent" + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "200": { + "description": "OK. The request has succeeded." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "x-ms-examples": { + "Create or update workspace": { + "$ref": "./examples/WorkspaceCreate.json" + }, + "Create or update workspace with custom parameters": { + "$ref": "./examples/WorkspaceCreateWithParameters.json" + }, + "Create a workspace which is ready for Customer-Managed Key (CMK) encryption": { + "$ref": "./examples/PrepareEncryption.json" + }, + "Enable Customer-Managed Key (CMK) encryption on a workspace which is prepared for encryption": { + "$ref": "./examples/EnableEncryption.json" + }, + "Revert Customer-Managed Key (CMK) encryption to Microsoft Managed Keys encryption on a workspace": { + "$ref": "./examples/DisableEncryption.json" + } + }, + "parameters": [ + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Workspace" + }, + "description": "Parameters supplied to the create or update a workspace." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Created - Returns information about the workspace, including provisioning status.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "201": { + "description": "Created - Returns information about the workspace, including provisioning status.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkspaceUpdate" + }, + "description": "The update to the workspace." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Successfully updated the workspace.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true, + "x-ms-examples": { + "Update a workspace's tags.": { + "$ref": "./examples/WorkspaceUpdate.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListByResourceGroup", + "description": "Gets all the workspaces within a resource group.", + "x-ms-examples": { + "Lists workspaces": { + "$ref": "./examples/WorkspacesListByResourceGroup.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns an array of workspaces.", + "schema": { + "$ref": "#/definitions/WorkspaceListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListBySubscription", + "description": "Gets all the workspaces within a subscription.", + "x-ms-examples": { + "Lists workspaces": { + "$ref": "./examples/WorkspacesListBySubscription.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns an array of workspaces.", + "schema": { + "$ref": "#/definitions/WorkspaceListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}/virtualNetworkPeerings/{peeringName}": { + "get": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_Get", + "description": "Gets the workspace vNet Peering.", + "x-ms-examples": { + "Get a workspace with vNet Peering Configured": { + "$ref": "./examples/WorkspaceVirtualNetPeeringGet.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "204": { + "description": "OK - NoContent" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_Delete", + "description": "Deletes the workspace vNetPeering.", + "x-ms-examples": { + "Delete a workspace vNet Peering": { + "$ref": "./examples/WorkspaceVirtualNetworkPeeringDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "204": { + "description": "NoContent" + }, + "200": { + "description": "OK. The request has succeeded." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "put": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_CreateOrUpdate", + "description": "Creates vNet Peering for workspace.", + "x-ms-examples": { + "Create vNet Peering for Workspace": { + "$ref": "./examples/WorkspaceVirtualNetworkPeeringCreateOrUpdate.json" + } + }, + "parameters": [ + { + "name": "VirtualNetworkPeeringParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + }, + "description": "Parameters supplied to the create workspace vNet Peering." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "201": { + "description": "Created - Returns information about the workspace vNet peering, including provisioning status.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "200": { + "description": "Update succeeded - Returns information about the workspace vNet peering.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}/virtualNetworkPeerings": { + "get": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_ListByWorkspace", + "description": "Lists the workspace vNet Peerings.", + "x-ms-examples": { + "List all vNet Peerings for the workspace": { + "$ref": "./examples/WorkspaceVirtualNetPeeringList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "List succeeded. Returns the resulting resource objects in response body.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeeringList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.Databricks/operations": { + "get": { + "tags": [ + "Operations" + ], + "description": "Lists all of the available RP operations.", + "x-ms-examples": { + "Operations": { + "$ref": "./examples/OperationsList.json" + } + }, + "operationId": "Operations_List", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/OperationListResult" + } + }, + "default": { + "description": "Resource Provider error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "Workspace": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WorkspaceProperties", + "description": "The workspace properties." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The SKU of the resource." + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "Information about workspace." + }, + "WorkspaceProperties": { + "properties": { + "managedResourceGroupId": { + "type": "string", + "description": "The managed resource group Id." + }, + "parameters": { + "$ref": "#/definitions/WorkspaceCustomParameters", + "description": "The workspace's custom parameters." + }, + "provisioningState": { + "readOnly": true, + "$ref": "#/definitions/ProvisioningState", + "description": "The workspace provisioning state." + }, + "uiDefinitionUri": { + "type": "string", + "description": "The blob URI where the UI definition file is located." + }, + "authorizations": { + "description": "The workspace provider authorizations.", + "type": "array", + "items": { + "$ref": "#/definitions/WorkspaceProviderAuthorization" + } + }, + "createdBy": { + "description": "Indicates the Object ID, PUID and Application ID of entity that created the workspace.", + "$ref": "#/definitions/CreatedBy" + }, + "updatedBy": { + "description": "Indicates the Object ID, PUID and Application ID of entity that last updated the workspace.", + "$ref": "#/definitions/CreatedBy" + }, + "createdDateTime": { + "description": "Specifies the date and time when the workspace is created.", + "$ref": "#/definitions/CreatedDateTime" + }, + "workspaceId": { + "readOnly": true, + "description": "The unique identifier of the databricks workspace in databricks control plane.", + "type": "string" + }, + "workspaceUrl": { + "readOnly": true, + "description": "The workspace URL which is of the format 'adb-{workspaceId}.{random}.azuredatabricks.net'", + "type": "string" + }, + "storageAccountIdentity": { + "description": "The details of Managed Identity of Storage Account", + "$ref": "#/definitions/ManagedIdentityConfiguration" + } + }, + "required": [ + "managedResourceGroupId" + ], + "description": "The workspace properties." + }, + "TrackedResource": { + "description": "The resource model definition for a ARM tracked top level resource", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "Resource": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "Sku": { + "properties": { + "name": { + "type": "string", + "description": "The SKU name." + }, + "tier": { + "type": "string", + "description": "The SKU tier." + } + }, + "required": [ + "name" + ], + "description": "SKU for the resource." + }, + "ProvisioningState": { + "description": "Provisioning status of the workspace.", + "readOnly": true, + "enum": [ + "Accepted", + "Running", + "Ready", + "Creating", + "Created", + "Deleting", + "Deleted", + "Canceled", + "Failed", + "Succeeded", + "Updating" + ], + "type": "string", + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true + } + }, + "PeeringProvisioningState": { + "type": "string", + "readOnly": true, + "description": "The current provisioning state.", + "enum": [ + "Succeeded", + "Updating", + "Deleting", + "Failed" + ], + "x-ms-enum": { + "name": "PeeringProvisioningState", + "modelAsString": true + } + }, + "ManagedIdentityConfiguration": { + "description": "The Managed Identity details for storage account.", + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The objectId of the Managed Identity that is linked to the Managed Storage account.", + "readOnly": true + }, + "tenantId": { + "type": "string", + "format": "uuid", + "description": "The tenant Id where the Managed Identity is created.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The type of Identity created. It can be either SystemAssigned or UserAssigned.", + "readOnly": true + } + } + }, + "WorkspaceCustomParameterType": { + "description": "Provisioning status of the workspace.", + "readOnly": true, + "enum": [ + "Bool", + "Object", + "String" + ], + "type": "string", + "x-ms-enum": { + "name": "CustomParameterType", + "modelAsString": true + } + }, + "WorkspaceCustomBooleanParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "boolean", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The value which should be used for this field." + }, + "WorkspaceCustomObjectParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "object", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The value which should be used for this field." + }, + "WorkspaceCustomStringParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "string", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The Value." + }, + "WorkspaceCustomParameters": { + "properties": { + "customVirtualNetworkId": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The ID of a Virtual Network where this Databricks Cluster should be created" + }, + "customPublicSubnetName": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The name of a Public Subnet within the Virtual Network" + }, + "customPrivateSubnetName": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The name of the Private Subnet within the Virtual Network" + }, + "enableNoPublicIp": { + "$ref": "#/definitions/WorkspaceCustomBooleanParameter", + "description": "Should the Public IP be Disabled?" + }, + "prepareEncryption": { + "$ref": "#/definitions/WorkspaceCustomBooleanParameter", + "description": "Prepare the workspace for encryption. Enables the Managed Identity for managed storage account." + }, + "encryption": { + "$ref": "#/definitions/WorkspaceEncryptionParameter", + "description": "Contains the encryption details for Customer-Managed Key (CMK) enabled workspace." + } + }, + "description": "Custom Parameters used for Cluster Creation." + }, + "CreatedDateTime": { + "type": "string", + "format": "date-time", + "description": "The date and time stamp when the workspace was created.", + "readOnly": true + }, + "CreatedBy": { + "properties": { + "oid": { + "type": "string", + "format": "uuid", + "description": "The Object ID that created the workspace.", + "readOnly": true + }, + "puid": { + "type": "string", + "description": "The Personal Object ID corresponding to the object ID above", + "readOnly": true + }, + "applicationId": { + "type": "string", + "format": "uuid", + "description": "The application ID of the application that initiated the creation of the workspace. For example, Azure Portal.", + "readOnly": true + } + }, + "description": "Provides details of the entity that created/updated the workspace." + }, + "WorkspaceEncryptionParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "$ref": "#/definitions/Encryption", + "description": "The value which should be used for this field." + } + }, + "description": "The object that contains details of encryption used on the workspace." + }, + "Encryption": { + "properties": { + "keySource": { + "type": "string", + "description": "The encryption keySource (provider). Possible values (case-insensitive): Default, Microsoft.Keyvault", + "enum": [ + "Default", + "Microsoft.Keyvault" + ], + "x-ms-enum": { + "name": "KeySource", + "modelAsString": true + }, + "default": "Default" + }, + "KeyName": { + "type": "string", + "description": "The name of KeyVault key." + }, + "keyversion": { + "type": "string", + "description": "The version of KeyVault key.", + "x-ms-client-name": "KeyVersion" + }, + "keyvaulturi": { + "type": "string", + "description": "The Uri of KeyVault.", + "x-ms-client-name": "KeyVaultUri" + } + }, + "description": "The object that contains details of encryption used on the workspace." + }, + "WorkspaceProviderAuthorization": { + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The provider's principal identifier. This is the identity that the provider will use to call ARM to manage the workspace resources." + }, + "roleDefinitionId": { + "type": "string", + "format": "uuid", + "description": "The provider's role definition identifier. This role will define all the permissions that the provider must have on the workspace's container resource group. This role definition cannot have permission to delete the resource group." + } + }, + "required": [ + "principalId", + "roleDefinitionId" + ], + "description": "The workspace provider authorization." + }, + "WorkspaceUpdate": { + "description": "An update to a workspace.", + "type": "object", + "properties": { + "tags": { + "description": "Resource tags.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "ErrorDetail": { + "title": "Error details.", + "type": "object", + "properties": { + "code": { + "description": "The error's code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "target": { + "description": "Indicates which property in the request is responsible for the error.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorInfo": { + "title": "The code and message for an error.", + "type": "object", + "properties": { + "code": { + "description": "A machine readable error code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "details": { + "description": "error details.", + "type": "array", + "items": { + "$ref": "#/definitions/ErrorDetail" + } + }, + "innererror": { + "description": "Inner error details if they exist.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorResponse": { + "title": "Error response.", + "description": "Contains details when the response code indicates an error.", + "type": "object", + "properties": { + "error": { + "description": "The error details.", + "$ref": "#/definitions/ErrorInfo" + } + }, + "required": [ + "error" + ] + }, + "WorkspaceListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Workspace" + }, + "description": "The array of workspaces." + }, + "nextLink": { + "type": "string", + "description": "The URL to use for getting the next set of results." + } + }, + "description": "List of workspaces." + }, + "Operation": { + "description": "REST API operation", + "type": "object", + "properties": { + "name": { + "description": "Operation name: {provider}/{resource}/{operation}", + "type": "string" + }, + "display": { + "description": "The object that represents the operation.", + "properties": { + "provider": { + "description": "Service provider: Microsoft.ResourceProvider", + "type": "string" + }, + "resource": { + "description": "Resource on which the operation is performed.", + "type": "string" + }, + "operation": { + "description": "Operation type: Read, write, delete, etc.", + "type": "string" + } + } + } + } + }, + "OperationListResult": { + "description": "Result of the request to list Resource Provider operations. It contains a list of operations and a URL link to get the next set of results.", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Operation" + }, + "description": "List of Resource Provider operations supported by the Resource Provider resource provider." + }, + "nextLink": { + "type": "string", + "description": "URL to get the next set of operation list results if there are any." + } + } + }, + "VirtualNetworkPeeringList": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualNetworkPeering" + }, + "description": "List of virtual network peerings on workspace." + }, + "nextLink": { + "type": "string", + "description": "URL to get the next set of virtual network peering list results if there are any." + } + }, + "description": "Gets all virtual network peerings under a workspace." + }, + "VirtualNetworkPeering": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/VirtualNetworkPeeringPropertiesFormat", + "description": "List of properties for vNet Peering" + }, + "name": { + "type": "string", + "description": "Name of the virtual network peering resource", + "readOnly": true + }, + "id": { + "type": "string", + "description": "Resource ID.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "type of the virtual network peering resource", + "readOnly": true + } + }, + "required": [ + "properties" + ], + "description": "Peerings in a VirtualNetwork resource", + "x-ms-azure-resource": true + }, + "VirtualNetworkPeeringPropertiesFormat": { + "properties": { + "allowVirtualNetworkAccess": { + "type": "boolean", + "description": "Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space." + }, + "allowForwardedTraffic": { + "type": "boolean", + "description": "Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network." + }, + "allowGatewayTransit": { + "type": "boolean", + "description": "If gateway links can be used in remote virtual networking to link to this virtual network." + }, + "useRemoteGateways": { + "type": "boolean", + "description": "If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway." + }, + "databricksVirtualNetwork": { + "properties": { + "id": { + "type": "string", + "description": "The Id of the databricks virtual network." + } + }, + "description": " The remote virtual network should be in the same region. See here to learn more (https://docs.microsoft.com/en-us/azure/databricks/administration-guide/cloud-configurations/azure/vnet-peering)." + }, + "databricksAddressSpace": { + "$ref": "#/definitions/AddressSpace", + "description": "The reference to the databricks virtual network address space." + }, + "remoteVirtualNetwork": { + "properties": { + "id": { + "type": "string", + "description": "The Id of the remote virtual network." + } + }, + "description": " The remote virtual network should be in the same region. See here to learn more (https://docs.microsoft.com/en-us/azure/databricks/administration-guide/cloud-configurations/azure/vnet-peering)." + }, + "remoteAddressSpace": { + "$ref": "#/definitions/AddressSpace", + "description": "The reference to the remote virtual network address space." + }, + "peeringState": { + "type": "string", + "description": "The status of the virtual network peering.", + "enum": [ + "Initiated", + "Connected", + "Disconnected" + ], + "x-ms-enum": { + "name": "peeringState", + "modelAsString": true + }, + "readOnly": true + }, + "provisioningState": { + "readOnly": true, + "$ref": "#/definitions/PeeringProvisioningState", + "description": "The provisioning state of the virtual network peering resource." + } + }, + "required": [ + "remoteVirtualNetwork" + ], + "description": "Properties of the virtual network peering." + }, + "AddressSpace": { + "properties": { + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of address blocks reserved for this virtual network in CIDR notation." + } + }, + "description": "AddressSpace contains an array of IP address ranges that can be used by subnets of the virtual network." + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation." + }, + "ResourceGroupName": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + }, + "PeeringNameParameter": { + "name": "peeringName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace vNet peering.", + "x-ms-parameter-location": "method" + } + } + } \ No newline at end of file From b5a27aebf7c80cf8ef3ad202a974afee0132a580 Mon Sep 17 00:00:00 2001 From: Dingmeng Xue <56333063+dingmeng-xue@users.noreply.github.com> Date: Thu, 16 Jul 2020 17:53:39 +0800 Subject: [PATCH 06/61] Init ADO pipeline for PR verification (#626) * Add dummy code * Change file name * Update code * Add PowerShell task * Update code * Correct displayName * Fix typo --- .azure-pipelines/test-module-upgrade.yml | 19 +++++++++++++++++++ tests-upgrade/AutoRestUpgradeTest.ps1 | 1 + 2 files changed, 20 insertions(+) create mode 100644 .azure-pipelines/test-module-upgrade.yml create mode 100644 tests-upgrade/AutoRestUpgradeTest.ps1 diff --git a/.azure-pipelines/test-module-upgrade.yml b/.azure-pipelines/test-module-upgrade.yml new file mode 100644 index 00000000000..1f684e35fc8 --- /dev/null +++ b/.azure-pipelines/test-module-upgrade.yml @@ -0,0 +1,19 @@ +pool: + name: Hosted VS2017 + demands: npm + +steps: +- task: Npm@1 + displayName: 'Install autorest@beta' + inputs: + command: custom + verbose: false + customCommand: 'install -g "@autorest/autorest"' + +- task: PowerShell@2 + displayName: Verify Upgrade + inputs: + targetType: inline + script: './AutoRestUpgradeTest.ps1 -Configuration' + workingDirectory: 'tests-upgrade' + failOnStderr: true \ No newline at end of file diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 new file mode 100644 index 00000000000..21b6ac00801 --- /dev/null +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -0,0 +1 @@ +Write-Host "Hello" \ No newline at end of file From 40539fa96c6967f662c6cdfd0a129d9ca15fc791 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 17 Jul 2020 15:15:51 +0800 Subject: [PATCH 07/61] Add virtual properties and fix a few issues (#628) --- powershell/cmdlets/class.ts | 60 +- powershell/llcsharp/model/model-class-json.ts | 4 +- powershell/llcsharp/model/model-class.ts | 297 +++++----- powershell/llcsharp/model/property.ts | 70 ++- powershell/plugins/cs-namer-v2.ts | 39 +- .../plugin-create-inline-properties.ts | 539 +++++++++--------- powershell/plugins/plugin-tweak-model.ts | 74 ++- 7 files changed, 647 insertions(+), 436 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 08f0f989406..42a8a6bf3c7 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -182,6 +182,60 @@ export function addDefaultInfo(targetProperty: Property, parameter: any) { export function addInfoAttribute(targetProperty: Property, pType: TypeDeclaration, isRequired: boolean, isReadOnly: boolean, description: string, serializedName: string) { + let pt = pType; + while (pt.elementType) { + switch (pt.elementType.schema.type) { + case JsonType.Object: + if (pt.elementType.schema.details.csharp.interfaceImplementation) { + pt = { + declaration: pt.elementType.schema.details.csharp.interfaceImplementation.declaration, + schema: pt.elementType.schema, + }; + } else { + // arg! it's not done yet. Hope it's not polymorphic itself. + pt = { + declaration: `${pt.elementType.schema.details.csharp.namespace}.${pt.elementType.schema.details.csharp.interfaceName}`, + schema: pt.elementType.schema, + }; + } + break; + + case JsonType.Array: + pt = pt.elementType; + break; + + default: + pt = pt.elementType; + break; + } + } + const ptypes = new Array(); + if (pt.schema && pt.schema && pt.schema.details.csharp.byReference) { + ptypes.push(`typeof(${pt.schema.details.csharp.namespace}.${pt.schema.details.csharp.interfaceName}_Reference)`); + // do we need polymorphic types for by-resource ? Don't think so. + } else { + ptypes.push(`typeof(${pt.declaration})`); + if (pt.schema && pt.schema.details.csharp.classImplementation && pt.schema.details.csharp.classImplementation.discriminators) { + ptypes.push(...[...pt.schema.details.csharp.classImplementation.discriminators.values()].map(each => `typeof(${each.modelInterface.fullName})`)); + } + } + + targetProperty.add(new Attribute(ClientRuntime.InfoAttribute, { + parameters: [ + new LiteralExpression(`\nRequired = ${isRequired}`), + new LiteralExpression(`\nReadOnly = ${isReadOnly}`), + new LiteralExpression(`\nDescription = ${new StringExpression(description).value}`), + new LiteralExpression(`\nSerializedName = ${new StringExpression(serializedName).value}`), + new LiteralExpression(`\nPossibleTypes = new [] { ${ptypes.join(',').replace(/\?/g, '').replace(/undefined\./g, '')} }`), + ] + })); + + +} + + +export function NewAddInfoAttribute(targetProperty: Property, pType: TypeDeclaration, isRequired: boolean, isReadOnly: boolean, description: string, serializedName: string) { + let pt = pType; while (pt.elementType) { switch (pt.elementType.schema.type) { @@ -2403,7 +2457,7 @@ export class NewCmdletClass extends Class { } else { cmdletParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(desc || '.')}"`)] })); cmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - addInfoAttribute(cmdletParameter, propertyType, !!vParam.required, false, desc, (vParam.origin).property.serializedName); + NewAddInfoAttribute(cmdletParameter, propertyType, !!vParam.required, false, desc, (vParam.origin).property.serializedName); NewAddCompleterInfo(cmdletParameter, vParam); addDefaultInfo(cmdletParameter, vParam); } @@ -2522,7 +2576,7 @@ export class NewCmdletClass extends Class { regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); } - addInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); + NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); NewAddCompleterInfo(regularCmdletParameter, vParam); addDefaultInfo(regularCmdletParameter, vParam); @@ -2644,7 +2698,7 @@ export class NewCmdletClass extends Class { shouldAddPassThru = shouldAddPassThru || values(operation.callGraph) .selectMany(httpOperation => values(httpOperation.responses)) //.selectMany(responsesItem => responsesItem.value) - .any(value => value instanceof SchemaResponse); + .any(value => (value).schema === undefined); if (outputTypes.size === 0) { outputTypes.add(`typeof(${dotnet.Bool})`); } diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 2e238ddeae5..0bb3ebc8205 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -320,12 +320,12 @@ export class NewJsonSerializableClass extends Class { pushTempVar(); for (const prop of values(modelClass.ownedProperties)) { - if (prop.details.csharp.HeaderProperty === 'Header') { + if (prop.language.csharp.HeaderProperty === 'Header') { continue; } const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Json, prop.valuePrivate, container, prop.serializedName, mode); - if (prop.details.csharp.readOnly) { + if (prop.language.csharp.readOnly) { serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); } else { serializeStatements.add(serializeStatement); diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index b3f613542c1..904c040605b 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -13,11 +13,13 @@ import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/e import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; import { ModelInterface, NewModelInterface } from './interface'; import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-json'; -import { ModelProperty } from './property'; +import { ModelProperty, NewModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; import { DictionaryImplementation } from './model-class-dictionary'; -import { Languages, Language } from '@azure-tools/codemodel'; +import { Languages, Language, Schema as NewSchema } from '@azure-tools/codemodel'; + +import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; export function getVirtualPropertyName(vp?: VirtualProperty): string { @@ -26,6 +28,15 @@ export function getVirtualPropertyName(vp?: VirtualProperty): string { } return vp ? vp.name : ''; } + +export function NewGetVirtualPropertyName(vp?: NewVirtualProperty): string { + + if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { + return NewGetVirtualPropertyName(vp.accessViaMember); + } + return vp ? vp.name : ''; +} + export interface BackingField { field: Field; typeDeclaration: TypeDeclaration; @@ -556,8 +567,8 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { /* @internal */ dictionaryImpl?: DictionaryImplementation; private readonly validationStatements = new Statements(); - public ownedProperties = new Array(); - private pMap = new Map(); + public ownedProperties = new Array(); + private pMap = new Map(); // public hasHeaderProperties: boolean; @@ -623,28 +634,28 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } } - private nested(virtualProperty: VirtualProperty, internal: boolean): string { + private nested(virtualProperty: NewVirtualProperty, internal: boolean): string { if (virtualProperty.accessViaProperty) { if (virtualProperty.accessViaProperty.accessViaProperty) { // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; + return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; } } //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; } - private accessor(virtualProperty: VirtualProperty, internal = false): string { + private accessor(virtualProperty: NewVirtualProperty, internal = false): string { if (virtualProperty.accessViaProperty) { const prefix = virtualProperty.accessViaProperty.accessViaProperty ? this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal) : ''; const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); if (containingProperty && virtualProperty.accessViaMember) { //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `((${virtualProperty.accessViaMember.originalContainingSchema.language.csharp?.fullInternalInterfaceName})${containingProperty.name}${prefix}).${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; } } // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; + return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; } private createProperties() { @@ -653,7 +664,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // add properties if (this.schema.language.csharp?.virtualProperties) { - const addFormatAttributesToProperty = (property: Property, virtualProperty: VirtualProperty) => { + const addFormatAttributesToProperty = (property: Property, virtualProperty: NewVirtualProperty) => { if (virtualProperty.format) { if (virtualProperty.format.suppressFormat) { property.add(new Attribute(DoNotFormatAttribute)); @@ -676,138 +687,138 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } }; // skip-for-time-being - // /* Owned Properties */ - // for (const virtualProperty of values(this.schema.language.csharp.virtualProperties.owned)) { - // const actualProperty = virtualProperty.property; - // let n = 0; - // const decl = this.state.project.modelsNamespace.resolveTypeDeclaration(actualProperty.schema, actualProperty.details.csharp.required, this.state.path('schema')); - - // /* public property */ - // const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.details.csharp.required, actualProperty.serializedName, actualProperty.details.csharp.description, this.state.path('properties', n++), { - // initializer: actualProperty.details.csharp.constantValue ? typeof actualProperty.details.csharp.constantValue === 'string' ? new StringExpression(actualProperty.details.csharp.constantValue) : new LiteralExpression(actualProperty.details.csharp.constantValue) : undefined - // }); - - // if (actualProperty.details.csharp.readOnly) { - // myProperty.set = undefined; - // } - // myProperty.details = virtualProperty.property.details; - - // if (actualProperty.details.csharp.constantValue !== undefined) { - // myProperty.setAccess = Access.Internal; - // myProperty.set = undefined; - // } - - // if (virtualProperty.private) { - // // when properties are inlined, the container accessor can be internalized. I think. - // myProperty.setAccess = Access.Internal; - // myProperty.getAccess = Access.Internal; - // this.pMap.set(virtualProperty, myProperty); - // } - - // this.ownedProperties.push(this.add(myProperty)); - - // if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined) { - // /* internal interface property */ - - // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, { - // description: `Internal Acessors for ${virtualProperty.name}`, - // getAccess: Access.Explicit, - // setAccess: Access.Explicit, - // get: myProperty.get, - // set: myProperty.assignPrivate('value') - // })); - // } - - // if (this.state.getValue('powershell')) { - // myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] })); - // addFormatAttributesToProperty(myProperty, virtualProperty); - // } - // } - - // /* Inherited properties. */ - // for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inherited)) { - // // so each parent property that is getting exposed - // // has to be accessed via the field in this.backingFields - // const parentField = this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.details.csharp.interfaceImplementation.fullName === each.typeDeclaration.declaration : false); - - // const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - // const opsType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.originalContainingSchema, false, this.state); - // const via = virtualProperty.accessViaProperty; - // const parentCast = `(${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName})`; - // const vp = this.add(new Property(virtualProperty.name, propertyType, { - // description: virtualProperty.property.details.csharp.description, - // get: toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`), - // set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value`) - // })); - - // if (virtualProperty.property.details.csharp.constantValue !== undefined) { - // vp.setAccess = Access.Internal; - // vp.set = undefined; - // } - - // if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - - // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - // description: `Internal Acessors for ${virtualProperty.name}`, - // getAccess: Access.Explicit, - // setAccess: Access.Explicit, - // get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`), - // set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`) - // })); - // } - - // if (this.state.getValue('powershell')) { - // vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] })); - // addFormatAttributesToProperty(vp, virtualProperty); - // } - // } - - // /* Inlined properties. */ - // for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inlined)) { - // if (virtualProperty.private) { - // // continue; - // // can't remove it, it has to be either public or internally implemented. - // } - - // if (virtualProperty.accessViaProperty) { - // const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); - // if (containingProperty) { - - // const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - - // // regular inlined property - // const vp = new Property(virtualProperty.name, propertyType, { - // description: virtualProperty.property.details.csharp.description, - // get: toExpression(`${this.accessor(virtualProperty)}`), - // set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value`) - // }); - - // if (!virtualProperty.private) { - // this.add(vp); - // } - - // if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - // this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - // description: `Internal Acessors for ${virtualProperty.name}`, - // getAccess: Access.Explicit, - // setAccess: Access.Explicit, - // get: vp.get, - // set: toExpression(`${this.accessor(virtualProperty)} = value`) - // })); - // } - - // if (virtualProperty.property.details.csharp.constantValue !== undefined) { - // vp.setAccess = Access.Internal; - // vp.set = undefined; - // } - - // if (this.state.getValue('powershell')) { - // vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] })); - // addFormatAttributesToProperty(vp, virtualProperty); - // } - // } - // } - // } + /* Owned Properties */ + for (const virtualProperty of values(>(this.schema.language.csharp.virtualProperties.owned))) { + const actualProperty = virtualProperty.property; + let n = 0; + const decl = this.state.project.modelsNamespace.NewResolveTypeDeclaration(actualProperty.schema, actualProperty.language.csharp?.required, this.state.path('schema')); + + /* public property */ + const myProperty = new NewModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.language.csharp?.required, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), { + initializer: actualProperty.language.csharp?.constantValue ? typeof actualProperty.language.csharp.constantValue === 'string' ? new StringExpression(actualProperty.language.csharp.constantValue) : new LiteralExpression(actualProperty.language.csharp.constantValue) : undefined + }); + + if (actualProperty.language.csharp?.readOnly) { + myProperty.set = undefined; + } + myProperty.language = virtualProperty.property.language; + + if (actualProperty.language.csharp?.constantValue !== undefined) { + myProperty.setAccess = Access.Internal; + myProperty.set = undefined; + } + + if (virtualProperty.private) { + // when properties are inlined, the container accessor can be internalized. I think. + myProperty.setAccess = Access.Internal; + myProperty.getAccess = Access.Internal; + this.pMap.set(virtualProperty, myProperty); + } + + this.ownedProperties.push(this.add(myProperty)); + + if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined) { + /* internal interface property */ + + this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, { + description: `Internal Acessors for ${virtualProperty.name}`, + getAccess: Access.Explicit, + setAccess: Access.Explicit, + get: myProperty.get, + set: myProperty.assignPrivate('value') + })); + } + + if (this.state.getValue('powershell')) { + myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] })); + addFormatAttributesToProperty(myProperty, virtualProperty); + } + } + + /* Inherited properties. */ + for (const virtualProperty of values(>(this.schema.language.csharp.virtualProperties.inherited))) { + // so each parent property that is getting exposed + // has to be accessed via the field in this.backingFields + const parentField = this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.language.csharp?.interfaceImplementation.fullName === each.typeDeclaration.declaration : false); + + const propertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.language.csharp?.required, this.state); + const opsType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(virtualProperty.originalContainingSchema, false, this.state); + const via = virtualProperty.accessViaProperty; + const parentCast = `(${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName})`; + const vp = this.add(new Property(virtualProperty.name, propertyType, { + description: virtualProperty.property.language.csharp?.description, + get: toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`), + set: (virtualProperty.property.language.csharp?.readOnly || virtualProperty.property.language.csharp?.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value`) + })); + + if (virtualProperty.property.language.csharp?.constantValue !== undefined) { + vp.setAccess = Access.Internal; + vp.set = undefined; + } + + if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { + + this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { + description: `Internal Acessors for ${virtualProperty.name}`, + getAccess: Access.Explicit, + setAccess: Access.Explicit, + get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`), + set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`) + })); + } + + if (this.state.getValue('powershell')) { + vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] })); + addFormatAttributesToProperty(vp, virtualProperty); + } + } + + /* Inlined properties. */ + for (const virtualProperty of values(>this.schema.language.csharp.virtualProperties.inlined)) { + if (virtualProperty.private) { + // continue; + // can't remove it, it has to be either public or internally implemented. + } + + if (virtualProperty.accessViaProperty) { + const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); + if (containingProperty) { + + const propertyType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.language.csharp?.required, this.state); + + // regular inlined property + const vp = new Property(virtualProperty.name, propertyType, { + description: virtualProperty.property.language.csharp?.description, + get: toExpression(`${this.accessor(virtualProperty)}`), + set: (virtualProperty.property.language.csharp?.readOnly || virtualProperty.property.language.csharp?.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value`) + }); + + if (!virtualProperty.private) { + this.add(vp); + } + + if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { + this.add(new Property(`${virtualProperty.originalContainingSchema.language.csharp?.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { + description: `Internal Acessors for ${virtualProperty.name}`, + getAccess: Access.Explicit, + setAccess: Access.Explicit, + get: vp.get, + set: toExpression(`${this.accessor(virtualProperty)} = value`) + })); + } + + if (virtualProperty.property.language.csharp?.constantValue !== undefined) { + vp.setAccess = Access.Internal; + vp.set = undefined; + } + + if (this.state.getValue('powershell')) { + vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] })); + addFormatAttributesToProperty(vp, virtualProperty); + } + } + } + } } } diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index d846cd77f11..dd21d43c46e 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -11,12 +11,13 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Property, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State } from '../generator'; +import { State, NewState } from '../generator'; import { ModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; +import { Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export class ModelProperty extends BackedProperty implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ @@ -81,3 +82,68 @@ export class ModelProperty extends BackedProperty implements EnhancedVariable { } + +export class NewModelProperty extends BackedProperty implements EnhancedVariable { + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { + return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { + return this.typeDeclaration.deserializeFromNode(mediaType, node, this); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { + return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { + return this.typeDeclaration.serializeToContent(mediaType, this, mode); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.typeDeclaration.serializeToContainerMember(mediaType, container, this, serializedName, mode); + } + public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { + if (this.required) { + return (this.type).validatePresence(eventListener, this); + } + return ''; + } + public validationStatement(eventListener: Variable): OneOrMoreStatements { + return (this.type).validateValue(eventListener, this); + } + + private required: boolean; + // DISABLED + // public IsHeaderProperty: boolean; + public schema: NewSchema; + public serializedName: string; + private typeDeclaration: NewEnhancedTypeDeclaration; + public language: any; + + constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: NewState, objectInitializer?: DeepPartial) { + const decl = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, isRequired, state.path('schema')); + super(name, decl); + this.typeDeclaration = decl; + this.serializedName = serializedName; + this.schema = schema; + // skip-for-time-being + // if (this.schema.readOnly) { + // this.set = undefined; + // } + this.apply(objectInitializer); + this.description = description; + this.required = isRequired; + if (this.schema.type === SchemaType.Object && isAnExpression(this.get) && schema.language.csharp?.classImplementation) { + // for objects, the getter should auto-create a new object + this.get = toExpression(`(${this.get.value} = ${this.get.value} ?? new ${schema.language.csharp?.fullname}())`); + } + } + + +} \ No newline at end of file diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 898178d4ca1..c39262b7b4f 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -21,29 +21,32 @@ type State = NewModelState; function setPropertyNames(schema: Schema) { // name each property in this schema // skip-for-time-being - // for (const propertySchema of values(schema.properties)) { - // const propertyDetails = propertySchema.details.default; + if (!isObjectSchema(schema)) { + return; + } + for (const propertySchema of values(schema.properties)) { + const propertyDetails = propertySchema.language.default; - // const className = schema.details.csharp.name; + const className = schema.language.csharp?.name; - // let pname = getPascalIdentifier(propertyDetails.name); - // if (pname === className) { - // pname = `${pname}Property`; - // } + let pname = getPascalIdentifier(propertyDetails.name); + if (pname === className) { + pname = `${pname}Property`; + } - // if (pname === 'default') { - // pname = '@default'; - // } + if (pname === 'default') { + pname = '@default'; + } - // propertySchema.details.csharp = { - // ...propertyDetails, - // name: pname // and so are the propertyNmaes - // }; + propertySchema.language.csharp = { + ...propertyDetails, + name: pname // and so are the propertyNmaes + }; - // if (propertyDetails.isNamedStream) { - // propertySchema.details.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); - // } - // } + if (propertyDetails.isNamedStream) { + propertySchema.language.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); + } + } } diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 1bd46a69f02..90cd2f1bd7b 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -13,6 +13,7 @@ import { CommandOperation } from '../utils/command-operation'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; import { VirtualParameter } from '../utils/command-operation'; +import { VirtualProperty, getAllProperties, getAllPublicVirtualProperties } from '../utils/schema'; function getPluralizationService(): EnglishPluralizationService { const result = new EnglishPluralizationService(); @@ -42,248 +43,254 @@ function getNameOptions(typeName: string, components: Array) { } -// function createVirtualProperties(schema: Schema, stack: Array, threshold: number, conflicts: Array) { -// // dolauli -// // owned: all properties(obj & nonobj) in the schema, -// // inherited: Properties from parents, -// // inlined: for obj properties, flatten them to children, -// // did we already inline this object -// if (schema.details.default.inline === 'yes') { -// return true; -// } - -// if (schema.details.default.inline === 'no') { -// return false; -// } - -// // this is bad. This would happen when we have a circular reference in the tree. -// // dolauli curious in which case this will happen, got it to use no-inline to skip inline and avoid circular reference -// if (schema.details.default.inline === 'inprogress') { -// let text = (`Note: during processing of '${schema.details.default.name}' a circular reference has been discovered.`); -// text += '\n In order to proceed, you must add a directive to indicate which model you want to not inline.\n'; -// text += '\ndirective:'; -// text += '\n- no-inline: # choose ONE of these models to disable inlining'; -// for (const each of stack) { -// text += (`\n - ${each} `); -// } -// text += '\n'; -// conflicts.push(text); -// /* `directive: -// - no-inline: -// - MyModel -// - YourModel -// - HerModel -// ` */ - -// // `, and we're skipping inlining.\n ${stack.join(' => ')}`); -// // mark it as 'not-inlining' -// schema.details.default.inline = 'no'; -// return false; -// } - -// // ok, set to in progress now. -// schema.details.default.inline = 'inprogress'; - -// // virutual property set. -// const virtualProperties = schema.details.default.virtualProperties = { -// owned: new Array(), -// inherited: new Array(), -// inlined: new Array(), -// }; - -// // First we should run thru the properties in parent classes and create inliners for each property they have. -// // dolauli handle properties in parents -// for (const parentSchema of values(schema.allOf)) { -// // make sure that the parent is done. -// createVirtualProperties(parentSchema, [...stack, `${schema.details.default.name}`], threshold, conflicts); - -// const parentProperties = parentSchema.details.default.virtualProperties || { -// owned: [], -// inherited: [], -// inlined: [], -// }; - -// // now we go thru the parent's virutal properties and create our own copies -// for (const virtualProperty of [...parentProperties.inherited, ...parentProperties.inlined, ...parentProperties.owned]) { -// // make sure that we have a list of shared owners of this property. -// virtualProperty.sharedWith = virtualProperty.sharedWith || [virtualProperty]; - -// // we are just copying over theirs to ours. -// const inheritedProperty = { -// name: virtualProperty.name, -// property: virtualProperty.property, -// private: virtualProperty.private, -// nameComponents: virtualProperty.nameComponents, -// nameOptions: virtualProperty.nameOptions, -// accessViaProperty: virtualProperty, -// accessViaMember: virtualProperty, -// accessViaSchema: parentSchema, -// originalContainingSchema: virtualProperty.originalContainingSchema, -// description: virtualProperty.description, -// alias: [], -// required: virtualProperty.required || !!values(schema.required).first(each => !!each && !!each.toLowerCase && each.toLowerCase() === virtualProperty.property.details.default.name.toLowerCase()), -// sharedWith: virtualProperty.sharedWith, -// }; -// // add it to the list of virtual properties that share this property. -// virtualProperty.sharedWith.push(inheritedProperty); - -// // add it to this class. -// virtualProperties.inherited.push(inheritedProperty); -// } -// } - -// // dolauli figure out object properties and non object properties in this class -// const [objectProperties, nonObjectProperties] = values(schema.properties).bifurcate(each => -// !schema.details.default['skip-inline'] && // if this schema is marked skip-inline, none can be inlined, treat them all as straight properties. -// !each.schema.details.default['skip-inline'] && // if the property schema is marked skip-inline, then it should not be processed either. -// each.schema.type === JsonType.Object && // is it an object -// getAllProperties(each.schema).length > 0 // does it have properties (or inherit properties) -// ); - -// // run thru the properties in this class. -// // dolauli handle properties in this class -// for (const property of objectProperties) { -// const propertyName = property.details.default.name; - -// // for each object member, make sure that it's inlined it's children that it can. -// createVirtualProperties(property.schema, [...stack, `${schema.details.default.name}`], threshold, conflicts); - -// // this happens if there is a circular reference. -// // this means that this class should not attempt any inlining of that property at all . -// // dolauli pay attention to the condition check -// const canInline = -// // (!property.schema.details.default['skip-inline']) && -// (!property.schema.details.default.byReference) && -// (!property.schema.additionalProperties) && -// property.schema.details.default.inline === 'yes'; - -// // the target has properties that we can inline -// const virtualChildProperties = property.schema.details.default.virtualProperties || { -// owned: [], -// inherited: [], -// inlined: [], -// }; - -// const allNotRequired = values(getAllPublicVirtualProperties()).all(each => !each.property.details.default.required); - -// const childCount = length(virtualChildProperties.owned) + length(virtualChildProperties.inherited) + length(virtualChildProperties.inlined); -// if (canInline && (property.details.default.required || allNotRequired) && (childCount < threshold || propertyName === 'properties')) { - - -// // if the child property is low enough (or it's 'properties'), let's create virtual properties for each one. -// // create a private property for the inlined ones to use. -// const privateProperty = { -// name: getPascalIdentifier(propertyName), -// propertySchema: schema, -// property, -// nameComponents: [getPascalIdentifier(propertyName)], -// nameOptions: getNameOptions(schema.details.default.name, [propertyName]), -// private: true, -// description: property.description || '', -// originalContainingSchema: schema, -// alias: [], -// required: property.details.default.required, -// }; -// virtualProperties.owned.push(privateProperty); - -// for (const inlinedProperty of [...virtualChildProperties.inherited, ...virtualChildProperties.owned]) { -// // child properties are be inlined without prefixing the name with the property name -// // unless there is a collision, in which case, we have to resolve - -// // (scan back from the far right) -// // deeper child properties should be inlined with their parent's name -// // ie, this.[properties].owner.name should be this.ownerName - -// const proposedName = getPascalIdentifier(`${propertyName === 'properties' || /*objectProperties.length === 1*/ propertyName === 'error' ? '' : pascalCase(fixLeadingNumber(deconstruct(propertyName)).map(each => singularize(each)))} ${inlinedProperty.name}`); - -// const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; -// virtualProperties.inlined.push({ -// name: proposedName, -// property: inlinedProperty.property, -// private: inlinedProperty.private, -// nameComponents: components, -// nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), -// accessViaProperty: privateProperty, -// accessViaMember: inlinedProperty, -// accessViaSchema: schema, -// originalContainingSchema: schema, -// description: inlinedProperty.description, -// alias: [], -// required: inlinedProperty.required && privateProperty.required, -// }); -// } - - -// for (const inlinedProperty of [...virtualChildProperties.inlined]) { -// // child properties are be inlined without prefixing the name with the property name -// // unless there is a collision, in which case, we have to resolve - -// // (scan back from the far right) -// // deeper child properties should be inlined with their parent's name -// // ie, this.[properties].owner.name should be this.ownerName - - -// const proposedName = getPascalIdentifier(inlinedProperty.name); -// const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; -// virtualProperties.inlined.push({ -// name: proposedName, -// property: inlinedProperty.property, -// private: inlinedProperty.private, -// nameComponents: components, -// nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), -// accessViaProperty: privateProperty, -// accessViaMember: inlinedProperty, -// accessViaSchema: schema, -// originalContainingSchema: schema, -// description: inlinedProperty.description, -// alias: [], -// required: inlinedProperty.required && privateProperty.required -// }); -// } -// } else { -// // otherwise, we're not below the threshold, and we should treat this as a non-inlined property -// nonObjectProperties.push(property); -// } -// } - -// for (const property of nonObjectProperties) { -// const name = getPascalIdentifier(property.details.default.name); -// // this is not something that has properties, -// // so we don't need to do any inlining -// // however, we can add it to our list of virtual properties -// // so that our consumers can get it. -// virtualProperties.owned.push({ -// name, -// property, -// nameComponents: [name], -// nameOptions: [name], -// description: property.description || '', -// originalContainingSchema: schema, -// alias: [], -// required: property.details.default.required -// }); -// } - -// // resolve name collisions. -// const allProps = [...virtualProperties.owned, ...virtualProperties.inherited, ...virtualProperties.inlined]; -// const inlined = new Map(); - -// for (const each of allProps) { -// // track number of instances of a given name. -// inlined.set(each.name, (inlined.get(each.name) || 0) + 1); -// } - -// const usedNames = new Set(inlined.keys()); -// for (const each of virtualProperties.inlined.sort((a, b) => length(a.nameOptions) - length(b.nameOptions))) { -// const ct = inlined.get(each.name); -// if (ct && ct > 1) { -// // console.error(`Fixing collision on name ${each.name} #${ct} `); -// each.name = selectName(each.nameOptions, usedNames); -// } -// } -// schema.details.default.inline = 'yes'; -// return true; -// } +function createVirtualProperties(schema: ObjectSchema, stack: Array, threshold: number, conflicts: Array) { + // dolauli + // owned: all properties(obj & nonobj) in the schema, + // inherited: Properties from parents, + // inlined: for obj properties, flatten them to children, + // did we already inline this object + if (schema.language.default.inline === 'yes') { + return true; + } + + if (schema.language.default.inline === 'no') { + return false; + } + + // this is bad. This would happen when we have a circular reference in the tree. + // dolauli curious in which case this will happen, got it to use no-inline to skip inline and avoid circular reference + if (schema.language.default.inline === 'inprogress') { + let text = (`Note: during processing of '${schema.language.default.name}' a circular reference has been discovered.`); + text += '\n In order to proceed, you must add a directive to indicate which model you want to not inline.\n'; + text += '\ndirective:'; + text += '\n- no-inline: # choose ONE of these models to disable inlining'; + for (const each of stack) { + text += (`\n - ${each} `); + } + text += '\n'; + conflicts.push(text); + /* `directive: + - no-inline: + - MyModel + - YourModel + - HerModel + ` */ + + // `, and we're skipping inlining.\n ${stack.join(' => ')}`); + // mark it as 'not-inlining' + schema.language.default.inline = 'no'; + return false; + } + + // ok, set to in progress now. + schema.language.default.inline = 'inprogress'; + + // virutual property set. + const virtualProperties = schema.language.default.virtualProperties = { + owned: new Array(), + inherited: new Array(), + inlined: new Array(), + }; + + // First we should run thru the properties in parent classes and create inliners for each property they have. + // dolauli handle properties in parents + for (const parentSchema of values(schema.parents?.immediate)) { + // make sure that the parent is done. + + // Guess parent should always be an object. + if (!isObjectSchema(parentSchema)) + continue; + + createVirtualProperties(parentSchema, [...stack, `${schema.language.default.name}`], threshold, conflicts); + + const parentProperties = parentSchema.language.default.virtualProperties || { + owned: [], + inherited: [], + inlined: [], + }; + + // now we go thru the parent's virutal properties and create our own copies + for (const virtualProperty of [...parentProperties.inherited, ...parentProperties.inlined, ...parentProperties.owned]) { + // make sure that we have a list of shared owners of this property. + virtualProperty.sharedWith = virtualProperty.sharedWith || [virtualProperty]; + + // we are just copying over theirs to ours. + const inheritedProperty = { + name: virtualProperty.name, + property: virtualProperty.property, + private: virtualProperty.private, + nameComponents: virtualProperty.nameComponents, + nameOptions: virtualProperty.nameOptions, + accessViaProperty: virtualProperty, + accessViaMember: virtualProperty, + accessViaSchema: parentSchema, + originalContainingSchema: virtualProperty.originalContainingSchema, + description: virtualProperty.description, + alias: [], + required: virtualProperty.required, //|| !!values(schema.required).first(each => !!each && !!each.toLowerCase && each.toLowerCase() === virtualProperty.property.details.default.name.toLowerCase()), + sharedWith: virtualProperty.sharedWith, + }; + // add it to the list of virtual properties that share this property. + virtualProperty.sharedWith.push(inheritedProperty); + + // add it to this class. + virtualProperties.inherited.push(inheritedProperty); + } + } + + // dolauli figure out object properties and non object properties in this class + const [objectProperties, nonObjectProperties] = values(schema.properties).bifurcate(each => + !schema.language.default['skip-inline'] && // if this schema is marked skip-inline, none can be inlined, treat them all as straight properties. + !each.schema.language.default['skip-inline'] && // if the property schema is marked skip-inline, then it should not be processed either. + each.schema.type === SchemaType.Object && // is it an object + getAllProperties(each.schema).length > 0 // does it have properties (or inherit properties) + ); + + // run thru the properties in this class. + // dolauli handle properties in this class + for (const property of objectProperties) { + const propertyName = property.language.default.name; + + // for each object member, make sure that it's inlined it's children that it can. + createVirtualProperties(property.schema, [...stack, `${schema.language.default.name}`], threshold, conflicts); + + // this happens if there is a circular reference. + // this means that this class should not attempt any inlining of that property at all . + // dolauli pay attention to the condition check + const canInline = + // (!property.schema.details.default['skip-inline']) && + (!property.schema.language.default.byReference) && + // no additionalProperties in m4 + //(!(property.schema).additionalProperties) && + (property.schema).language.default.inline === 'yes'; + + // the target has properties that we can inline + const virtualChildProperties = property.schema.language.default.virtualProperties || { + owned: [], + inherited: [], + inlined: [], + }; + + const allNotRequired = values(getAllPublicVirtualProperties()).all(each => !each.property.language.default.required); + + const childCount = length(virtualChildProperties.owned) + length(virtualChildProperties.inherited) + length(virtualChildProperties.inlined); + if (canInline && (property.language.default.required || allNotRequired) && (childCount < threshold || propertyName === 'properties')) { + + + // if the child property is low enough (or it's 'properties'), let's create virtual properties for each one. + // create a private property for the inlined ones to use. + const privateProperty = { + name: getPascalIdentifier(propertyName), + propertySchema: schema, + property, + nameComponents: [getPascalIdentifier(propertyName)], + nameOptions: getNameOptions(schema.language.default.name, [propertyName]), + private: true, + description: property.summary || '', + originalContainingSchema: schema, + alias: [], + required: property.language.default.required, + }; + virtualProperties.owned.push(privateProperty); + + for (const inlinedProperty of [...virtualChildProperties.inherited, ...virtualChildProperties.owned]) { + // child properties are be inlined without prefixing the name with the property name + // unless there is a collision, in which case, we have to resolve + + // (scan back from the far right) + // deeper child properties should be inlined with their parent's name + // ie, this.[properties].owner.name should be this.ownerName + + const proposedName = getPascalIdentifier(`${propertyName === 'properties' || /*objectProperties.length === 1*/ propertyName === 'error' ? '' : pascalCase(fixLeadingNumber(deconstruct(propertyName)).map(each => singularize(each)))} ${inlinedProperty.name}`); + + const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; + virtualProperties.inlined.push({ + name: proposedName, + property: inlinedProperty.property, + private: inlinedProperty.private, + nameComponents: components, + nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), + accessViaProperty: privateProperty, + accessViaMember: inlinedProperty, + accessViaSchema: schema, + originalContainingSchema: schema, + description: inlinedProperty.description, + alias: [], + required: inlinedProperty.required && privateProperty.required, + }); + } + + + for (const inlinedProperty of [...virtualChildProperties.inlined]) { + // child properties are be inlined without prefixing the name with the property name + // unless there is a collision, in which case, we have to resolve + + // (scan back from the far right) + // deeper child properties should be inlined with their parent's name + // ie, this.[properties].owner.name should be this.ownerName + + + const proposedName = getPascalIdentifier(inlinedProperty.name); + const components = [...removeSequentialDuplicates([propertyName, ...inlinedProperty.nameComponents])]; + virtualProperties.inlined.push({ + name: proposedName, + property: inlinedProperty.property, + private: inlinedProperty.private, + nameComponents: components, + nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), + accessViaProperty: privateProperty, + accessViaMember: inlinedProperty, + accessViaSchema: schema, + originalContainingSchema: schema, + description: inlinedProperty.description, + alias: [], + required: inlinedProperty.required && privateProperty.required + }); + } + } else { + // otherwise, we're not below the threshold, and we should treat this as a non-inlined property + nonObjectProperties.push(property); + } + } + + for (const property of nonObjectProperties) { + const name = getPascalIdentifier(property.language.default.name); + // this is not something that has properties, + // so we don't need to do any inlining + // however, we can add it to our list of virtual properties + // so that our consumers can get it. + virtualProperties.owned.push({ + name, + property, + nameComponents: [name], + nameOptions: [name], + description: property.summary || '', + originalContainingSchema: schema, + alias: [], + required: property.language.default.required + }); + } + + // resolve name collisions. + const allProps = [...virtualProperties.owned, ...virtualProperties.inherited, ...virtualProperties.inlined]; + const inlined = new Map(); + + for (const each of allProps) { + // track number of instances of a given name. + inlined.set(each.name, (inlined.get(each.name) || 0) + 1); + } + + const usedNames = new Set(inlined.keys()); + for (const each of virtualProperties.inlined.sort((a, b) => length(a.nameOptions) - length(b.nameOptions))) { + const ct = inlined.get(each.name); + if (ct && ct > 1) { + // console.error(`Fixing collision on name ${each.name} #${ct} `); + each.name = selectName(each.nameOptions, usedNames); + } + } + schema.language.default.inline = 'yes'; + return true; +} function createVirtualParameters(operation: CommandOperation) { // dolauli expand body parameter @@ -359,30 +366,30 @@ async function createVirtuals(state: State): Promise { // dolauli this plugin is used to expand the property in an object. // dolauli inline-threshold could be set in readme.md // skip-for-time-being - // const threshold = await state.getValue('inlining-threshold', 24); - // const conflicts = new Array(); - - // for (const schema of values(state.model.schemas)) { - // if (schema.type === JsonType.Object) { - // // did we already inline this object - // // dolauli skip if inlined - // if (schema.details.default.inlined) { - // continue; - // } - // // we have an object, let's process it. - - // createVirtualProperties(schema, new Array(), threshold, conflicts); - // } - // } - // if (length(conflicts) > 0) { - // // dolauli need to figure out how inline-properties is used in readme.md - // state.error('You have one or more circular references in your model, you must add configuration entries to specify which models won\'t be inlined.', ['inline-properties']); - // for (const each of conflicts) { - // state.error(each, ['circular reference']); - // } - // throw new Error('Circular references exists, must mark models as `no-inline`'); - // } - // dolauli update operations under commands + const threshold = await state.getValue('inlining-threshold', 24); + const conflicts = new Array(); + + for (const schema of values(state.model.schemas.objects)) { + + // did we already inline this object + // dolauli skip if inlined + if (schema.language.default.inlined) { + continue; + } + // we have an object, let's process it. + + createVirtualProperties(schema, new Array(), threshold, conflicts); + + } + if (length(conflicts) > 0) { + // dolauli need to figure out how inline-properties is used in readme.md + state.error('You have one or more circular references in your model, you must add configuration entries to specify which models won\'t be inlined.', ['inline-properties']); + for (const each of conflicts) { + state.error(each, ['circular reference']); + } + throw new Error('Circular references exists, must mark models as `no-inline`'); + } + //dolauli update operations under commands for (const operation of values(state.model.commands.operations)) { createVirtualParameters(operation); } diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 9750101ed49..7712068e4b7 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { Property, codeModelSchema, CodeModel, Schema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize } from '@azure-tools/codegen'; @@ -12,6 +12,7 @@ import { NewModelState } from '../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { defaultCipherList } from 'constants'; +import { NewString } from '../llcsharp/schema/string'; export const HeaderProperty = 'HeaderProperty'; export enum HeaderPropertyType { @@ -79,6 +80,75 @@ async function tweakModelV2(state: State): Promise { universalId.apiVersions = universalId.apiVersions || []; state.model.schemas.objects = state.model.schemas.objects || []; (universalId.language.default).uid = true; + + universalId.properties = universalId.properties || new Array(); + const urlParam = new Set(); + for (const operationGroup of values(model.operationGroups)) { + for (const operation of values(operationGroup.operations)) { + for (const param of values(operation.parameters).where(each => each.protocol.http?.in === ParameterLocation.Path)) { + const name = param.language.default.name; + + if (!urlParam.has(name)) { + urlParam.add(name); + universalId.addProperty(new Property(name, '', param.schema, { + serializedName: name, language: { + default: { + description: param.summary, + name: name, + required: false, + readOnly: false, + uid: 'universal-parameter:resource identity' + } + } + })); + } + } + } + } + + if (await state.getValue('azure', false)) { + universalId.addProperty(new Property('id', '', new StringSchema('_identity_type_', 'Resource identity path'), + { + serializedName: 'id', language: { + default: { + description: 'Resource identity path', + name: 'id', + required: false, + readOnly: false, + uid: 'universal-parameter:resource identity' + } + } + } + )); + } + // universalId.properties['id'] = new Property('id', { + // schema: new Schema('_identity_type_', { type: JsonType.String, description: 'Resource identity path' }), + // description: 'Resource identity path', serializedName: 'id', details: { + // default: { + // description: 'Resource identity path', + // name: 'id', + // required: false, + // readOnly: false, + // uid: 'universal-parameter:resource identity' + // } + // } + // }); + + + // if (await state.getValue('azure', false)) { + // universalId.properties['id'] = new Property('id', { + // schema: new Schema('_identity_type_', { type: JsonType.String, description: 'Resource identity path' }), + // description: 'Resource identity path', serializedName: 'id', details: { + // default: { + // description: 'Resource identity path', + // name: 'id', + // required: false, + // readOnly: false, + // uid: 'universal-parameter:resource identity' + // } + // } + // }); + // } state.model.schemas.objects.push(universalId); model.commands = { @@ -354,4 +424,4 @@ export async function tweakModelPlugin(service: Host) { //const result = tweakModelV2(session); await service.WriteFile('code-model-v4-tweakcodemodel-v2.yaml', serialize(await tweakModelV2(state)), undefined, 'code-model-v4'); //return processCodeModel(tweakModelV2, service, 'tweakcodemodel-v2'); -} +} \ No newline at end of file From d37d2219799ea39f5d7600b9eac0ff5183212d9b Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 21 Jul 2020 12:08:42 +0800 Subject: [PATCH 08/61] Support parameter path - llcsharp (#629) * add tweak-model-azure-v2 plugin * support path parameter (llcsharp) * fix comment * fix comment * Fix some issues in powershell-v2 Co-authored-by: xichen Co-authored-by: derek --- powershell/autorest-configuration.md | 5 +- powershell/cmdlets/class.ts | 19 +- powershell/cmdlets/namespace.ts | 1 - powershell/llcsharp/model/interface.ts | 127 +++++++---- powershell/llcsharp/model/model-class.ts | 1 - powershell/llcsharp/operation/method.ts | 50 ++--- powershell/main.ts | 4 +- powershell/package.json | 2 +- powershell/plugins/llcsharp-v2.ts | 1 + powershell/plugins/llcsharp.ts | 13 +- .../plugin-create-inline-properties.ts | 8 +- .../plugins/plugin-tweak-model-azure-v2.ts | 201 ++++++++++++++++++ powershell/plugins/plugin-tweak-model.ts | 150 +++++++------ powershell/utils/PwshModel.ts | 2 +- 14 files changed, 432 insertions(+), 152 deletions(-) create mode 100644 powershell/plugins/plugin-tweak-model-azure-v2.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 79134309a6d..5d5c8d8ec61 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -121,9 +121,12 @@ pipeline: # --- extension powershell based on modelerfour tweakcodemodel-v2: input: modelerfour/identity + + tweakcodemodelazure-v2: + input: tweakcodemodel-v2 create-commands-v2: - input: tweakcodemodel-v2 + input: tweakcodemodelazure-v2 create-virtual-properties-v2: input: create-commands-v2 diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 42a8a6bf3c7..cf021f91903 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -1837,7 +1837,7 @@ export class NewCmdletClass extends Class { name: p.language.csharp?.name, param: values($this.properties). where(each => each.metadata.parameterDefinition). - first(each => each.metadata.parameterDefinition.details.csharp.uid === p.language.csharp?.uid), + first(each => each.metadata.parameterDefinition.schema === p.schema), isPathParam: $this.isViaIdentity && p.protocol.http?.in === ParameterLocation.Path }; @@ -2576,7 +2576,7 @@ export class NewCmdletClass extends Class { regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); } - NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); + NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, origin.details.default.name); NewAddCompleterInfo(regularCmdletParameter, vParam); addDefaultInfo(regularCmdletParameter, vParam); @@ -2586,16 +2586,15 @@ export class NewCmdletClass extends Class { } const httpParam = origin.details.csharp.httpParameter; - const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; + //const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; - // skip-for-time-being - // const cat = values(operation.callGraph[0].parameters). - // where(each => !(each.details.csharp.constantValue)). - // first(each => each.details.csharp.uid === uid); + const cat = values(operation.callGraph[0].parameters). + where(each => !(each.language.csharp?.constantValue)). + first(each => each.schema === httpParam.schema); - // if (cat) { - // regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase(cat.in)}`] })); - // } + if (cat) { + regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase((cat.protocol.http?.in))}`] })); + } if (origin.details.csharp.completer) { diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index 96e05ae6ff4..b215bb3eb70 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -55,7 +55,6 @@ export class NewCmdletNamespace extends Namespace { if (this.state.project.azure && operation.details.csharp.verb === 'Set' && operation.details.csharp.name.indexOf('ViaIdentity') > 0) { continue; } - // skip-for-time-being this.addClass(await new NewCmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); } return this; diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index e09576d5969..a4d8d61fd51 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -8,13 +8,14 @@ import { KnownMediaType, JsonType, getPolymorphicBases } from '@azure-tools/code import { Expression, ExpressionOrLiteral, Interface, Namespace, OneOrMoreStatements, Variable, Access, InterfaceProperty, Attribute, StringExpression, LiteralExpression, Property, TypeDeclaration } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Schema as NewSchema, Language } from '@azure-tools/codemodel'; +import { Schema as NewSchema, Language, ObjectSchema } from '@azure-tools/codemodel'; import { State, NewState } from '../generator'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ModelClass, NewModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; +import { VirtualProperty as NewVirtualProperty, VirtualProperties as NewVirtualProperties } from '../../utils/schema' export function addInfoAttribute(targetProperty: Property, pType: TypeDeclaration, isRequired: boolean, isReadOnly: boolean, description: string, serializedName: string) { @@ -70,6 +71,58 @@ export function addInfoAttribute(targetProperty: Property, pType: TypeDeclaratio })); } +export function newAddInfoAttribute(targetProperty: Property, pType: TypeDeclaration, isRequired: boolean, isReadOnly: boolean, description: string, serializedName: string) { + + let pt = pType; + while (pt.elementType) { + switch (pt.elementType.schema.type) { + case JsonType.Object: + if (pt.elementType.schema.language.csharp.interfaceImplementation) { + pt = { + declaration: pt.elementType.schema.language.csharp.interfaceImplementation.declaration, + schema: pt.elementType.schema, + }; + } else { + // arg! it's not done yet. Hope it's not polymorphic itself. + pt = { + declaration: `${pt.elementType.schema.language.csharp.namespace}.${pt.elementType.schema.language.csharp.interfaceName}`, + schema: pt.elementType.schema, + }; + } + break; + + case JsonType.Array: + pt = pt.elementType; + break; + + default: + pt = pt.elementType; + break; + } + } + const ptypes = new Array(); + + if (pt.schema && pt.schema.language.csharp.byReference) { + ptypes.push(`typeof(${pt.schema.language.csharp.namespace}.${pt.schema.language.csharp.interfaceName}_Reference)`); + // do we need polymorphic types for by-resource ? Don't think so. + } else { + ptypes.push(`typeof(${pt.declaration})`); + if (pt.schema && pt.schema.language.csharp.classImplementation && pt.schema.language.csharp.classImplementation.discriminators) { + ptypes.push(...[...pt.schema.language.csharp.classImplementation.discriminators.values()].map(each => `typeof(${each.modelInterface.fullName})`)); + } + } + + targetProperty.add(new Attribute(ClientRuntime.InfoAttribute, { + parameters: [ + new LiteralExpression(`\nRequired = ${isRequired}`), + new LiteralExpression(`\nReadOnly = ${isReadOnly}`), + new LiteralExpression(`\nDescription = ${new StringExpression(description ?? '').value}`), + new LiteralExpression(`\nSerializedName = ${new StringExpression(serializedName).value}`), + new LiteralExpression(`\nPossibleTypes = new [] { ${ptypes.join(',').replace(/\?/g, '').replace(/undefined\./g, '')} }`), + ] + })); +} + export class ModelInterface extends Interface implements EnhancedTypeDeclaration { get schema(): Schema { @@ -302,58 +355,58 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla //implData.interfaceImplementation = this; this.description = `${this.schema.language.csharp.description}`; - const virtualProperties = this.schema.language.csharp.virtualProperties || { + const virtualProperties: NewVirtualProperties = this.schema.language.csharp.virtualProperties || { owned: [], inherited: [], inlined: [] }; // skip-for-time-being - // if (this.schema.language.csharp.virtualProperties) { + if (this.schema.language.csharp.virtualProperties) { - // for (const virtualProperty of values(virtualProperties.owned)) { - // if (virtualProperty.private && !this.isInternal) { - // continue; - // } + for (const virtualProperty of values(virtualProperties.owned)) { + if (virtualProperty.private && !this.isInternal) { + continue; + } - // const modelProperty = virtualProperty.property; + const modelProperty = virtualProperty.property; - // const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); + const internalSet = !!(!this.isInternal && (modelProperty.readOnly || (modelProperty.language.csharp).constantValue)); - // const isRequired = !!modelProperty.details.csharp.required; - // const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - // const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - // description: modelProperty.details.csharp.description, - // setAccess: internalSet ? Access.Internal : Access.Public - // })); + const isRequired = !!modelProperty.required; + const pType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); + const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { + description: modelProperty.language.default.description, + setAccess: internalSet ? Access.Internal : Access.Public + })); - // this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); + this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.language.default.description, modelProperty.serializedName); - // if (!this.isInternal && modelProperty.details.csharp.constantValue !== undefined) { - // p.setAccess = Access.Internal; - // } - // } + if (!this.isInternal && (modelProperty.language.csharp).constantValue !== undefined) { + p.setAccess = Access.Internal; + } + } - // for (const virtualProperty of values(virtualProperties.inlined)) { + for (const virtualProperty of values(virtualProperties.inlined)) { - // // don't publicly expose the 'private' properties. - // if (virtualProperty.private && !this.isInternal) { - // continue; - // } + // don't publicly expose the 'private' properties. + if (virtualProperty.private && !this.isInternal) { + continue; + } - // const modelProperty = virtualProperty.property; - // const isRequired = !!modelProperty.details.csharp.required; - // const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); + const modelProperty = virtualProperty.property; + const isRequired = !!modelProperty.required; + const pType = this.state.project.modelsNamespace.NewResolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - // const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); + const internalSet = !!(!this.isInternal && (modelProperty.readOnly || (modelProperty.language.csharp).constantValue)); - // const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - // description: modelProperty.details.csharp.description, - // setAccess: internalSet ? Access.Internal : Access.Public - // })); - // this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); + const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { + description: modelProperty.language.default.description, + setAccess: internalSet ? Access.Internal : Access.Public + })); + this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.language.default.description, modelProperty.serializedName); - // } - // } + } + } if (!this.isInternal) { // mark it as json serializable @@ -371,7 +424,7 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla addInfoAttribute(p: Property, pType: TypeDeclaration, isRequired: boolean, internalSet: boolean, description: string, serializedName: string) { if (!this.isInternal) { - return addInfoAttribute(p, pType, isRequired, internalSet, description, serializedName); + return newAddInfoAttribute(p, pType, isRequired, internalSet, description, serializedName); } } } diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 904c040605b..e528249edd8 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -18,7 +18,6 @@ import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } f import { Schema } from '../code-model'; import { DictionaryImplementation } from './model-class-dictionary'; import { Languages, Language, Schema as NewSchema } from '@azure-tools/codemodel'; - import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; export function getVirtualPropertyName(vp?: VirtualProperty): string { diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 58a7c338950..35f9f09ed70 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -37,6 +37,11 @@ function removeEncoding(pp: OperationParameter, paramName: string, kmt: KnownMed return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; } +function newRemoveEncoding(pp: NewOperationParameter, paramName: string, kmt: KnownMediaType): string { + const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; + return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; +} + export class EventListener { constructor(protected expression: Expression, protected emitSignals: boolean) { @@ -371,6 +376,7 @@ export class NewOperationMethod extends Method { this.senderParameter = this.addParameter(new Parameter('sender', ClientRuntime.ISendAsync, { description: `an instance of an ${ClientRuntime.ISendAsync} pipeline to use to make the request.` })); let rx = this.operation.requests ? this.operation.requests[0].protocol.http?.path : ''; + const path = rx; // For post API, Some URI may contain an action string .e.x '/start' at the end // of the URI, for such cases, we will drop the action string if identityCorrection // is set in the configuration @@ -399,19 +405,19 @@ export class NewOperationMethod extends Method { // + "`); // } - // for (const pp of pathParams) { - // rx = rx.replace(`{${pp.param.name}}`, `(?<${pp.param.name}>[^/]+)`); + for (const pp of pathParams) { + rx = rx.replace(`{${pp.param.language.default.name}}`, `(?<${pp.param.language.default.name}>[^/]+)`); - // if (this.viaIdentity) { - // url = url.replace(`{${pp.param.name}}`, `" - // + ${pp.name} - // + "`); - // } else { - // url = url.replace(`{${pp.param.name}}`, `" - // + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} - // + "`); - // } - // } + if (this.viaIdentity) { + url = url.replace(`{${pp.param.language.default.name}}`, `" + + ${pp.name} + + "`); + } else { + url = url.replace(`{${pp.param.language.default.name}}`, `" + + ${newRemoveEncoding(pp, '', KnownMediaType.UriParameter)} + + "`); + } + } rx = `"^${rx}$"`; url = url.replace(/\s*\+ ""/gm, ''); @@ -429,30 +435,20 @@ export class NewOperationMethod extends Method { const match = Local('_match', `${System.Text.RegularExpressions.Regex.new(rx).value}.Match(${identity.value})`); yield match.declarationStatement; - yield If(`!${match}.Success`, `throw new global::System.Exception("Invalid identity for URI '${rx}'");`); + yield If(`!${match}.Success`, `throw new global::System.Exception("Invalid identity for URI '${path}'");`); yield EOL; yield '// replace URI parameters with values from identity'; - // skip-for-time-being - // for (const pp of pathParams) { - // yield `var ${pp.name} = ${match.value}.Groups["${pp.param.name}"].Value;`; - // } + for (const pp of pathParams) { + yield `var ${pp.name} = ${match.value}.Groups["${pp.param.language.default.name}"].Value;`; + } } yield '// construct URL'; - // const urlV = new LocalVariable('_url', dotnet.Var, { - // initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( - // "${url}" - // ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - // + ${removeEncoding(pp, pp.param.name, KnownMediaType.QueryParameter)}`, ` - // + "&"` - // )} - // ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) - // }); const urlV = new LocalVariable('_url', dotnet.Var, { initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( "${url}" ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${''}`, ` + + ${newRemoveEncoding(pp, pp.param.language.default.name, KnownMediaType.QueryParameter)}`, ` + "&"` )} ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) diff --git a/powershell/main.ts b/powershell/main.ts index a338bc235c2..9181414f78e 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -13,7 +13,7 @@ import { csnamer } from './plugins/cs-namer'; import { llcsharp } from './plugins/llcsharp'; import { createInlinedPropertiesPlugin } from './plugins/plugin-create-inline-properties'; import { tweakModelPlugin } from './plugins/plugin-tweak-model'; -import { tweakModelAzurePlugin } from './plugins/plugin-tweak-model-azure'; +import { tweakModelAzurePluginV2 } from './plugins/plugin-tweak-model-azure-v2'; import { createCommandsV2 } from './plugins/create-commands-v2'; import { csnamerV2 } from './plugins/cs-namer-v2'; import { namerV2 } from './plugins/ps-namer-v2'; @@ -33,7 +33,7 @@ export async function main() { pluginHost.Add('llcsharp', llcsharp); // Following are plugins moved from remodeler pluginHost.Add('tweakcodemodel-v2', tweakModelPlugin); - pluginHost.Add('tweakcodemodelazure-v2', tweakModelAzurePlugin); + pluginHost.Add('tweakcodemodelazure-v2', tweakModelAzurePluginV2); pluginHost.Add('create-virtual-properties-v2', createInlinedPropertiesPlugin); pluginHost.Add('create-commands-v2', createCommandsV2); pluginHost.Add('csnamer-v2', csnamerV2); diff --git a/powershell/package.json b/powershell/package.json index 891838f6031..62b74a21d72 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -66,4 +66,4 @@ "source-map-support": "0.5.13", "xmlbuilder": "10.1.1" } -} \ No newline at end of file +} diff --git a/powershell/plugins/llcsharp-v2.ts b/powershell/plugins/llcsharp-v2.ts index 802f820fc78..a5c14fed490 100644 --- a/powershell/plugins/llcsharp-v2.ts +++ b/powershell/plugins/llcsharp-v2.ts @@ -10,6 +10,7 @@ import { Model } from '../llcsharp/code-model'; import { State } from '../llcsharp/generator'; import { Project, NewProject } from '../llcsharp/project'; import { PwshModel } from '../utils/PwshModel'; +import { Dictionary } from '@azure-tools/linq'; const resources = `${__dirname}/../../resources`; diff --git a/powershell/plugins/llcsharp.ts b/powershell/plugins/llcsharp.ts index a166a31bc64..0d84bd25793 100644 --- a/powershell/plugins/llcsharp.ts +++ b/powershell/plugins/llcsharp.ts @@ -8,14 +8,25 @@ import { join } from 'path'; import { Model } from '../llcsharp/code-model'; import { State } from '../llcsharp/generator'; import { Project } from '../llcsharp/project'; +import { Dictionary } from '@azure-tools/linq'; const resources = `${__dirname}/../../resources`; +function outerTest(service: Host, project: Project, fname: string, content: string) { + service.WriteFile(join(project.apifolder, fname), test(content, project.overrides), undefined, 'source-file-csharp'); +} + +function test(content: string, overrides: Dictionary): string { + const a = applyOverrides(content, overrides); + return a; +} + export async function llcsharp(service: Host) { try { const project = await new Project(service).init(); - await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); + await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), test(content, project.overrides), undefined, 'source-file-csharp')); + await project.writeFiles(async (fname, content) => outerTest(service, project, fname, content)); // recursive copy resources await copyResources(join(resources, 'runtime', 'csharp', 'client'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 90cd2f1bd7b..7ed0a20201e 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -355,6 +355,7 @@ function createVirtualParameters(operation: CommandOperation) { operation.details.default.virtualParameters = virtualParameters; } + async function createVirtuals(state: State): Promise { /* A model class should provide inlined properties for anything in a property called properties @@ -363,16 +364,11 @@ async function createVirtuals(state: State): Promise { Individual models can change the $THRESHOLD for generate */ - // dolauli this plugin is used to expand the property in an object. - // dolauli inline-threshold could be set in readme.md - // skip-for-time-being const threshold = await state.getValue('inlining-threshold', 24); const conflicts = new Array(); for (const schema of values(state.model.schemas.objects)) { - - // did we already inline this object - // dolauli skip if inlined + // did we already inline this objecct if (schema.language.default.inlined) { continue; } diff --git a/powershell/plugins/plugin-tweak-model-azure-v2.ts b/powershell/plugins/plugin-tweak-model-azure-v2.ts new file mode 100644 index 00000000000..6be6d79808e --- /dev/null +++ b/powershell/plugins/plugin-tweak-model-azure-v2.ts @@ -0,0 +1,201 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { keys, length, values } from '@azure-tools/linq'; + +import { Channel, Host } from '@azure-tools/autorest-extension-base'; +import { NewModelState } from '../utils/model-state'; +import { PwshModel } from '../utils/PwshModel'; +import { getAllProperties, ObjectSchema, Response, SchemaType, Schema } from '@azure-tools/codemodel'; +import { serialize } from '@azure-tools/codegen'; +type State = NewModelState; + +const xmsPageable = 'x-ms-pageable'; + +async function tweakModel(state: State): Promise { + 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 values(model.operationGroups)) { + for (const operation of 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 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 === SchemaType.Array) { + operation.language.default.pageable = { + responseType: 'array', + }; + continue; + } + + // if it returns an object, let's see what's inside... + if (schema.type === SchemaType.Object) { + const objSchema = schema as ObjectSchema; + + // does it have a single member that is an array (ie, value : [...]) + if (length(objSchema.properties) === 1 && !objSchema.parents) { + const property = objSchema.properties?.[0]; + if (property) { + if (property.schema.type === 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 (length(objSchema.properties) === 2 && !objSchema.parents) { + const hasNextLink = objSchema.properties?.some((prop) => prop.serializedName === 'nextLink'); + if (hasNextLink) { + const property = objSchema.properties?.find((prop) => prop.serializedName !== 'nextLink'); + if (property) { + if (property.schema.type === 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 values(model.operationGroups)) { + for (const operation of 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 + // delete operation.responses['201']; + // delete operation.responses['202']; + } + } + } + + // 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 values(model.operationGroups)) { + // for (const operation of values(group.operations)) { + // const apiVersions = operation.pathExtensions && operation.pathExtensions['x-ms-metadata'] ? operation.pathExtensions['x-ms-metadata'].apiVersions : undefined; + // for (const parameter of values(operation.parameters)) { + + // if (parameter.name === '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 (length(apiVersions) === 1) { + // parameter.details.default.constantValue = apiVersions[0]; + // continue; + // } + + // // otherwise, the parameter can't have a constant value + // parameter.details.default.constantValue = undefined; + + // // mark it so that we can add profile support in the method generation + // parameter.details.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 values(model.schemas.objects ?? [])) { + // find schemas that have an 'id' and are not readonly + if (values(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 values(group.operations)) { + for (const request of op.requests ?? []) { + + if (request.protocol.http?.method === 'put') { + for (const response of op.responses ?? []) { + // 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; +} + +function getSchema(response: Response): Schema { + return (response).schema; +} + +// Azure version - +// Additional tweaks the code model to adjust things so that the code will generate better. + +export async function tweakModelAzurePluginV2(service: Host) { + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-tweakcodemodelazure-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); +} diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 7712068e4b7..2638fb1c93f 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Property, codeModelSchema, CodeModel, Schema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { Property, codeModelSchema, CodeModel, Schema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize } from '@azure-tools/codegen'; @@ -75,86 +75,108 @@ async function tweakModelV2(state: State): Promise { state.setValue('service-name', serviceName); const model = state.model; + const schemas = model.schemas; + const allSchemas: Schema[] = []; + for (const prop of Object.values(schemas)) { + if (Array.isArray(prop) && prop.length > 0 && prop[0] instanceof Schema) { + allSchemas.push(...prop); + } + } + + // const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); + // universalId.apiVersions = universalId.apiVersions || []; + // state.model.schemas.objects = state.model.schemas.objects || []; + // state.model.schemas.objects.push(universalId); + + model.commands = { + operations: new Dictionary(), + parameters: new Dictionary(), + }; + // we're going to create a schema that represents the distinct sum + // of all operation PATH parameters const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); universalId.apiVersions = universalId.apiVersions || []; state.model.schemas.objects = state.model.schemas.objects || []; - (universalId.language.default).uid = true; + state.model.schemas.objects.push(universalId); - universalId.properties = universalId.properties || new Array(); - const urlParam = new Set(); - for (const operationGroup of values(model.operationGroups)) { - for (const operation of values(operationGroup.operations)) { - for (const param of values(operation.parameters).where(each => each.protocol.http?.in === ParameterLocation.Path)) { + for (const group of values(model.operationGroups)) { + for (const operation of values(group.operations)) { + for (const param of values(operation.parameters).where(each => each.protocol?.http?.in === ParameterLocation.Path)) { const name = param.language.default.name; - - if (!urlParam.has(name)) { - urlParam.add(name); - universalId.addProperty(new Property(name, '', param.schema, { - serializedName: name, language: { - default: { - description: param.summary, - name: name, - required: false, - readOnly: false, - uid: 'universal-parameter:resource identity' - } - } - })); + const hasName = universalId.properties?.findIndex((prop) => prop.language.default.name === name); + if (!hasName) { + if (!universalId.properties) { + universalId.properties = []; + } + const newProp = new Property(name, param.language.default.description, param.schema); + newProp.required = false; + newProp.readOnly = false; + newProp.serializedName = name; + universalId.properties.push(newProp); } } } } if (await state.getValue('azure', false)) { - universalId.addProperty(new Property('id', '', new StringSchema('_identity_type_', 'Resource identity path'), - { - serializedName: 'id', language: { - default: { - description: 'Resource identity path', - name: 'id', - required: false, - readOnly: false, - uid: 'universal-parameter:resource identity' + const idScheam = new Schema('_identity_type_', 'Resource identity path', SchemaType.String); + const idProp = new Property('id', 'Resource identity path', idScheam); + idProp.readOnly = false; + idProp.required = false; + if (!universalId.properties) { + universalId.properties = []; + } + universalId.properties.push(idProp); + } + + // identify models that are polymorphic in nature + for (const schema of allSchemas) { + if (schema instanceof ObjectSchema) { + const objSchema = schema as ObjectSchema; + // if this actual type is polymorphic, make sure we know that. + // parent class + if (objSchema.discriminator) { + objSchema.language.default.isPolymorphic = true; + if (objSchema.children) { + objSchema.language.default.polymorphicChildren = objSchema.children?.all; + } + } + + // sub class + if (objSchema.discriminatorValue) { + objSchema.language.default.discriminatorValue = objSchema.extensions?.['x-ms-discriminator-value']; + } + } + } + + // identify parameters that are constants + for (const group of values(model.operationGroups)) { + for (const operation of values(group.operations)) { + for (const parameter of values(operation.parameters)) { + if (parameter.required && parameter.schema instanceof ChoiceSchema) { + const choiceSchema = parameter.schema as ChoiceSchema; + if (choiceSchema.choices.length === 1) { + parameter.language.default.constantValue = choiceSchema.choices[0].value; } } } - )); + } } - // universalId.properties['id'] = new Property('id', { - // schema: new Schema('_identity_type_', { type: JsonType.String, description: 'Resource identity path' }), - // description: 'Resource identity path', serializedName: 'id', details: { - // default: { - // description: 'Resource identity path', - // name: 'id', - // required: false, - // readOnly: false, - // uid: 'universal-parameter:resource identity' - // } - // } - // }); - - - // if (await state.getValue('azure', false)) { - // universalId.properties['id'] = new Property('id', { - // schema: new Schema('_identity_type_', { type: JsonType.String, description: 'Resource identity path' }), - // description: 'Resource identity path', serializedName: 'id', details: { - // default: { - // description: 'Resource identity path', - // name: 'id', - // required: false, - // readOnly: false, - // uid: 'universal-parameter:resource identity' - // } - // } - // }); - // } - state.model.schemas.objects.push(universalId); - model.commands = { - operations: new Dictionary(), - parameters: new Dictionary(), - }; + // identify properties that are constants + for (const schema of values(schemas.objects)) { + for (const property of values(schema.properties)) { + if (property.required && property.schema instanceof ChoiceSchema) { + const choiceSchema = property.schema as ChoiceSchema; + if (choiceSchema.choices.length === 1) { + // properties with an enum single value are constants + // add the constant value + property.language.default.constantValue = choiceSchema.choices[0].value; + } + } + } + } return model; } diff --git a/powershell/utils/PwshModel.ts b/powershell/utils/PwshModel.ts index bae5a6932e1..2f200bc7df6 100644 --- a/powershell/utils/PwshModel.ts +++ b/powershell/utils/PwshModel.ts @@ -14,4 +14,4 @@ export class PwshModel extends CodeModel { this.apply(initializer); } -} \ No newline at end of file +} From f4fcba8808d871bd8944a92b6bd4d730ee49695f Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 21 Jul 2020 21:40:03 +0800 Subject: [PATCH 09/61] Add azure support for get with an empty response (#634) --- .../llcsharp/model/model-class-serializer.ts | 19 ++++++++++--------- powershell/plugins/plugin-tweak-model.ts | 1 + powershell/plugins/ps-namer-v2.ts | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index 7a6e7b48498..d3d653e3cf7 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -32,7 +32,8 @@ import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -import { getVirtualPropertyName } from './model-class'; +import { getVirtualPropertyName, NewGetVirtualPropertyName } from './model-class'; +import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; export class SerializationPartialClass extends Initializer { constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, protected resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { @@ -273,16 +274,16 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { return function* () { yield '// actually deserialize '; // skip-for-time-being - // for (const virtualProperty of values($this.allVirtualProperties)) { - // // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; - // const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.details.default.required); + for (const virtualProperty of values(>$this.allVirtualProperties)) { + // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; + const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.language.default.required); - // const cvt = type.convertObjectMethod; - // const t = `((${virtualProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - // const tt = type ? `(${type.declaration})` : ''; + const cvt = type.convertObjectMethod; + const t = `((${virtualProperty.originalContainingSchema.language.csharp?.fullInternalInterfaceName})this)`; + const tt = type ? `(${type.declaration})` : ''; - // yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; - // } + yield `${t}.${NewGetVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${NewGetVirtualPropertyName(virtualProperty)}",${t}.${NewGetVirtualPropertyName(virtualProperty)}, ${cvt});`; + } }; } diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 2638fb1c93f..e58c00aec1f 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -98,6 +98,7 @@ async function tweakModelV2(state: State): Promise { const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); universalId.apiVersions = universalId.apiVersions || []; state.model.schemas.objects = state.model.schemas.objects || []; + (universalId.language.default).uid = 'universal-parameter-type'; state.model.schemas.objects.push(universalId); for (const group of values(model.operationGroups)) { diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index 79b536b8fd7..cf926c52af5 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -55,7 +55,7 @@ async function tweakModel(state: State): Promise { // make sure recursively that every details field has csharp for (const { index, instance } of linq.visitor(state.model)) { - if (index === 'details' && instance.default && !instance.csharp) { + if ((index === 'details' || index === 'language') && instance.default && !instance.csharp) { instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); } } From 6a7b1c9595c5b64622061103f3c77481211db6a9 Mon Sep 17 00:00:00 2001 From: Dingmeng Xue <56333063+dingmeng-xue@users.noreply.github.com> Date: Wed, 22 Jul 2020 16:31:04 +0800 Subject: [PATCH 10/61] Add validation script in pipeline (#630) * Add -AllowList * Add scripts and configuration * Add build steps * Change work directory * Enable AutoRestUpgradeTest.ps1. * Add save artifacts task * Revert "Enable AutoRestUpgradeTest.ps1." This reverts commit 66c750d8fa1db81803c3626d97e1d71a8989b107. * Update the script Co-authored-by: Youri --- .azure-pipelines/test-module-upgrade.yml | 38 +- tests-upgrade/AutoRestUpgradeTest.ps1 | 326 +++++++++++++++++- tests-upgrade/Configuration.json | 36 ++ .../basic-disableazure-get/readme.md | 13 + .../basic-disableazure-get/swagger.json | 53 +++ .../basic-disableazure-response/readme.md | 13 + .../basic-disableazure-response/swagger.json | 61 ++++ 7 files changed, 537 insertions(+), 3 deletions(-) create mode 100644 tests-upgrade/Configuration.json create mode 100644 tests-upgrade/basic-disableazure-get/readme.md create mode 100644 tests-upgrade/basic-disableazure-get/swagger.json create mode 100644 tests-upgrade/basic-disableazure-response/readme.md create mode 100644 tests-upgrade/basic-disableazure-response/swagger.json diff --git a/.azure-pipelines/test-module-upgrade.yml b/.azure-pipelines/test-module-upgrade.yml index 1f684e35fc8..e128344281b 100644 --- a/.azure-pipelines/test-module-upgrade.yml +++ b/.azure-pipelines/test-module-upgrade.yml @@ -3,6 +3,11 @@ pool: demands: npm steps: +- task: NodeTool@0 + displayName: 'Use Node 10.16.0' + inputs: + versionSpec: 10.16.0 + - task: Npm@1 displayName: 'Install autorest@beta' inputs: @@ -10,10 +15,39 @@ steps: verbose: false customCommand: 'install -g "@autorest/autorest"' +- task: Npm@1 + displayName: 'Install @microsoft/rush' + inputs: + command: custom + verbose: false + customCommand: 'install -g @microsoft/rush@5.12.0' + +- task: CmdLine@2 + displayName: 'Rush sync-versions' + inputs: + script: 'rush sync-versions' + +- task: CmdLine@2 + displayName: 'Rush Update' + inputs: + script: 'rush update' + +- task: CmdLine@2 + displayName: 'Rush Rebuild' + inputs: + script: 'rush rebuild' + - task: PowerShell@2 displayName: Verify Upgrade inputs: targetType: inline - script: './AutoRestUpgradeTest.ps1 -Configuration' + script: './AutoRestUpgradeTest.ps1 -AllowList' workingDirectory: 'tests-upgrade' - failOnStderr: true \ No newline at end of file + failOnStderr: true + +- task: PublishPipelineArtifact@0 + displayName: 'Save artifacts' + inputs: + artifactName: CompareResult + targetPath: tests-upgrade\CompareResult + condition: succeededOrFailed() \ No newline at end of file diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index 21b6ac00801..c5d01e21166 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -1 +1,325 @@ -Write-Host "Hello" \ No newline at end of file +param([switch]$Generate,[string]$TestName,[switch]$SourceVersion,[switch]$TargetVersion,[switch]$AllowList,[switch]$BlackList) +#Need to use the right version of node.js +#nvs use 10.16.0 +#Create folder to save Compare Results +New-Item CompareResult -ItemType "directory" +#Define the global param 'isError' to determine wheather throw the error +$global:isError = $false +#Import the Configuration Json +$conf = (Get-Content 'Configuration.json') | ConvertFrom-Json +if($AllowList) +{ + #Get the whiteList from json + $whiteList = $conf.WhiteList +} +if($BlackList) +{ + #Get the blackList from json + $blackTestList = $conf.BlackList +} + +#Determine whether the difference is command +function IsCommand([Object]$SourceFile , [Object]$TargetFile) +{ + $isCommandResult = $True + $difference = Compare-Object $SourceFile $TargetFile + foreach($line in $difference) + { + $lineInfo = $line.InputObject.Replace(' ','') + $lineCompareResult =$lineInfo.Startswith('//') + if(!$lineCompareResult) + { + $isCommandResult = $false + break + } + } + return $isCommandResult +} + +#Determine whether the file needs to be ignored +function IsNeedIgnore([string]$inputFileName , [Array]$ignoreArray) +{ + $Ignore = $false + foreach($ignoreDetail in $ignoreArray) + { + if($inputFileName.Startswith($ignoreDetail)) + { + $Ignore =$True + break + } + } + return $Ignore +} + +#Code generation +function GenerateCode() +{ + $GenerateResult=$Ture + #source and generate codes all need to be generated + if((-not $SourceVersion) -and (-not $TargetVersion)) + { + #generate source code + Write-Host -ForegroundColor Green 'M3' + $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.386 --output-folder:.\generate\m3 --Debug | Out-string + #generate target code + Write-Host -ForegroundColor Green 'M4' + $GenerateTargetResult = autorest-beta --use:..\..\ --output-folder:.\generate\m4 --Debug | Out-string + if(!$GenerateSourceResult.Contains('Generation Complete') -or !$GenerateTargetResult.Contains('Generation Complete')) + { + $GenerateResult = $false + } + }elseif($SourceVersion) + { + Write-Host -ForegroundColor Green 'M3' + $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.386 --output-folder:.\generate\m3 --Debug | Out-string + if(!$GenerateSourceResult.Contains('Generation Complete')) + { + $GenerateResult = $false + } + }else + { + Write-Host -ForegroundColor Green 'M4' + $GenerateTargetResult = autorest-beta --use:..\..\ --output-folder:.\generate\m4 --Debug | Out-string + if(!$GenerateTargetResult.Contains('Generation Complete')) + { + $GenerateResult = $false + } + } + return $GenerateResult +} + +#Compare the gap between the two versions +function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath,[string]$testFileName) +{ + #to creare ecah dictionary (the struct is (string,obj)) + #the key is the path of each file,and the obj has two parameters(hashcodevalue,status) + $initialDict = @{} + #in m3Path + cd $inputSourcePath + $initFileList = Get-ChildItem -Recurse -force + $initIgnoreFileList = (($inputSourcePath+'\generated\modules'), ($inputSourcePath+'\.gitignore'),($inputSourcePath+'\tools\Resources\.gitignore')) + $targetIgnoreFileList = (($inputTargetPath+'\generated\modules'), ($inputTargetPath+'\.gitignore'),($inputTargetPath+'\tools\Resources\.gitignore')) + #foreach initFileList and get the hashcode of them + foreach( $initFile in $initFileList) + { + $ignoreResult = IsNeedIgnore -inputFileName $initFile.FullName -ignoreArray $initIgnoreFileList + if(!$ignoreResult) + { + # if(!$initFile.FullName.Startswith($initIgnoreFileList)){ + $obj = "what" | Select-Object -Property HashCode, Status + #if the file is not filefolder + if($initFile.mode -eq '-a---') + { + #get the hashcode of the file + $hashTable = $initFile.PSPath.Replace('Microsoft.PowerShell.Core\FileSystem::','') | get-filehash + # $initFile.FullName + # $hashTable + $obj.HashCode = $hashTable.Hash + #get the path of the file + $detailPath = $hashTable.Path.Replace($inputSourcePath,'') + $initialDict.Add($detailPath,$obj) + } + } + } + $targetDict = @{} + #in TargetPath + cd $inputTargetPath + $targetFileList = Get-ChildItem -Recurse -force + #foreach initFileList and get the hashcode of them + foreach( $targetFile in $targetFileList) + { + $ignoreResult = IsNeedIgnore -inputFileName $targetFile.FullName -ignoreArray $targetIgnoreFileList + if(!$ignoreResult) + { + $obj = "waht2" | Select-Object -Property HashCode, Status + #if the file is not filefolder + if($targetFile.mode -eq '-a---') + { + #get the hashcode of the file + $hashTable = $targetFile.PSPath.Replace('Microsoft.PowerShell.Core\FileSystem::','') | get-filehash + $obj.HashCode = $hashTable.Hash + #get the path of the file + $detailPath = $hashTable.path.Replace($inputTargetPath,'') + $targetDict.Add($detailPath,$obj) + } + } + } + [object[]] $difArray=@() + + #search each dictDetail in targetDict + #the status means: 0 this file do not exist in anouther filefolder + # 1 the hashcode of the file is the same as that in another filefolder + # 2 the hashcode of the file is different from that in another filefolder + foreach($initDictDetail in $initialDict.Keys) + { + $difDetail = "what"| Select-Object -Property fileName,Path,fileFolderName,Status + #if the file not exists in targetDict + if($targetDict[$initDictDetail] -eq $null) + { + $difDetail.Path = $initDictDetail + $difDetail.fileFolderName = 'M3' + $splitStrings = $initDictDetail.Split('\') + $difDetail.fileName = $splitStrings[$splitStrings.count-1] + $difDetail.status = 'lack in M4' + #sign up the status of the file + $initialDict[$initDictDetail].status = 0 + $difArray+= $difDetail + }elseif($targetDict[$initDictDetail].HashCode -ne $initialDict[$initDictDetail].HashCode) + { + $M3CompareFile = Get-Content ($inputSourcePath + $initDictDetail) + $M4CompareFile = Get-Content ($inputTargetPath + $initDictDetail) + $isCommandResult = IsCommand -SourceFile $M3CompareFile -TargetFile $M4CompareFile + if( $isCommandResult -ne $True) + { + $difDetail.Path = $initDictDetail + $difDetail.fileFolderName = 'M3' + $splitStrings = $initDictDetail.Split('\') + $difDetail.fileName = $splitStrings[$splitStrings.count-1] + $difDetail.status = 'different' + #sign up the status of the file + $initialDict[$initDictDetail].status = 2 + $targetDict[$initDictDetail].status = 2 + $difArray+=$difDetail + }else + { + $initialDict[$initDictDetail].status = 1 + $targetDict[$initDictDetail].status = 1 + } + }else + { + $initialDict[$initDictDetail].status = 1 + $targetDict[$initDictDetail].status = 1 + } + } + #search those files which status is null + foreach($targetDetail in $targetDict.Keys) + { + $difDetail = "what"| Select-Object -Property fileName,Path,fileFolderName,Status + if($targetDict[$targetDetail].Status -eq $null) + { + $difDetail.Path = $targetDetail + $difDetail.fileFolderName = 'M4' + $splitStrings = $targetDetail.Split('\') + $difDetail.fileName = $splitStrings[$splitStrings.count-1] + $difDetail.Status = 'lack in m3' + $difArray+=$difDetail + } + } + if($difArray.Count -gt 0) + { + $global:isError=$True + } + #Export the differ csv to the 'CompareResult' folder + $filename = $PSScriptRoot + '\CompareResult\' + $testFileName + (get-date -format 'yyyyMMddhhmmss')+'.csv' + $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Export-CSV -path $filename +} + +$currentPath = Get-Location +$fileList = Get-ChildItem +#if only one case +if($TestName -ne $null -and ($TestName -ne '')) +{ + cd ($PSScriptRoot+'\'+$TestName) + $deatilPath = $PSScriptRoot + 'generate' + try + { + $IsGenerateSuccess = GenerateCode + if(-not $Generate -and $IsGenerateSuccess) + { + $sourceFilePath = $PSScriptRoot +'\'+$TestName + '\generate\m3' + $targetFilePath = $PSScriptRoot +'\'+$TestName + '\generate\m4' + CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $TestName + } + } + catch + { + Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + } +}elseif($AllowList) +{ + #get each testfolder in whiteList + foreach($eachTest in $whiteList) + { + $eachTest + cd ($PSScriptRoot+'\'+$eachTest) + $deatilPath = $PSScriptRoot + 'generate' + try + { + $IsGenerateSuccess = GenerateCode + if(-not $Generate -and $IsGenerateSuccess) + { + $sourceFilePath = $PSScriptRoot +'\'+$eachTest + '\generate\m3' + $targetFilePath = $PSScriptRoot +'\'+$eachTest + '\generate\m4' + CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $eachTest + } + } + catch + { + Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + } + } +}elseif($BlackList) +{ + #get each testfolder and except those tests in blacklist + foreach($fileDetail in $fileList) + { + foreach($blackTestName in $blackTestList) + { + if(($fileDetail.Mode -eq 'd----') -and (!$fileDetail.Name.Startswith($blackTestName))) + { + try + { + cd ($PSScriptRoot+'\'+$fileDetail.Name) + $deatilPath = $PSScriptRoot + 'generate' + $IsGenerateSuccess = GenerateCode + if(-not $Generate -and $IsGenerateSuccess) + { + $sourceFilePath = $PSScriptRoot +'\'+$fileDetail.Name + '\generate\m3' + $targetFilePath = $PSScriptRoot +'\'+$fileDetail.Name + '\generate\m4' + CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDeatil.path + } + } + catch + { + Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + } + } + } + } +} +else +{ + foreach($fileDetail in $fileList) + { + if($fileDetail.Mode -eq 'd----' -and (!$fileDetail.Name.Startswith('Compare'))) + { + $g1 = $PSScriptRoot +'\' +$fileDetail.Name + cd ($PSScriptRoot +'\' +$fileDetail.Name) + $deatilPath = $PSScriptRoot +'\' +$fileDetail.Name + try + { + Write-Host -ForegroundColor Blue $fileDetail.Name + $IsGenerateSuccess = GenerateCode + if(-not $Generate -and $IsGenerateSuccess) + { + $sourceFilePath = $deatilPath + '\generate\m3' + $targetFilePath = $deatilPath + '\generate\m4' + CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDetail.Name + } + } + catch + { + Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + } + } + } +} +cd $PSScriptRoot +#Throw error if there are some different +if($global:isError) +{ + throw 'Error: The code generated by the target file is different from the code generated by the source file.' +}else +{ + Write-Host -ForegroundColor blue 'All generated codes are the same' +} diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json new file mode 100644 index 00000000000..510add0a1fd --- /dev/null +++ b/tests-upgrade/Configuration.json @@ -0,0 +1,36 @@ +{ + "WhiteList": [ + "basic-disableazure-get", + "basic-disableazure-response" + ], + "BlackList": [ + "basic-get-querystr", + "basic-get-delete", + "basic-get-delete-put-patch", + "basic-request-methods", + "basic-get-response-operation", + "basic-response-multioperation", + "basic-response-defaultoperation", + "basic-disableazure-get", + "component-param", + "component-multiparam", + "component-param-remote", + "component--param-localremote", + "component-param-inbody", + "component-definitions-local", + "component-definitions-remote", + "component-definitions-combined", + "datamodels-datatypes-mixedtypes", + "datamodels-datatypes-integer", + "datamodels-datatypes-string", + "datamodels-datatypes-nullable", + "datamodels-datatypes-array", + "datamodels-datatypes-object", + "datamodels-datatypes-file", + "datamodels-datatypes-anytype", + "datamodels-enums", + "datamodels-keyvalue", + "datamodels-combineschema", + "datamodels-inheritpolymorphism" + ] +} \ No newline at end of file diff --git a/tests-upgrade/basic-disableazure-get/readme.md b/tests-upgrade/basic-disableazure-get/readme.md new file mode 100644 index 00000000000..f64f8c74647 --- /dev/null +++ b/tests-upgrade/basic-disableazure-get/readme.md @@ -0,0 +1,13 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md + +azure: false + +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-disableazure-get/swagger.json b/tests-upgrade/basic-disableazure-get/swagger.json new file mode 100644 index 00000000000..ec29bdce647 --- /dev/null +++ b/tests-upgrade/basic-disableazure-get/swagger.json @@ -0,0 +1,53 @@ +{ + + "swagger": "2.0", + "info": { + "title": "AutoRestUpgradeClient", + "version": "2018-04-01", + "description": "ARM AutoRestUpgrade" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "Ok-Return" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-disableazure-response/readme.md b/tests-upgrade/basic-disableazure-response/readme.md new file mode 100644 index 00000000000..f64f8c74647 --- /dev/null +++ b/tests-upgrade/basic-disableazure-response/readme.md @@ -0,0 +1,13 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md + +azure: false + +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-disableazure-response/swagger.json b/tests-upgrade/basic-disableazure-response/swagger.json new file mode 100644 index 00000000000..4e3ddee1c72 --- /dev/null +++ b/tests-upgrade/basic-disableazure-response/swagger.json @@ -0,0 +1,61 @@ +{ + + "swagger": "2.0", + "info": { + "title": "AutoRestUpgradeClient", + "version": "2018-04-01", + "description": "ARM AutoRestUpgrade" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "Ok-Return", + "schema": { + "$ref": "#/definitions/Workspaces" + } + } + } + } + } + }, + "definitions": { + "Workspaces": { + "type": "string" + } + } +} \ No newline at end of file From ff9c6141b592bdc061a45f87f4a249e01707a15d Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 22 Jul 2020 17:09:36 +0800 Subject: [PATCH 11/61] Add support for default response and fix an issue related to model (#635) --- powershell/cmdlets/class.ts | 2 +- powershell/llcsharp/operation/method.ts | 4 ++-- powershell/plugins/cs-namer-v2.ts | 15 +++++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index cf021f91903..471b9d41b63 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -1872,7 +1872,7 @@ export class NewCmdletClass extends Class { } // create the response handlers - const responses = [...values(apiCall.responses)]; + const responses = [...values(apiCall.responses), ...values(apiCall.exceptions)]; const callbackMethods = values(responses).toArray().map(each => new LiteralExpression(each.language.csharp?.name || '')); diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 35f9f09ed70..cdc12a501e8 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -356,7 +356,7 @@ export class NewOperationMethod extends Method { // this.addParameter(this.bodyParameter); // } - for (const response of values(this.operation.responses)) { + for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { const responseType = (response).schema ? state.project.modelsNamespace.NewResolveTypeDeclaration(((response).schema), true, state) : null; //skip-for-time-being @@ -887,7 +887,7 @@ export class NewCallMethod extends Method { // add response handlers yield Switch(`${response}.StatusCode`, function* () { - for (const responses of values(opMethod.operation.responses)) { + for (const responses of [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)]) { if (responses.protocol.http?.statusCodes[0] !== 'default') { const responseCode = responses.protocol.http?.statusCodes[0]; // will use enum when it can, fall back to casting int when it can't diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index c39262b7b4f..c4932fe2f83 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -65,17 +65,17 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, // create the namespace if required if (azure) { - const metadata = schema.extensions && schema.extensions['x-ms-metadata']; - if (metadata) { - const apiVersions = | undefined>metadata.apiVersions; - if (apiVersions && length(apiVersions) > 0) { - thisApiversion = minimum(apiVersions); + const versions = [...values(schema.apiVersions).select(v => v.version)]; + if (schema.language.default?.uid !== 'universal-parameter-type') { + if (versions && length(versions) > 0) { + thisApiversion = minimum(versions); thisNamespace = subNamespace.get(thisApiversion) || new Set(); subNamespace.set(thisApiversion, thisNamespace); } } } + // for each schema, we're going to set the name // to the suggested name, unless we have collisions // at which point, we're going to add a number (for now?) @@ -195,7 +195,9 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso }; } - for (const rsp of values(operation.responses)) { + const responses = [...values(operation.responses), ...values(operation.exceptions)]; + + for (const rsp of responses) { // per responseCode const response = rsp; const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state) : undefined; @@ -205,6 +207,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso if (response.protocol.http?.statusCodes[0] === 'default' || rawValue === 'default' || '') { rawValue = 'any response code not handled elsewhere'; code = 'default'; + response.language.default.isErrorResponse = true; } response.language.csharp = { ...response.language.default, From edefc7497d469363b0d809d575d9c8da9264c2f1 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Thu, 23 Jul 2020 12:24:41 +0800 Subject: [PATCH 12/61] enable the test cases basic-get and basic-get-delete (#636) --- powershell/cmdlets/class.ts | 2 +- tests-upgrade/Configuration.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 471b9d41b63..8b550336221 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -2695,7 +2695,7 @@ export class NewCmdletClass extends Class { // if any response does not return, // the cmdlet should have a PassThru parameter shouldAddPassThru = shouldAddPassThru || values(operation.callGraph) - .selectMany(httpOperation => values(httpOperation.responses)) + .selectMany(httpOperation => values((httpOperation.responses || []).concat(httpOperation.exceptions || []))) //.selectMany(responsesItem => responsesItem.value) .any(value => (value).schema === undefined); if (outputTypes.size === 0) { diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 510add0a1fd..c684cc1bfa4 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -1,7 +1,9 @@ { "WhiteList": [ "basic-disableazure-get", - "basic-disableazure-response" + "basic-disableazure-response", + "basic-get", + "basic-get-delete" ], "BlackList": [ "basic-get-querystr", From 66018948bce24971264a0cd83442ecdd65332b6d Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 24 Jul 2020 10:08:32 +0800 Subject: [PATCH 13/61] Add another 9 test cases that has been supported (#638) --- tests-upgrade/Configuration.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index c684cc1bfa4..f52c7cbf054 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -3,7 +3,16 @@ "basic-disableazure-get", "basic-disableazure-response", "basic-get", - "basic-get-delete" + "basic-get-delete", + "basic-get-delete-put-patch", + "basic-get-response-operation", + "basic-response-multioperation", + "basic-spec-required", + "basic-spec-root", + "component-definitions-local", + "component-param", + "datamodels-datatypes-array", + "datamodels-datatypes-integer" ], "BlackList": [ "basic-get-querystr", From e400979d78c58c52d730af74fc9ff0d19d220336 Mon Sep 17 00:00:00 2001 From: Youri970410 <62531040+Youri970410@users.noreply.github.com> Date: Fri, 24 Jul 2020 17:11:55 +0800 Subject: [PATCH 14/61] Change the script (#639) --- tests-upgrade/AutoRestUpgradeTest.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index c5d01e21166..aaaad9bab70 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -54,7 +54,7 @@ function IsNeedIgnore([string]$inputFileName , [Array]$ignoreArray) #Code generation function GenerateCode() { - $GenerateResult=$Ture + $GenerateResult=$True #source and generate codes all need to be generated if((-not $SourceVersion) -and (-not $TargetVersion)) { @@ -208,10 +208,10 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, if($difArray.Count -gt 0) { $global:isError=$True + #Export the differ csv to the 'CompareResult' folder + $filename = $PSScriptRoot + '\CompareResult\' + $testFileName + (get-date -format 'yyyyMMddhhmmss')+'.csv' + $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Export-CSV -path $filename } - #Export the differ csv to the 'CompareResult' folder - $filename = $PSScriptRoot + '\CompareResult\' + $testFileName + (get-date -format 'yyyyMMddhhmmss')+'.csv' - $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Export-CSV -path $filename } $currentPath = Get-Location From 266cb927717e1893a83551cd190de64b706ee35d Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 24 Jul 2020 17:18:24 +0800 Subject: [PATCH 15/61] Update test-module-upgrade.yml --- .azure-pipelines/test-module-upgrade.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/test-module-upgrade.yml b/.azure-pipelines/test-module-upgrade.yml index e128344281b..20bcf7ebdb5 100644 --- a/.azure-pipelines/test-module-upgrade.yml +++ b/.azure-pipelines/test-module-upgrade.yml @@ -39,6 +39,7 @@ steps: - task: PowerShell@2 displayName: Verify Upgrade + pwsh: true inputs: targetType: inline script: './AutoRestUpgradeTest.ps1 -AllowList' @@ -50,4 +51,4 @@ steps: inputs: artifactName: CompareResult targetPath: tests-upgrade\CompareResult - condition: succeededOrFailed() \ No newline at end of file + condition: succeededOrFailed() From 359123e64e78dabee621264bb0cc9175f039a438 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 24 Jul 2020 17:38:39 +0800 Subject: [PATCH 16/61] Update test-module-upgrade.yml, should use core instead of window powershell for pipeline --- .azure-pipelines/test-module-upgrade.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.azure-pipelines/test-module-upgrade.yml b/.azure-pipelines/test-module-upgrade.yml index 20bcf7ebdb5..b491241b6ba 100644 --- a/.azure-pipelines/test-module-upgrade.yml +++ b/.azure-pipelines/test-module-upgrade.yml @@ -37,14 +37,10 @@ steps: inputs: script: 'rush rebuild' -- task: PowerShell@2 - displayName: Verify Upgrade - pwsh: true - inputs: - targetType: inline - script: './AutoRestUpgradeTest.ps1 -AllowList' - workingDirectory: 'tests-upgrade' - failOnStderr: true +- pwsh: | + ./AutoRestUpgradeTest.ps1 -AllowList + workingDirectory: 'tests-upgrade' + displayName: 'Verify Upgrad' - task: PublishPipelineArtifact@0 displayName: 'Save artifacts' From 1c9806ffeac1293d374901beba74c47467c076e7 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 27 Jul 2020 12:56:57 +0800 Subject: [PATCH 17/61] Remove unpassed cases and upgrade codemodel dependency (#641) --- powershell/package.json | 4 ++-- tests-upgrade/Configuration.json | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/powershell/package.json b/powershell/package.json index 62b74a21d72..73432b459e5 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -58,7 +58,7 @@ "@azure-tools/codegen": "~2.1.0", "@azure-tools/codegen-csharp": "~3.0.0", "@azure-tools/codemodel-v3": "~3.1.0", - "@azure-tools/codemodel": "~4.13.327", + "@azure-tools/codemodel": "~4.13.342", "@azure-tools/autorest-extension-base": "~3.1.0", "@azure-tools/linq": "~3.1.0", "@azure-tools/tasks": "~3.0.0", @@ -66,4 +66,4 @@ "source-map-support": "0.5.13", "xmlbuilder": "10.1.1" } -} +} \ No newline at end of file diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index f52c7cbf054..02c76ec53fe 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -9,10 +9,7 @@ "basic-response-multioperation", "basic-spec-required", "basic-spec-root", - "component-definitions-local", - "component-param", - "datamodels-datatypes-array", - "datamodels-datatypes-integer" + "datamodels-datatypes-array" ], "BlackList": [ "basic-get-querystr", From 373573fd3102c504ba82fd63a1380fde7386c23d Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 28 Jul 2020 09:14:08 +0800 Subject: [PATCH 18/61] support request body (#637) * support request body * fix query parameter and no-requried parameter * fix readonly * fix diff between m3 and m4 Co-authored-by: xichen --- powershell/autorest-configuration.md | 7 +- powershell/cmdlets/class.ts | 207 +++++++++--------- powershell/cmdlets/namespace.ts | 2 +- powershell/llcsharp/model/model-class.ts | 2 +- powershell/llcsharp/operation/method.ts | 67 +++--- powershell/llcsharp/operation/parameter.ts | 62 +++++- powershell/llcsharp/schema/schema-resolver.ts | 11 +- powershell/main.ts | 2 + powershell/module/module-class.ts | 3 +- powershell/plugins/add-azure-completers-v2.ts | 50 +++++ powershell/plugins/create-commands-v2.ts | 3 +- powershell/plugins/cs-namer-v2.ts | 2 + .../plugin-create-inline-properties.ts | 10 +- .../plugins/plugin-tweak-model-azure-v2.ts | 56 ++--- powershell/plugins/plugin-tweak-model.ts | 12 +- powershell/plugins/ps-namer-v2.ts | 2 +- 16 files changed, 314 insertions(+), 184 deletions(-) create mode 100644 powershell/plugins/add-azure-completers-v2.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 5d5c8d8ec61..076d7cb7f65 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -137,11 +137,14 @@ pipeline: psnamer-v2: input: csnamer-v2 - llcsharp-v2: + add-azure-completers-v2: input: psnamer-v2 + + llcsharp-v2: + input: add-azure-completers-v2 powershell-v2: - input: psnamer-v2 + input: add-azure-completers-v2 # --- extension powershell --- # creates high-level commands diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 8b550336221..819ecbe673d 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -1592,23 +1592,29 @@ export class NewCmdletClass extends Class { public get headerComment(): string { const header = super.headerComment; - const ops = ''; + let ops = ''; for (const httpOperation of values(this.operation.callGraph)) { - // ops = `${ops}\n[OpenAPI] ${httpOperation.operationId}=>${httpOperation.method.toUpperCase()}:"${httpOperation.path}"`; - // skip-for-time-being - // if (this.debugMode) { - // const m = (httpOperation.extensions && httpOperation.extensions['x-ms-metadata']) || (httpOperation.pathExtensions ? httpOperation.pathExtensions['x-ms-metadata'] : undefined); - // if (m) { - // ops = `${ops}\n [METADATA]\n${serialize(m)}`; - // } - - // ops = `${ops}\n [DETAILS]`; - // ops = `${ops}\n verb: ${this.operation.details.csharp.verb}`; - // ops = `${ops}\n subjectPrefix: ${this.operation.details.csharp.subjectPrefix}`; - // ops = `${ops}\n subject: ${this.operation.details.csharp.subject}`; - // ops = `${ops}\n variant: ${this.operation.details.csharp.name}`; - // } + const request = httpOperation.requests?.[0]; + if (!request) { + continue; + } + const httpMethod = request.protocol.http?.method ?? ''; + const httpPath = request.protocol.http?.path ?? ''; + ops = `${ops}\n[OpenAPI] ${httpOperation.language.default.name}=>${httpMethod.toUpperCase()}:"${httpPath}"`; + if (this.debugMode) { + // x-ms-metadata seems no longer exists + // const m = (httpOperation.extensions && httpOperation.extensions['x-ms-metadata']) || (httpOperation.pathExtensions ? httpOperation.pathExtensions['x-ms-metadata'] : undefined); + // if (m) { + // ops = `${ops}\n [METADATA]\n${serialize(m)}`; + // } + + ops = `${ops}\n [DETAILS]`; + ops = `${ops}\n verb: ${this.operation.details.csharp.verb}`; + ops = `${ops}\n subjectPrefix: ${this.operation.details.csharp.subjectPrefix}`; + ops = `${ops}\n subject: ${this.operation.details.csharp.subject}`; + ops = `${ops}\n variant: ${this.operation.details.csharp.name}`; + } } return ops ? `${header}\n${docComment(xmlize('remarks', ops))}` : header; @@ -1837,7 +1843,7 @@ export class NewCmdletClass extends Class { name: p.language.csharp?.name, param: values($this.properties). where(each => each.metadata.parameterDefinition). - first(each => each.metadata.parameterDefinition.schema === p.schema), + first(each => each.metadata.parameterDefinition.language.csharp?.serializedName === p.language.csharp?.serializedName), // xichen: Is it safe enough to use serializedName? isPathParam: $this.isViaIdentity && p.protocol.http?.in === ParameterLocation.Path }; @@ -2086,72 +2092,71 @@ export class NewCmdletClass extends Class { const actualCall = function* () { yield $this.eventListener.signal(Events.CmdletBeforeAPICall); const idOpParams = operationParameters.filter(each => !each.isPathParam); - // skip-for-time-being, viaidentity - // const idschema = values($this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - - - // if ($this.isViaIdentity) { - // const identityFromPathParams = function* () { - // yield '// try to call with PATH parameters from Input Object'; - - // if (idschema) { - // const allVPs = getAllPublicVirtualProperties(idschema.details.csharp.virtualProperties); - // const props = [...values(idschema.properties)]; - - // const idOpParams = operationParameters.map(each => { - // const pascalName = pascalCase(`${each.name}`); - - // if (!each.isPathParam) { - // return { - // name: undefined, - // value: valueOf(each.expression) - // }; - // } - // const match = props.find(p => pascalCase(p.serializedName) === pascalName); - // if (match) { - - // const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType; - // // match up vp name - // const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName); - // if (vp) { - // return { - // name: `InputObject.${vp.name}`, - // value: `InputObject.${vp.name} ?? ${defaultOfType}` - // }; - // } - // // fall back! - - // console.error(`Unable to match identity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalCase(match.details.csharp.name)}').`); - // return { - // name: `InputObject.${pascalCase(match.details.csharp.name)}`, - // value: `InputObject.${pascalCase(match.details.csharp.name)} ?? ${defaultOfType}` - // }; - // } - // console.error(`Unable to match idenity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalName}')`); - // return { - // name: `InputObject.${pascalName}`, - // value: `InputObject.${pascalName}` - // }; - // }); - // for (const opParam of idOpParams) { - // if (opParam.name) { - // yield If(IsNull(opParam.name), `ThrowTerminatingError( new ${ErrorRecord}(new global::System.Exception("InputObject has null value for ${opParam.name}"),string.Empty, ${ErrorCategory('InvalidArgument')}, InputObject) );`); - // } - // } - // yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...idOpParams.map(each => toExpression(each.value)), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - - // } - // }; - - // if (idschema && values(idschema.properties).first(each => each.details.csharp.uid === 'universal-parameter:resource identity')) { - // yield If('InputObject?.Id != null', `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}ViaIdentity`, ...[toExpression('InputObject.Id'), ...idOpParams.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`); - // yield Else(identityFromPathParams); - // } else { - // yield identityFromPathParams; - // } - // } else { - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}`, ...[...operationParameters.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - //} + const idschema = values($this.state.project.model.schemas.objects).first(each => each.language.default.uid === 'universal-parameter-type'); + + + if ($this.isViaIdentity) { + const identityFromPathParams = function* () { + yield '// try to call with PATH parameters from Input Object'; + + if (idschema) { + const allVPs = NewGetAllPublicVirtualProperties(idschema.language.csharp?.virtualProperties); + const props = [...values(idschema.properties)]; + + const idOpParams = operationParameters.map(each => { + const pascalName = pascalCase(`${each.name}`); + + if (!each.isPathParam) { + return { + name: undefined, + value: valueOf(each.expression) + }; + } + const match = props.find(p => pascalCase(p.serializedName) === pascalName); + if (match) { + + const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType; + // match up vp name + const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName); + if (vp) { + return { + name: `InputObject.${vp.name}`, + value: `InputObject.${vp.name} ?? ${defaultOfType}` + }; + } + // fall back! + + console.error(`Unable to match identity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalCase(match.language.csharp?.name ?? '')}').`); + return { + name: `InputObject.${pascalCase(match.language.csharp?.name ?? '')}`, + value: `InputObject.${pascalCase(match.language.csharp?.name ?? '')} ?? ${defaultOfType}` + }; + } + console.error(`Unable to match idenity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalName}')`); + return { + name: `InputObject.${pascalName}`, + value: `InputObject.${pascalName}` + }; + }); + for (const opParam of idOpParams) { + if (opParam.name) { + yield If(IsNull(opParam.name), `ThrowTerminatingError( new ${ErrorRecord}(new global::System.Exception("InputObject has null value for ${opParam.name}"),string.Empty, ${ErrorCategory('InvalidArgument')}, InputObject) );`); + } + } + yield `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}`, ...[...idOpParams.map(each => toExpression(each.value)), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + + } + }; + + if (idschema && values(idschema.properties).first(each => each.language.csharp?.uid === 'universal-parameter:resource identity')) { + yield If('InputObject?.Id != null', `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}ViaIdentity`, ...[toExpression('InputObject.Id'), ...idOpParams.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`); + yield Else(identityFromPathParams); + } else { + yield identityFromPathParams; + } + } else { + yield `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}`, ...[...operationParameters.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + } yield $this.eventListener.signal(Events.CmdletAfterAPICall); }; @@ -2505,19 +2510,18 @@ export class NewCmdletClass extends Class { } } - // skip-for-time-being - // if (this.isViaIdentity) { - // // add in the pipeline parameter for the identity - - // const idschema = values(this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - // const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state); - // const idParam = this.add(new BackedProperty('InputObject', idtd, { - // description: 'Identity Parameter' - // })); - // const parameters = [new LiteralExpression('Mandatory = true'), new LiteralExpression('HelpMessage = "Identity Parameter"'), new LiteralExpression('ValueFromPipeline = true')]; - // idParam.add(new Attribute(ParameterAttribute, { parameters })); - // idParam.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Path`] })); - // } + if (this.isViaIdentity) { + // add in the pipeline parameter for the identity + + const idschema = values(this.state.project.model.schemas.objects).first(each => each.language.default.uid === 'universal-parameter-type'); + const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state); + const idParam = this.add(new BackedProperty('InputObject', idtd, { + description: 'Identity Parameter' + })); + const parameters = [new LiteralExpression('Mandatory = true'), new LiteralExpression('HelpMessage = "Identity Parameter"'), new LiteralExpression('ValueFromPipeline = true')]; + idParam.add(new Attribute(ParameterAttribute, { parameters })); + idParam.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Path`] })); + } for (const vParam of values(vps.operation)) { if (vParam.name === 'Host') { // skip 'Host' @@ -2576,7 +2580,7 @@ export class NewCmdletClass extends Class { regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); } - NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, origin.details.default.name); + NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required ?? false, false, vParam.description, origin.details.default.serializedName); NewAddCompleterInfo(regularCmdletParameter, vParam); addDefaultInfo(regularCmdletParameter, vParam); @@ -2588,12 +2592,13 @@ export class NewCmdletClass extends Class { const httpParam = origin.details.csharp.httpParameter; //const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; - const cat = values(operation.callGraph[0].parameters). - where(each => !(each.language.csharp?.constantValue)). - first(each => each.schema === httpParam.schema); + if (httpParam) { + // xichen: Is it safe to compare by csharp serializedName? Because we no longer have uid + const cat = operation.callGraph[0].parameters?.find((param) => !param.language.csharp?.constantValue && param.language.csharp?.serializedName === httpParam.language.csharp?.serializedName); - if (cat) { - regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase((cat.protocol.http?.in))}`] })); + if (cat) { + regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase((cat.protocol.http?.in))}`] })); + } } diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index b215bb3eb70..0be43177733 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -41,7 +41,7 @@ export class NewCmdletNamespace extends Namespace { return this.state.project.cmdletFolder; } - constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { super('Cmdlets', parent); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index e528249edd8..6fbf72d0312 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -697,7 +697,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { initializer: actualProperty.language.csharp?.constantValue ? typeof actualProperty.language.csharp.constantValue === 'string' ? new StringExpression(actualProperty.language.csharp.constantValue) : new LiteralExpression(actualProperty.language.csharp.constantValue) : undefined }); - if (actualProperty.language.csharp?.readOnly) { + if (actualProperty.language.csharp?.readOnly || actualProperty.readOnly) { myProperty.set = undefined; } myProperty.language = virtualProperty.property.language; diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index cdc12a501e8..a1db05fac8e 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -25,7 +25,7 @@ import { Local, LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { HttpOperation, Schema } from '../code-model'; import { State, NewState } from '../generator'; -import { CallbackParameter, NewCallbackParameter, OperationBodyParameter, OperationParameter, NewOperationParameter } from '../operation/parameter'; +import { CallbackParameter, NewCallbackParameter, OperationBodyParameter, OperationParameter, NewOperationParameter, NewOperationBodyParameter } from '../operation/parameter'; import { isMediaTypeJson, isMediaTypeXml, KnownMediaType, knownMediaType, normalizeMediaType, parseMediaType } from '@azure-tools/codemodel-v3'; import { ClassType, dotnet, System } from '@azure-tools/codegen-csharp'; @@ -292,7 +292,7 @@ export class OperationMethod extends Method { export class NewOperationMethod extends Method { public methodParameters: Array; - public bodyParameter?: OperationBodyParameter; + public bodyParameter?: NewOperationBodyParameter; public contextParameter!: Parameter; public senderParameter!: Parameter; public resourceUri!: Parameter; @@ -347,14 +347,16 @@ export class NewOperationMethod extends Method { // add body paramter if there should be one. // skip-for-time-being - // if (this.operation.requestBody) { - // // this request does have a request body. - // this.bodyParameter = new OperationBodyParameter(this, 'body', this.operation.requestBody.description || '', this.operation.requestBody.schema, this.operation.requestBody.required, this.state.path('requestBody'), { - // mediaType: knownMediaType(this.operation.requestBody.contentType), - // contentType: this.operation.requestBody.contentType - // }); - // this.addParameter(this.bodyParameter); - // } + if (this.operation.requests && this.operation.requests.length && this.operation.requests[0].parameters && this.operation.requests[0].parameters.length) { + // this request does have a request body. + const param = this.operation.requests[0].parameters[0]; + this.bodyParameter = new NewOperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { + // TODO: temp solution. We need a class like NewKnowMediaType + mediaType: knownMediaType(KnownMediaType.Json), + contentType: KnownMediaType.Json + }); + this.addParameter(this.bodyParameter); + } for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { @@ -380,11 +382,10 @@ export class NewOperationMethod extends Method { // For post API, Some URI may contain an action string .e.x '/start' at the end // of the URI, for such cases, we will drop the action string if identityCorrection // is set in the configuration - // skip-for-time-being - // if (this.operation.method === 'post' && this.state.project.identityCorrection) { - // const idx = rx.lastIndexOf('/'); - // rx = rx.substr(0, idx); - // } + if (this.operation.requests && this.operation.requests.length && this.operation.requests[0].protocol.http?.method === 'post' && this.state.project.identityCorrection) { + const idx = rx.lastIndexOf('/'); + rx = rx.substr(0, idx); + } let url = `${baseUrl}/${rx.startsWith('/') ? rx.substr(1) : rx}`; @@ -398,12 +399,11 @@ export class NewOperationMethod extends Method { const cookieParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Cookie); // replace any server params in the uri - // skip-for-time-being - // for (const pp of serverParams) { - // url = url.replace(`{${pp.param.name}}`, `" - // + ${pp.name} - // + "`); - // } + for (const pp of serverParams) { + url = url.replace(`{${pp.param.language.default.name}}`, `" + + ${pp.name} + + "`); + } for (const pp of pathParams) { rx = rx.replace(`{${pp.param.language.default.name}}`, `(?<${pp.param.language.default.name}>[^/]+)`); @@ -448,7 +448,7 @@ export class NewOperationMethod extends Method { initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( "${url}" ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${newRemoveEncoding(pp, pp.param.language.default.name, KnownMediaType.QueryParameter)}`, ` + + ${newRemoveEncoding(pp, pp.param.language.default.serializedName, KnownMediaType.QueryParameter)}`, ` + "&"` )} ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) @@ -466,18 +466,17 @@ export class NewOperationMethod extends Method { yield eventListener.signal(ClientRuntime.Events.RequestCreated, urlV.value); yield EOL; - // skip-for-time-being - // if (length(headerParams) > 0) { - // yield '// add headers parameters'; - // for (const hp of headerParams) { - // if (hp.param.name === 'Content-Length') { - // // content length is set when the request body is set - // continue; - // } - // yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.name, ClientRuntime.SerializationMode.None); - // } - // yield EOL; - // } + if (length(headerParams) > 0) { + yield '// add headers parameters'; + for (const hp of headerParams) { + if (hp.param.language.default.name === 'Content-Length') { + // content length is set when the request body is set + continue; + } + yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.default.name, ClientRuntime.SerializationMode.None); + } + yield EOL; + } yield eventListener.signal(ClientRuntime.Events.HeaderParametersAdded, urlV.value); if (bp) { diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index 77daa09a41d..ea6f207eaa3 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Method } from '@azure-tools/codegen-csharp'; -import { Parameter as NewHttpOperationParameter } from '@azure-tools/codemodel'; +import { Parameter as NewHttpOperationParameter, Schema as NewSchema } from '@azure-tools/codemodel'; import { KnownMediaType } from '@azure-tools/codemodel-v3'; import { System } from '@azure-tools/codegen-csharp'; import { Expression, ExpressionOrLiteral } from '@azure-tools/codegen-csharp'; @@ -175,6 +175,66 @@ export class OperationBodyParameter extends Parameter implements EnhancedVariabl } } +export class NewOperationBodyParameter extends Parameter implements EnhancedVariable { + /** emits an expression to deserialize a property from a member inside a container */ + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { + // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)); + return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); + } + + /** emits an expression to deserialze a container as the value itself. */ + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { + // return this.assign(this.typeDeclaration.deserializeFromNode(mediaType, node, this)); + return this.typeDeclaration.deserializeFromNode(mediaType, node, this); + } + + /** emits an expression serialize this to the value required by the container */ + serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { + return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); + } + + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { + return this.typeDeclaration.serializeToContent(mediaType, this, mode); + } + + /** emits the code required to serialize this into a container */ + serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); + } + + public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { + return this.typeDeclaration.validatePresence(eventListener, this); + } + public validationStatement(eventListener: Variable): OneOrMoreStatements { + return this.typeDeclaration.validateValue(eventListener, this); + } + public mediaType: KnownMediaType; + public contentType: string; + + public typeDeclaration: NewEnhancedTypeDeclaration; + + constructor(parent: Method, name: string, description: string, schema: NewSchema, required: boolean, state: NewState, objectInitializer?: DeepPartial) { + const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, required, state.path('schema')); + super(name, typeDeclaration); + this.typeDeclaration = typeDeclaration; + this.mediaType = KnownMediaType.Json; + this.contentType = KnownMediaType.Json; + + this.apply(objectInitializer); + this.description = description || schema.language.csharp?.description || ''; + } + + public get jsonSerializationStatement(): OneOrMoreStatements { + // get the body serialization from the typeDeclaration. + + return '/* body parameter */';// (this.type).jsonserialize(this.name); + } + public get jsonDeserializationStatement(): OneOrMoreStatements { + return '/* body parameter */';// (this.type).jsonDeserializationImplementation(this.name); + } +} + export class CallbackParameter extends Parameter { responseType: (EnhancedTypeDeclaration) | null; headerType: (EnhancedTypeDeclaration) | null; diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index a7ab9d51377..e0094acf4ca 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -214,6 +214,15 @@ export class NewSchemaDefinitionResolver { // fallback to float if the format isn't recognized return new NewNumeric(schema, required, required ? 'float' : 'float?'); + case SchemaType.Constant: + switch ((schema).valueType.type) { + case SchemaType.String: + return new NewEnumImplementation(schema, required); + default: + state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); + throw new Error('Unknown Model. Fatal.'); + } + case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { return new NewEnumImplementation(schema, required); diff --git a/powershell/main.ts b/powershell/main.ts index 9181414f78e..c2764a4af99 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -19,6 +19,7 @@ import { csnamerV2 } from './plugins/cs-namer-v2'; import { namerV2 } from './plugins/ps-namer-v2'; import { llcsharpV2 } from './plugins/llcsharp-v2'; import { powershellV2 } from './plugins/powershell-v2'; +import { addCompleterV2 } from './plugins/add-azure-completers-v2'; require('source-map-support').install(); @@ -38,6 +39,7 @@ export async function main() { pluginHost.Add('create-commands-v2', createCommandsV2); pluginHost.Add('csnamer-v2', csnamerV2); pluginHost.Add('psnamer-v2', namerV2); + pluginHost.Add('add-azure-completers-v2', addCompleterV2); pluginHost.Add('llcsharp-v2', llcsharpV2); pluginHost.Add('powershell-v2', powershellV2); diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index 027e4c56654..8edad8193c6 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; +import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, If, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; import { InvocationInfo, PSCredential, IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, } from '../internal/powershell-declarations'; import { State, NewState } from '../internal/state'; @@ -379,6 +379,7 @@ export class NewModuleClass extends Class { createInitAndPipeline(namespace: Namespace) { const $this = this; + // non-azure init method this.initMethod.add(function* () { yield '// called at module init time...'; diff --git a/powershell/plugins/add-azure-completers-v2.ts b/powershell/plugins/add-azure-completers-v2.ts new file mode 100644 index 00000000000..81b1ac87afb --- /dev/null +++ b/powershell/plugins/add-azure-completers-v2.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { values } from '@azure-tools/linq'; +import { Host } from '@azure-tools/autorest-extension-base'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; +import { serialize } from '@azure-tools/codegen'; + +type State = NewModelState; + +const resourceGroupNames = new Set([ + 'resourcegroupname', + 'resourcegroup', +]); +const subscriptionIdNames = new Set([ + 'subscriptionid', +]); +const locationNames = new Set([ + 'location', +]); + +async function tweakModel(state: State): Promise { + const model = state.model; + for (const operation of values(model.commands.operations)) { + for (const parameter of values(operation.parameters)) { + const parameterName = parameter.details.csharp.name.toLowerCase(); + if (resourceGroupNames.has(parameterName)) { + parameter.details.csharp.completer = 'ResourceGroup'; + } + if (subscriptionIdNames.has(parameterName)) { + parameter.details.csharp.completer = 'SubscriptionId'; + } + if (locationNames.has(parameterName)) { + parameter.details.csharp.completer = 'Location'; + } + // 'Resource' + // 'ResourceId' + } + } + return model; +} + + +export async function addCompleterV2(service: Host) { + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-add-azure-completers-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); +} diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index 7490a1d3b08..aab456f6873 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -406,10 +406,11 @@ export /* @internal */ class Inferrer { const constantParameters = constants.map(each => `'${each.language.default.constantValue}'`); // the body parameter + // xichen: How to handle if has multiple requests? const body = (operation.requests && operation.requests[0].parameters) ? operation.requests[0].parameters[0] : null; // skip-for-time-being, looks x-ms-requestBody-name is not supported any more //const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : ''; - const bodyParameterName = body ? 'bodyParameter' : ''; + const bodyParameterName = body ? body.language.default.name : ''; // all the properties in the body parameter const bodyProperties = (body && body.schema && isObjectSchema(body.schema)) ? values(getAllProperties(body.schema)).where(property => !property.language.default.readOnly).toArray() : []; diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index c4932fe2f83..c3929d5df70 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -26,6 +26,8 @@ function setPropertyNames(schema: Schema) { } for (const propertySchema of values(schema.properties)) { const propertyDetails = propertySchema.language.default; + propertyDetails.required = propertySchema.required ?? false; + propertyDetails.readOnly = propertySchema.readOnly ?? false; const className = schema.language.csharp?.name; diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 7ed0a20201e..07ecf13568c 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -14,6 +14,7 @@ import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; import { VirtualParameter } from '../utils/command-operation'; import { VirtualProperty, getAllProperties, getAllPublicVirtualProperties } from '../utils/schema'; +import { resolveParameterNames } from '../utils/resolve-conflicts'; function getPluralizationService(): EnglishPluralizationService { const result = new EnglishPluralizationService(); @@ -300,8 +301,7 @@ function createVirtualParameters(operation: CommandOperation) { body: new Array() }; - /// const dropBodyParameter = !!operation.details.default.dropBodyParameter; - const dropBodyParameter = false; + const dropBodyParameter = !!operation.details.default.dropBodyParameter; // loop thru the parameters of the command operation, and if there is a body parameter, expand it if necessary. for (const parameter of values(operation.parameters)) { if (parameter.details.default.constantValue) { @@ -320,13 +320,13 @@ function createVirtualParameters(operation: CommandOperation) { if (vps) { for (const virtualProperty of [...vps.inherited, ...vps.owned, ...vps.inlined]) { // dolauli add virtual parameter for virtual property - if (virtualProperty.private || virtualProperty.property.details.default.readOnly || virtualProperty.property.details.default.constantValue !== undefined || virtualProperty.property.details.default.HeaderProperty === 'Header') { + if (virtualProperty.private || virtualProperty.property.readOnly || virtualProperty.property.language.default.constantValue !== undefined || virtualProperty.property.language.default.HeaderProperty === 'Header') { // private or readonly properties aren't needed as parameters. continue; } virtualParameters.body.push({ name: virtualProperty.name, - description: virtualProperty.property.details.default.description, + description: virtualProperty.property.language.default.description, nameOptions: virtualProperty.nameOptions, required: virtualProperty.required, schema: virtualProperty.property.schema, @@ -349,7 +349,7 @@ function createVirtualParameters(operation: CommandOperation) { } } - //resolveParameterNames([], virtualParameters); + resolveParameterNames([], virtualParameters); // dolauli see operation.details.default.virtualParameters operation.details.default.virtualParameters = virtualParameters; diff --git a/powershell/plugins/plugin-tweak-model-azure-v2.ts b/powershell/plugins/plugin-tweak-model-azure-v2.ts index 6be6d79808e..f1e87c034ee 100644 --- a/powershell/plugins/plugin-tweak-model-azure-v2.ts +++ b/powershell/plugins/plugin-tweak-model-azure-v2.ts @@ -125,34 +125,34 @@ async function tweakModel(state: State): Promise { // 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 values(model.operationGroups)) { - // for (const operation of values(group.operations)) { - // const apiVersions = operation.pathExtensions && operation.pathExtensions['x-ms-metadata'] ? operation.pathExtensions['x-ms-metadata'].apiVersions : undefined; - // for (const parameter of values(operation.parameters)) { - - // if (parameter.name === '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 (length(apiVersions) === 1) { - // parameter.details.default.constantValue = apiVersions[0]; - // continue; - // } - - // // otherwise, the parameter can't have a constant value - // parameter.details.default.constantValue = undefined; - - // // mark it so that we can add profile support in the method generation - // parameter.details.default.apiversion = true; - // } - // } - // } - // } - // } + for (const group of values(model.operationGroups)) { + for (const operation of values(group.operations)) { + const apiVersions = operation.apiVersions; + for (const parameter of 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 (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)) { diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index e58c00aec1f..cede952c758 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -83,11 +83,6 @@ async function tweakModelV2(state: State): Promise { } } - // const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); - // universalId.apiVersions = universalId.apiVersions || []; - // state.model.schemas.objects = state.model.schemas.objects || []; - // state.model.schemas.objects.push(universalId); - model.commands = { operations: new Dictionary(), parameters: new Dictionary(), @@ -95,7 +90,9 @@ async function tweakModelV2(state: State): Promise { // we're going to create a schema that represents the distinct sum // of all operation PATH parameters - const universalId = new ObjectSchema(`${serviceName}Identity`, 'Resource Identity'); + const universalId = new ObjectSchema(`${serviceName}Identity`, ''); + // xichen: Add 'universal-parameter-type' in language.default.uid, so that we can find it later + universalId.language.default.uid = 'universal-parameter-type'; universalId.apiVersions = universalId.apiVersions || []; state.model.schemas.objects = state.model.schemas.objects || []; (universalId.language.default).uid = 'universal-parameter-type'; @@ -105,7 +102,7 @@ async function tweakModelV2(state: State): Promise { for (const operation of values(group.operations)) { for (const param of values(operation.parameters).where(each => each.protocol?.http?.in === ParameterLocation.Path)) { const name = param.language.default.name; - const hasName = universalId.properties?.findIndex((prop) => prop.language.default.name === name); + const hasName = universalId.properties?.find((prop) => prop.language.default.name === name); if (!hasName) { if (!universalId.properties) { universalId.properties = []; @@ -125,6 +122,7 @@ async function tweakModelV2(state: State): Promise { const idProp = new Property('id', 'Resource identity path', idScheam); idProp.readOnly = false; idProp.required = false; + idProp.language.default.uid = 'universal-parameter:resource identity'; if (!universalId.properties) { universalId.properties = []; } diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index cf926c52af5..39f28aee11b 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -102,7 +102,7 @@ async function tweakModel(state: State): Promise { // now remove the subject from the beginning of the parameter // to reduce naming redundancy, but just for path parameters // e.g. get-vm -vmname ---> get-vm -name - if ((parameter.origin).in === ParameterLocation.Path) { + if ((parameter.origin).protocol?.http?.in === ParameterLocation.Path) { const sanitizedName = removeProhibitedPrefix( parameter.name, operation.details.csharp.subject, From b1f482cf4916eaf48028cadf0cdc1fb6d0175e19 Mon Sep 17 00:00:00 2001 From: Youri970410 <62531040+Youri970410@users.noreply.github.com> Date: Tue, 28 Jul 2020 10:15:20 +0800 Subject: [PATCH 19/61] Change the AutoRestUpgrade.ps1 for different Powershell version (#642) * Change the script * add script tips * fix the powershell version issue * Fix formatting issues --- tests-upgrade/AutoRestUpgradeTest.ps1 | 47 +++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index aaaad9bab70..1d847ee0d73 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -105,14 +105,13 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, $ignoreResult = IsNeedIgnore -inputFileName $initFile.FullName -ignoreArray $initIgnoreFileList if(!$ignoreResult) { - # if(!$initFile.FullName.Startswith($initIgnoreFileList)){ - $obj = "what" | Select-Object -Property HashCode, Status + #create an object with HashCode, Status + $obj = New-Object psobject | Select-Object -Property HashCode, Status #if the file is not filefolder - if($initFile.mode -eq '-a---') + if(!((Get-Item $initFile.PSPath) -is [System.IO.DirectoryInfo])) { #get the hashcode of the file $hashTable = $initFile.PSPath.Replace('Microsoft.PowerShell.Core\FileSystem::','') | get-filehash - # $initFile.FullName # $hashTable $obj.HashCode = $hashTable.Hash #get the path of the file @@ -131,9 +130,9 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, $ignoreResult = IsNeedIgnore -inputFileName $targetFile.FullName -ignoreArray $targetIgnoreFileList if(!$ignoreResult) { - $obj = "waht2" | Select-Object -Property HashCode, Status + $obj = New-Object psobject | Select-Object -Property HashCode, Status #if the file is not filefolder - if($targetFile.mode -eq '-a---') + if(!((Get-Item $targetFile.PSPath) -is [System.IO.DirectoryInfo])) { #get the hashcode of the file $hashTable = $targetFile.PSPath.Replace('Microsoft.PowerShell.Core\FileSystem::','') | get-filehash @@ -152,7 +151,7 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, # 2 the hashcode of the file is different from that in another filefolder foreach($initDictDetail in $initialDict.Keys) { - $difDetail = "what"| Select-Object -Property fileName,Path,fileFolderName,Status + $difDetail = New-Object psobject | Select-Object -Property fileName,Path,fileFolderName,Status #if the file not exists in targetDict if($targetDict[$initDictDetail] -eq $null) { @@ -194,7 +193,7 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, #search those files which status is null foreach($targetDetail in $targetDict.Keys) { - $difDetail = "what"| Select-Object -Property fileName,Path,fileFolderName,Status + $difDetail = New-Object psobject | Select-Object -Property fileName,Path,fileFolderName,Status if($targetDict[$targetDetail].Status -eq $null) { $difDetail.Path = $targetDetail @@ -208,9 +207,9 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, if($difArray.Count -gt 0) { $global:isError=$True - #Export the differ csv to the 'CompareResult' folder - $filename = $PSScriptRoot + '\CompareResult\' + $testFileName + (get-date -format 'yyyyMMddhhmmss')+'.csv' + $filename = Join-Path $PSScriptRoot 'CompareResult' ($testFileName + (get-date -format 'yyyyMMddhhmmss') + '.csv') $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Export-CSV -path $filename + Write-Warning ('There are ' + $difArray.Count + ' different files') } } @@ -220,14 +219,13 @@ $fileList = Get-ChildItem if($TestName -ne $null -and ($TestName -ne '')) { cd ($PSScriptRoot+'\'+$TestName) - $deatilPath = $PSScriptRoot + 'generate' try { $IsGenerateSuccess = GenerateCode if(-not $Generate -and $IsGenerateSuccess) { - $sourceFilePath = $PSScriptRoot +'\'+$TestName + '\generate\m3' - $targetFilePath = $PSScriptRoot +'\'+$TestName + '\generate\m4' + $sourceFilePath = Join-Path $PSScriptRoot $TestName 'generate\m3' + $targetFilePath = Join-Path $PSScriptRoot $TestName 'generate\m4' CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $TestName } } @@ -242,14 +240,13 @@ if($TestName -ne $null -and ($TestName -ne '')) { $eachTest cd ($PSScriptRoot+'\'+$eachTest) - $deatilPath = $PSScriptRoot + 'generate' try { $IsGenerateSuccess = GenerateCode if(-not $Generate -and $IsGenerateSuccess) { - $sourceFilePath = $PSScriptRoot +'\'+$eachTest + '\generate\m3' - $targetFilePath = $PSScriptRoot +'\'+$eachTest + '\generate\m4' + $sourceFilePath = Join-Path $PSScriptRoot $eachTest 'generate\m3' + $targetFilePath = Join-Path $PSScriptRoot $eachTest 'generate\m4' CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $eachTest } } @@ -265,17 +262,17 @@ if($TestName -ne $null -and ($TestName -ne '')) { foreach($blackTestName in $blackTestList) { - if(($fileDetail.Mode -eq 'd----') -and (!$fileDetail.Name.Startswith($blackTestName))) + + if(((Get-Item $fileDetail.PSPath) -is [System.IO.DirectoryInfo]) -and (!$fileDetail.Name.Startswith($blackTestName))) { try { cd ($PSScriptRoot+'\'+$fileDetail.Name) - $deatilPath = $PSScriptRoot + 'generate' $IsGenerateSuccess = GenerateCode if(-not $Generate -and $IsGenerateSuccess) { - $sourceFilePath = $PSScriptRoot +'\'+$fileDetail.Name + '\generate\m3' - $targetFilePath = $PSScriptRoot +'\'+$fileDetail.Name + '\generate\m4' + $sourceFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m3' + $targetFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m4' CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDeatil.path } } @@ -291,19 +288,19 @@ else { foreach($fileDetail in $fileList) { - if($fileDetail.Mode -eq 'd----' -and (!$fileDetail.Name.Startswith('Compare'))) + if(((Get-Item $fileDetail.PSPath) -is [System.IO.DirectoryInfo]) -and (!$fileDetail.Name.Startswith('Compare'))) { - $g1 = $PSScriptRoot +'\' +$fileDetail.Name + $g1 = Join-Path $PSScriptRoot $fileDetail.Name cd ($PSScriptRoot +'\' +$fileDetail.Name) - $deatilPath = $PSScriptRoot +'\' +$fileDetail.Name + $deatilPath =Join-Path $PSScriptRoot $fileDetail.Name try { Write-Host -ForegroundColor Blue $fileDetail.Name $IsGenerateSuccess = GenerateCode if(-not $Generate -and $IsGenerateSuccess) { - $sourceFilePath = $deatilPath + '\generate\m3' - $targetFilePath = $deatilPath + '\generate\m4' + $sourceFilePath = Join-Path $deatilPath 'generate\m3' + $targetFilePath = Join-Path $deatilPath 'generate\m4' CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDetail.Name } } From 67674b25809b83fce7a4a0f77c22a03908148a36 Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 29 Jul 2020 10:10:51 +0800 Subject: [PATCH 20/61] Support enum (#643) * support enum * fix diff from m3 * llcsharp-v2 should rely on modifiers-v2 Co-authored-by: xichen Co-authored-by: Xiaogang --- powershell/autorest-configuration.md | 7 +- powershell/cmdlets/class.ts | 2 +- powershell/enums/namespace.ts | 202 ++--- powershell/llcsharp/enums/enum.ts | 171 ++++- powershell/llcsharp/model/namespace.ts | 12 +- powershell/llcsharp/operation/method.ts | 12 +- powershell/llcsharp/schema/enum.ts | 4 +- powershell/llcsharp/schema/schema-resolver.ts | 4 +- powershell/llcsharp/schema/string.ts | 33 +- powershell/main.ts | 2 + powershell/plugins/create-commands-v2.ts | 1 + powershell/plugins/cs-namer-v2.ts | 65 +- powershell/plugins/modifiers-v2.ts | 716 ++++++++++++++++++ powershell/plugins/plugin-tweak-model.ts | 4 +- powershell/utils/schema.ts | 12 + tests-upgrade/Configuration.json | 6 +- 16 files changed, 1082 insertions(+), 171 deletions(-) create mode 100644 powershell/plugins/modifiers-v2.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 076d7cb7f65..e146910a3c7 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -137,11 +137,14 @@ pipeline: psnamer-v2: input: csnamer-v2 - add-azure-completers-v2: + modifiers-v2: input: psnamer-v2 + add-azure-completers-v2: + input: modifiers-v2 + llcsharp-v2: - input: add-azure-completers-v2 + input: modifiers-v2 powershell-v2: input: add-azure-completers-v2 diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 819ecbe673d..41c630537af 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -2580,7 +2580,7 @@ export class NewCmdletClass extends Class { regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); } - NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required ?? false, false, vParam.description, origin.details.default.serializedName); + NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required ?? false, false, vParam.description, origin.name); NewAddCompleterInfo(regularCmdletParameter, vParam); addDefaultInfo(regularCmdletParameter, vParam); diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index a3b07985233..8350aad788c 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -10,6 +10,8 @@ import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; +import { EnumDetails as NewEnumDetails } from '../utils/schema'; + export class EnumNamespace extends Namespace { public get outputFolder(): string { return join(this.state.project.apiFolder, 'Support'); @@ -127,104 +129,106 @@ export class NewEnumNamespace extends Namespace { constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); - // skip-for-time-being - // const enumInfos = values(state.model.schemas) - // .where(each => each.details.csharp.enum !== undefined && !each.details.csharp.skip) - // .select(each => ({ details: each.details.csharp.enum, description: each.details.csharp.description })) - // .toArray(); - - // const done = new Set(); - - - // for (const enumInfo of enumInfos) { - // if (done.has(enumInfo.details.name)) { - // continue; - // } - - // done.add(enumInfo.details.name); - - // if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) { - // continue; - // } - - // // generate a typeconverter for the enum class too. - - // const enumValues = values(enumInfo.details.values).select(v => v.value).toArray(); - // const enumClass = new Struct(this, enumInfo.details.name, undefined, { - // interfaces: [IArgumentCompleter], - // partial: true, - // description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`, - // fileName: `${enumInfo.details.name}.Completer` - // }); - // const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' }); - // const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' }); - // const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' }); - // const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' }); - // const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' }); - // const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters]; - - // enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () { - // for (const enumValue of enumValues) { - // yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`, - // `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`); - // } - // }); - - - // // generate a typeconverter for the enum class too. - - // const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, { - // interfaces: [PSTypeConverter], - // partial: true, - // description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`, - // fileName: `${enumInfo.details.name}.TypeConverter` - // }); - - // converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, { - // override: Modifier.Override, - // parameters: [ - // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - // new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - // ], - // description: 'Determines if the converter can convert the parameter to the parameter.', - // returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - // })); - - // converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - // override: Modifier.Override, - // parameters: [ - // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - // new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - // ], - // description: 'Determines if the converter can convert the parameter to the parameter.', - // returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - // })); - - // converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), { - // override: Modifier.Override, - // parameters: [ - // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - // new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - // new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - // new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - // ], - // description: 'Converts the parameter to the parameter using and ', - // returnsDescription: `an instance of , or null if there is no suitable conversion.` - // })); - - // converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - // override: Modifier.Override, - // parameters: [ - // new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - // new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - // new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - // new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - // ], description: 'NotImplemented -- this will return null', - // returnsDescription: 'will always return null.' - // })); - - // enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - - // } + const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] + .filter((choice) => !choice.language.csharp?.skip) + .map((choice) => { + return { + details: choice.language.csharp?.enum, + description: choice.language.csharp?.description + } + }); + + const done = new Set(); + + for (const enumInfo of enumInfos) { + if (done.has(enumInfo.details.name)) { + continue; + } + + done.add(enumInfo.details.name); + + if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) { + continue; + } + + // generate a typeconverter for the enum class too. + + const enumValues = values(enumInfo.details.values).select(v => v.value).toArray(); + const enumClass = new Struct(this, enumInfo.details.name, undefined, { + interfaces: [IArgumentCompleter], + partial: true, + description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`, + fileName: `${enumInfo.details.name}.Completer` + }); + const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' }); + const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' }); + const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' }); + const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' }); + const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' }); + const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters]; + + enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () { + for (const enumValue of enumValues) { + yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`, + `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`); + } + }); + + + // generate a typeconverter for the enum class too. + + const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, { + interfaces: [PSTypeConverter], + partial: true, + description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`, + fileName: `${enumInfo.details.name}.TypeConverter` + }); + + converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + })); + + converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }) + ], + description: 'Determines if the converter can convert the parameter to the parameter.', + returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', + })); + + converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], + description: 'Converts the parameter to the parameter using and ', + returnsDescription: `an instance of , or null if there is no suitable conversion.` + })); + + converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { + override: Modifier.Override, + parameters: [ + new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), + new Parameter('destinationType', System.Type, { description: 'the to convert to' }), + new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), + new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), + ], description: 'NotImplemented -- this will return null', + returnsDescription: 'will always return null.' + })); + + enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); + + } } } \ No newline at end of file diff --git a/powershell/llcsharp/enums/enum.ts b/powershell/llcsharp/enums/enum.ts index e44e8783673..8f4303e708c 100644 --- a/powershell/llcsharp/enums/enum.ts +++ b/powershell/llcsharp/enums/enum.ts @@ -20,11 +20,13 @@ import { Property } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Struct } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; -import { EnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State } from '../generator'; +import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { State, NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; + export class EnumClass extends Struct implements EnhancedTypeDeclaration { implementation: EnumImplementation; get schema(): Schema { @@ -187,3 +189,166 @@ export class EnumClass extends Struct implements EnhancedTypeDeclaration { return this.implementation.validatePresence(eventListener, property); } } + +export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { + implementation: NewEnumImplementation; + get schema(): NewSchema { + return this.implementation.schema; + } + get convertObjectMethod() { + return this.implementation.convertObjectMethod; + } + + get defaultOfType() { + return toExpression('null /* enum value */'); + } + + deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { + return this.implementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); + } + deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { + return this.implementation.deserializeFromNode(mediaType, node, defaultValue); + } + /** emits an expression to deserialize content from a string */ + deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.implementation.deserializeFromString(mediaType, content, defaultValue); + } + /** emits an expression to deserialize content from a content/response */ + deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { + return this.implementation.deserializeFromResponse(mediaType, content, defaultValue); + } + serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { + return this.implementation.serializeToNode(mediaType, value, serializedName, mode); + } + /** emits an expression serialize this to a HttpContent */ + serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { + return this.implementation.serializeToContent(mediaType, value, mode); + } + + serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { + return this.implementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); + } + + get isXmlAttribute(): boolean { + return this.implementation.isXmlAttribute; + } + + get isNullable(): boolean { + return this.implementation.isNullable; + } + + get isRequired(): boolean { + return this.implementation.isRequired; + } + + constructor(schemaWithFeatures: NewEnumImplementation, state: NewState, objectInitializer?: DeepPartial) { + if (!schemaWithFeatures.schema.language.csharp?.enum) { + throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.language.csharp?.name}`); + } + + super(state.project.supportNamespace, schemaWithFeatures.schema.language.csharp?.enum.name, undefined, { + interfaces: [new Interface(new Namespace('System'), 'IEquatable', { + genericParameters: [`${schemaWithFeatures.schema.language.csharp?.enum.name}`] + })], + }); + this.description = schemaWithFeatures.schema.language.csharp?.description; + this.implementation = schemaWithFeatures; + this.partial = true; + + this.apply(objectInitializer); + + // add known enum values + for (const evalue of schemaWithFeatures.schema.language.csharp?.enum.values) { + this.addField(new Field(evalue.name, this, { initialValue: new StringExpression(evalue.value), static: Modifier.Static, description: evalue.description })); + } + + // add backingField + const backingField = this.add(new Property('_value', dotnet.String, { + getAccess: Access.Private, + setAccess: Access.Private, + description: `the value for an instance of the Enum.` + })); + + // add private constructor + const p = new Parameter('underlyingValue', dotnet.String, { description: 'the value to create an instance for.' }); + const ctor = this.addMethod(new Constructor(this, { + access: Access.Private, + parameters: [p], + description: `Creates an instance of the ` + })).add(`this.${backingField.value} = ${p.value};`); + + // add toString Method + this.addMethod(new Method('ToString', dotnet.String, { + override: Modifier.Override, + description: `Returns string representation for ${this.name}`, + returnsDescription: 'A string for this value.' + })).add(`return this.${backingField.value};`); + + // add Equals Method(thistype) + this.addMethod(new Method('Equals', dotnet.Bool, { + description: `Compares values of enum type ${this.name}`, + parameters: [new Parameter('e', this, { description: 'the value to compare against this instance.' })], + returnsDescription: 'true if the two instances are equal to the same value' + })).add(`return ${backingField.value}.Equals(e.${backingField.value});`); + + // add Equals Method(object) + this.addMethod(new Method('Equals', dotnet.Bool, { + override: Modifier.Override, + description: `Compares values of enum type ${this.name} (override for Object)`, + parameters: [new Parameter('obj', dotnet.Object, { description: 'the value to compare against this instance.' })], + returnsDescription: 'true if the two instances are equal to the same value' + })).add(`return obj is ${this.name} && Equals((${this.name})obj);`); + + // add implicit operator(string) + this.addMethod(new Operator(`implicit operator ${this.name}`, { + static: Modifier.Static, + description: `Implicit operator to convert string to ${this.name}`, + parameters: [new Parameter('value', dotnet.String, { description: `the value to convert to an instance of .` })] + })).add(`return new ${this.name}(value);`); + + // add static creation + this.addMethod(new Method('CreateFrom', dotnet.Object, { + static: Modifier.Static, + access: Access.Internal, + description: `Conversion from arbitrary object to ${this.name}`, + parameters: [new Parameter('value', dotnet.Object, { description: `the value to convert to an instance of .` })] + })).add(`return new ${this.name}(System.Convert.ToString(value));`); + + // add implicit operator(thistype) + this.addMethod(new Operator('implicit operator string', { + static: Modifier.Static, + description: `Implicit operator to convert ${this.name} to string`, + parameters: [new Parameter('e', this, { description: `the value to convert to an instance of .` })] + })).add(`return e.${backingField.value};`); + + // add operator == + this.addMethod(new Method('operator ==', dotnet.Bool, { + static: Modifier.Static, + description: `Overriding == operator for enum ${this.name}`, + parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], + returnsDescription: 'true if the two instances are equal to the same value' + })).add('return e2.Equals(e1);'); + + // add opeator != + this.addMethod(new Method('operator !=', dotnet.Bool, { + static: Modifier.Static, + description: `Overriding != operator for enum ${this.name}`, + parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], + returnsDescription: 'true if the two instances are not equal to the same value' + })).add('return !e2.Equals(e1);'); + + // add getHashCode + this.addMethod(new Method('GetHashCode', dotnet.Int, { + override: Modifier.Override, + description: `Returns hashCode for enum ${this.name}`, + returnsDescription: 'The hashCode of the value' + })).add(`return this.${backingField.value}.GetHashCode();`); + } + + public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.implementation.validateValue(eventListener, property); + } + public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { + return this.implementation.validatePresence(eventListener, property); + } +} \ No newline at end of file diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index c651d1befb2..a437aa8ce57 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -13,7 +13,7 @@ import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../schema/schema-resolver'; -import { EnumClass } from '../enums/enum'; +import { EnumClass, NewEnumClass } from '../enums/enum'; import * as validation from '../validations'; import { ModelInterface, NewModelInterface } from './interface'; import { ModelClass, NewModelClass } from './model-class'; @@ -146,9 +146,8 @@ export class ModelsNamespace extends Namespace { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { - // skip-for-time-being - //new EnumClass(td, state); - // return schema.details.csharp.typeDeclaration = ec[0]; + new NewEnumClass(td, state); + // return schema.language.csharp.typeDeclaration = ec[0]; } } schema.language.csharp = schema.language.csharp || new Language(); @@ -223,9 +222,8 @@ export class NewModelsNamespace extends Namespace { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { - // skip-for-time-being - //new EnumClass(td, state); - // return schema.details.csharp.typeDeclaration = ec[0]; + new NewEnumClass(td, state); + // return schema.language.csharp.typeDeclaration = ec[0]; } } schema.language.csharp = schema.language.csharp || new Language(); diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index a1db05fac8e..bf7a4d05bfa 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -400,20 +400,20 @@ export class NewOperationMethod extends Method { // replace any server params in the uri for (const pp of serverParams) { - url = url.replace(`{${pp.param.language.default.name}}`, `" + url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + ${pp.name} + "`); } for (const pp of pathParams) { - rx = rx.replace(`{${pp.param.language.default.name}}`, `(?<${pp.param.language.default.name}>[^/]+)`); + rx = rx.replace(`{${pp.param.language.csharp?.name}}`, `(?<${pp.param.language.csharp?.name}>[^/]+)`); if (this.viaIdentity) { - url = url.replace(`{${pp.param.language.default.name}}`, `" + url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + ${pp.name} + "`); } else { - url = url.replace(`{${pp.param.language.default.name}}`, `" + url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + ${newRemoveEncoding(pp, '', KnownMediaType.UriParameter)} + "`); } @@ -439,7 +439,7 @@ export class NewOperationMethod extends Method { yield EOL; yield '// replace URI parameters with values from identity'; for (const pp of pathParams) { - yield `var ${pp.name} = ${match.value}.Groups["${pp.param.language.default.name}"].Value;`; + yield `var ${pp.name} = ${match.value}.Groups["${pp.param.language.csharp?.name}"].Value;`; } } @@ -473,7 +473,7 @@ export class NewOperationMethod extends Method { // content length is set when the request body is set continue; } - yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.default.name, ClientRuntime.SerializationMode.None); + yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.csharp?.name || hp.param.language.default.name, ClientRuntime.SerializationMode.None); } yield EOL; } diff --git a/powershell/llcsharp/schema/enum.ts b/powershell/llcsharp/schema/enum.ts index fdd7f4d1088..bf80b84f77e 100644 --- a/powershell/llcsharp/schema/enum.ts +++ b/powershell/llcsharp/schema/enum.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Schema } from '../code-model'; -import { StringSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema } from '@azure-tools/codemodel'; import { String, NewString } from './string'; import { dotnet, toExpression } from '@azure-tools/codegen-csharp'; @@ -36,7 +36,7 @@ export class NewEnumImplementation extends NewString { return !this.isRequired; } - constructor(schema: StringSchema, isRequired: boolean) { + constructor(schema: NewSchema, isRequired: boolean) { super(schema, isRequired); } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index e0094acf4ca..e175248d98e 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -222,7 +222,9 @@ export class NewSchemaDefinitionResolver { state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); throw new Error('Unknown Model. Fatal.'); } - + case SchemaType.Choice: + case SchemaType.SealedChoice: + return new NewEnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { return new NewEnumImplementation(schema, required); diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index 110a9d4ee46..8d8316e78fe 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -12,7 +12,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Schema as NewSchema, StringSchema } from '@azure-tools/codemodel'; +import { ChoiceSchema, Schema as NewSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; @@ -354,7 +354,7 @@ export class NewString implements NewEnhancedTypeDeclaration { return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); } - constructor(public schema: StringSchema, public isRequired: boolean) { + constructor(public schema: NewSchema, public isRequired: boolean) { } @@ -367,6 +367,7 @@ export class NewString implements NewEnhancedTypeDeclaration { ${this.validateMinLength(eventListener, property)} ${this.validateMaxLength(eventListener, property)} ${this.validateRegex(eventListener, property)} +${this.validateEnum(eventListener, property)} `.trim(); } @@ -376,27 +377,31 @@ ${this.validateRegex(eventListener, property)} } private validateMinLength(eventListener: Variable, property: Variable): string { - if (!this.schema.minLength) { + const len = (this.schema).minLength; + if (!len) { return ''; } - return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${this.schema.minLength});`; + return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${len});`; } private validateMaxLength(eventListener: Variable, property: Variable): string { - if (!this.schema.maxLength) { + const len = (this.schema).maxLength; + if (!len) { return ''; } - return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${this.schema.maxLength});`; + return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${len});`; } private validateRegex(eventListener: Variable, property: Variable): string { - if (!this.schema.pattern) { + const pattern = (this.schema).pattern; + if (!pattern) { return ''; } - return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${this.schema.pattern}");`; + return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${pattern}");`; + } + private validateEnum(eventListener: Variable, property: Variable): string { + if (!(this.schema instanceof ChoiceSchema)) { + return ''; + } + const choiceValues = this.schema.choices.map((c) => c.value); + return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${choiceValues.joinWith((v) => `@"${v}"`)});`; } - // private validateEnum(eventListener: Variable, property: Variable): string { - // if (!this.schema.enum || length(this.schema.enum) === 0) { - // return ''; - // } - // return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${this.schema.enum.joinWith((v) => `@"${v}"`)});`; - // } } diff --git a/powershell/main.ts b/powershell/main.ts index c2764a4af99..5aa78458fc3 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -20,6 +20,7 @@ import { namerV2 } from './plugins/ps-namer-v2'; import { llcsharpV2 } from './plugins/llcsharp-v2'; import { powershellV2 } from './plugins/powershell-v2'; import { addCompleterV2 } from './plugins/add-azure-completers-v2'; +import { applyModifiersV2 } from './plugins/modifiers-v2'; require('source-map-support').install(); @@ -39,6 +40,7 @@ export async function main() { pluginHost.Add('create-commands-v2', createCommandsV2); pluginHost.Add('csnamer-v2', csnamerV2); pluginHost.Add('psnamer-v2', namerV2); + pluginHost.Add('modifiers-v2', applyModifiersV2); pluginHost.Add('add-azure-completers-v2', addCompleterV2); pluginHost.Add('llcsharp-v2', llcsharpV2); pluginHost.Add('powershell-v2', powershellV2); diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index aab456f6873..ca67a3e2199 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -393,6 +393,7 @@ export /* @internal */ class Inferrer { name: pascalCase(each.language.default.name), httpParameter }; + each.name = each.language.default.serializedName; return each; }), // skip-for-time-being, this callGraph is used in the header comments diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index c3929d5df70..3fd5e67f59a 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, StringSchema, ChoiceSchema, SealedChoiceSchema } from '@azure-tools/codemodel'; //import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; @@ -14,6 +14,7 @@ import { SchemaDetails } from '../llcsharp/code-model'; import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; +import { SchemaDetails as NewSchemaDetails } from '../utils/schema'; type State = NewModelState; @@ -106,27 +107,27 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, namespace: pascalCase([serviceNamespace, '.', 'Models', ...ns]), // objects have a namespace fullname: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${getPascalIdentifier(schemaName)}`, }; - } else if (schema.type === SchemaType.String && schema.language.default.enum) { + } else if (schema.type === SchemaType.Choice || schema.type === SchemaType.SealedChoice) { // oh, it's an enum type - // Skip for time-being - // schema.language.csharp = { - // ...details, - // interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), - // name: getPascalIdentifier(schema.language.default.enum.name), - // namespace: pascalCase([serviceNamespace, '.', 'Support']), - // fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schema.language.default.enum.name)}`, - // enum: { - // ...schema.language.default.enum, - // name: getPascalIdentifier(schema.language.default.enum.name), - // values: schema.language.default.enum.values.map(each => { - // return { - // ...each, - // name: getPascalIdentifier(each.name), - // description: each.description - // }; - // }) - // } - // }; + const choiceSchema = | SealedChoiceSchema>schema; + schema.language.csharp = { + ...details, + interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), + name: getPascalIdentifier(schemaName), + namespace: pascalCase([serviceNamespace, '.', 'Support']), + fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schemaName)}`, + enum: { + ...schema.language.default.enum, + name: getPascalIdentifier(schema.language.default.name), + values: choiceSchema.choices.map(each => { + return { + ...each, + name: getPascalIdentifier(each.language.default.name), + description: each.language.default.description + }; + }) + } + }; } else { schema.language.csharp = { ...details, @@ -139,21 +140,17 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, } // name each property in this schema - setPropertyNames(schema); + setPropertyNames(schema); // fix enum names - // skip-for-time-being - // if (schema.details.default.enum) { - // schema.details.csharp.enum = { - // ...schema.details.default.enum, - // name: getPascalIdentifier(schema.details.default.enum.name) - // }; - - // // and the value names themselves - // for (const value of values(schema.details.csharp.enum.values)) { - // value.name = getPascalIdentifier(value.name); - // } - // } + if (schema.type === SchemaType.Choice || schema.type === SchemaType.SealedChoice) { + schema.language.csharp.enum.name = getPascalIdentifier(schema.language.default.name); + + // and the value names themselves + for (const value of values(schema.language.csharp.enum.values)) { + (value).name = getPascalIdentifier((value).name); + } + } } } diff --git a/powershell/plugins/modifiers-v2.ts b/powershell/plugins/modifiers-v2.ts new file mode 100644 index 00000000000..7ad674ad718 --- /dev/null +++ b/powershell/plugins/modifiers-v2.ts @@ -0,0 +1,716 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, ModelState, command } from '@azure-tools/codemodel-v3'; +import { Host, Channel } from '@azure-tools/autorest-extension-base'; +import { pascalCase, serialize } from '@azure-tools/codegen'; +import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; +import { stat } from 'fs'; +import { CommandOperation } from '../utils/command-operation'; +// import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; +import { NewModelState } from '../utils/model-state'; +import { PwshModel } from '../utils/PwshModel'; +import { allVirtualParameters, allVirtualProperties } from '../utils/resolve-conflicts'; +import { EnumValue } from '../utils/schema'; + +type State = NewModelState; + +let directives: Array = []; + +interface WhereCommandDirective { + select?: string; + where: { + 'subject'?: string; + 'subject-prefix'?: string; + 'verb'?: string; + 'variant'?: string; + 'parameter-name'?: string; + }; + set?: { + 'alias': Array | string; + 'subject'?: string; + 'subject-prefix'?: string; + 'verb'?: string; + 'variant'?: string; + 'parameter-name'?: string; + 'parameter-description'?: string; + 'completer'?: { + name: string; + description: string; + script: string; + }; + 'default'?: { + name: string; + description: string; + script: string; + }; + }; + 'clear-alias': boolean; + hide?: boolean; +} +interface RemoveCommandDirective { + select?: string; + where: { + 'subject'?: string; + 'subject-prefix'?: string; + 'verb'?: string; + 'variant'?: string; + 'parameter-name'?: string; + }; + remove: boolean; +} + + +function hasSpecialChars(str: string): boolean { + return !/^[a-zA-Z0-9]+$/.test(str); +} + + +function getFilterError(whereObject: any, prohibitedFilters: Array, selectionType: string): string { + let error = ''; + for (const each of values(prohibitedFilters)) { + if (whereObject[each] !== undefined) { + error += `Can't filter by ${each} when selecting command. `; + } + } + + return error; +} + +function getSetError(setObject: any, prohibitedSetters: Array, selectionType: string): string { + let error = ''; + for (const each of values(prohibitedSetters)) { + if (setObject[each] !== undefined) { + error += `Can't set ${each} when a ${selectionType} is selected. `; + } + } + + return error; +} + + +function isWhereCommandDirective(it: any): it is WhereCommandDirective { + const directive = it; + const select = directive.select; + const where = directive.where; + const set = directive.set; + if (directive.remove === undefined && where && (where.verb || where.variant || where['parameter-name'] || where.subject || where['subject-prefix'] || directive.hide || select === 'command' || select === 'parameter' || directive['clear-alias'])) { + const prohibitedFilters = ['model-name', 'property-name', 'enum-name', 'enum-value-name']; + let error = getFilterError(where, prohibitedFilters, 'command'); + + if (set !== undefined) { + const prohibitedSetters = ['property-name', 'property-description', ' model-name', 'enum-name', 'enum-value-name']; + error += getSetError(set, prohibitedSetters, 'command'); + } + + if (error) { + throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); + } + + return true; + } + + return false; +} + +function isRemoveCommandDirective(it: any): it is RemoveCommandDirective { + const directive = it; + const where = directive.where; + const remove = directive.remove; + if (where && remove && (where.subject || where.verb || where.variant || where['subject-prefix'] || where['parameter-name'] || directive.select === 'command') && directive.select !== 'parameter') { + return true; + } + + return false; +} + + +interface WhereModelDirective { + select?: string; + where: { + 'model-name'?: string; + 'model-fullname'?: string; + 'model-namespace'?: string; + 'property-name'?: string; + }; + set: { + 'suppress-format'?: boolean; + 'format-table'?: { + 'properties'?: Array; + 'exclude-properties'?: Array; + 'labels'?: { [name: string]: string }; + 'width'?: { [name: string]: number }; + }; + 'model-name'?: string; + 'property-name'?: string; + 'property-description'?: string; + }; +} + +function isWhereModelDirective(it: any): it is WhereModelDirective { + const directive = it; + const where = directive.where; + const set = directive.set; + + + if (where && set && (where['model-name'] || where['model-fullname'] || where['model-namespace'] || where['property-name'] || directive.select === 'model')) { + const prohibitedFilters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; + let error = getFilterError(where, prohibitedFilters, 'enum'); + const prohibitedSetters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; + error += getSetError(set, prohibitedSetters, 'enum'); + const modelSelectNameConflict = []; + let modelSelectNameType = ''; + if (where['model-name']) { + modelSelectNameType = 'model-name'; + if (where['model-fullname']) { + modelSelectNameConflict.push('model-fullname'); + } + + if (where['model-namespace']) { + modelSelectNameConflict.push('model-namespace'); + } + } else if (where['model-fullname']) { + modelSelectNameType = 'model-fullname'; + if (where['model-name']) { + modelSelectNameConflict.push('model-name'); + } + + if (where['model-namespace']) { + modelSelectNameConflict.push('model-namespace'); + } + } else if (where['model-namespace']) { + modelSelectNameType = 'model-namespace'; + if (where['model-fullname']) { + modelSelectNameConflict.push('model-fullname'); + } + + if (where['model-name']) { + modelSelectNameConflict.push('model-name'); + } + } + + if (length(modelSelectNameConflict) > 0) { + error += `Can't select ${modelSelectNameType} and ${modelSelectNameConflict} at the same time`; + } + + if (error) { + throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}.Reason: ${error}.`); + } + + return true; + + } + return false; +} + +interface WhereEnumDirective { + select?: string; + where: { + 'enum-name'?: string; + 'enum-value-name'?: string; + }; + set: { + 'enum-name'?: string; + 'enum-value-name'?: string; + }; +} + +function isWhereEnumDirective(it: any): it is WhereEnumDirective { + const directive = it; + const where = directive.where; + const set = directive.set; + if (where && set && (where['enum-name'] || where['enum-value-name'] || directive.select === 'enum')) { + const prohibitedFilters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; + let error = getFilterError(where, prohibitedFilters, 'enum'); + const prohibitedSetters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; + error += getSetError(set, prohibitedSetters, 'enum'); + if (error) { + throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); + } + + return true; + } + return false; +} + +async function tweakModel(state: State): Promise { + + // only look at directives without the `transform` node. + // dolauli for directives with transform are implemented in autorest core + for (const directive of directives.filter(each => !each.transform)) { + const getPatternToMatch = (selector: string | undefined): RegExp | undefined => { + return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined; + }; + + if (isWhereCommandDirective(directive)) { + const selectType = directive.select; + const clearAlias = directive['clear-alias']; + const subjectRegex = getPatternToMatch(directive.where['subject']); + const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); + const verbRegex = getPatternToMatch(directive.where.verb); + const variantRegex = getPatternToMatch(directive.where.variant); + const parameterRegex = getPatternToMatch(directive.where['parameter-name']); + + const alias = + (directive.set !== undefined) ? + (directive.set.alias !== undefined) ? + !Array.isArray(directive.set.alias) ? + [directive.set.alias] + : directive.set.alias + : undefined + : undefined; + const subjectReplacer = (directive.set !== undefined) ? directive.set['subject'] : undefined; + const subjectPrefixReplacer = (directive.set !== undefined) ? directive.set['subject-prefix'] : undefined; + const verbReplacer = (directive.set !== undefined) ? directive.set.verb : undefined; + const variantReplacer = (directive.set !== undefined) ? directive.set.variant : undefined; + const parameterReplacer = (directive.set !== undefined) ? directive.set['parameter-name'] : undefined; + const paramDescriptionReplacer = (directive.set !== undefined) ? directive.set['parameter-description'] : undefined; + const paramCompleterReplacer = (directive.set !== undefined) ? directive.set['completer'] : undefined; + const paramDefaultReplacer = (directive.set !== undefined) ? directive.set['default'] : undefined; + + // select all operations + let operations: Array = values(state.model.commands.operations).toArray(); + if (subjectRegex) { + operations = values(operations) + .where(operation => + !!`${operation.details.csharp.subject}`.match(subjectRegex)) + .toArray(); + } + + if (subjectPrefixRegex) { + operations = values(operations) + .where(operation => + !!`${operation.details.csharp.subjectPrefix}`.match(subjectPrefixRegex)) + .toArray(); + } + + if (verbRegex) { + operations = values(operations) + .where(operation => + !!`${operation.details.csharp.verb}`.match(verbRegex)) + .toArray(); + } + + if (variantRegex) { + operations = values(operations) + .where(operation => + !!`${operation.details.csharp.name}`.match(variantRegex)) + .toArray(); + } + + if (parameterRegex && selectType === 'command') { + operations = values(operations) + .where(operation => values(allVirtualParameters(operation.details.csharp.virtualParameters)) + .any(parameter => !!`${parameter.name}`.match(parameterRegex))) + .toArray(); + } + + if (parameterRegex && (selectType === undefined || selectType === 'parameter')) { + const parameters = values(operations) + .selectMany(operation => allVirtualParameters(operation.details.csharp.virtualParameters)) + .where(parameter => !!`${parameter.name}`.match(parameterRegex)) + .toArray(); + for (const p of values(parameters)) { + const parameter = p; + const prevName = parameter.name; + parameter.name = parameterReplacer ? parameterRegex ? parameter.name.replace(parameterRegex, parameterReplacer) : parameterReplacer : parameter.name; + parameter.description = paramDescriptionReplacer ? paramDescriptionReplacer : parameter.description; + parameter.completerInfo = paramCompleterReplacer ? paramCompleterReplacer : parameter.completerInfo; + parameter.defaultInfo = paramDefaultReplacer ? paramDefaultReplacer : parameter.defaultInfo; + + if (clearAlias) { + parameter.alias = []; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from parameter ${parameter.name}.` + }); + } + + if (alias) { + const parsedAlias = new Array(); + for (const each of values(alias)) { + parsedAlias.push(hasSpecialChars(each) ? prevName.replace(parameterRegex, each) : each); + } + + parameter.alias = [...new Set(values(parameter.alias, parsedAlias).toArray())]; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to parameter ${parameter.name}.` + }); + } + + if (parameterReplacer) { + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Changed parameter-name from ${prevName} to ${parameter.name}.` + }); + } + + if (paramDescriptionReplacer) { + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Set parameter-description from parameter ${parameter.name}.` + }); + } + } + + } else if (operations) { + for (const operation of values(operations)) { + const getCmdletName = (verb: string, subjectPrefix: string, subject: string, variantName: string): string => { + return `${verb}-${subjectPrefix}${subject}${variantName ? `_${variantName}` : ''}`; + }; + + const prevSubject = operation.details.csharp.subject; + const prevSubjectPrefix = operation.details.csharp.subjectPrefix; + const prevVerb = operation.details.csharp.verb; + const prevVariantName = operation.details.csharp.name; + const oldCommandName = getCmdletName(prevVerb, prevSubjectPrefix, prevSubject, prevVariantName); + + // set values + operation.details.csharp.subject = subjectReplacer ? subjectRegex ? prevSubject.replace(subjectRegex, subjectReplacer) : subjectReplacer : prevSubject; + operation.details.csharp.subjectPrefix = subjectPrefixReplacer !== undefined ? subjectPrefixRegex ? prevSubjectPrefix.replace(subjectPrefixRegex, subjectPrefixReplacer) : subjectPrefixReplacer : prevSubjectPrefix; + operation.details.csharp.verb = verbReplacer ? verbRegex ? prevVerb.replace(verbRegex, verbReplacer) : verbReplacer : prevVerb; + operation.details.csharp.name = variantReplacer ? variantRegex ? prevVariantName.replace(variantRegex, variantReplacer) : variantReplacer : prevVariantName; + operation.details.csharp.hidden = (directive.hide !== undefined) ? !!directive.hide : operation.details.csharp.hidden; + + const newSubject = operation.details.csharp.subject; + const newSubjectPrefix = operation.details.csharp.subjectPrefix; + const newVerb = operation.details.csharp.verb; + const newVariantName = operation.details.csharp.name; + const newCommandName = getCmdletName(newVerb, newSubjectPrefix, newSubject, newVariantName); + + // just the subject prefix can be an empty string + if (subjectPrefixReplacer !== undefined || subjectReplacer || verbReplacer || variantReplacer) { + const modificationMessage = `[DIRECTIVE] Changed command from ${oldCommandName} to ${newCommandName}. `; + state.message({ + Channel: Channel.Debug, Text: modificationMessage + }); + } + + if (clearAlias) { + operation.details.csharp.alias = []; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from command ${newCommandName}.` + }); + } + + if (alias) { + const getParsedAlias = (rawAlias: string) => { + return rawAlias.replace('${verb}', operation.details.csharp.verb) + .replace('${subject-prefix}', operation.details.csharp.subjectPrefix) + .replace('${subject}', operation.details.csharp.subject) + .replace('${variant}', operation.details.csharp.name); + }; + + const parsedAlias = new Array(); + for (const each of values(alias)) { + parsedAlias.push(getParsedAlias(each)); + } + + operation.details.csharp.alias = [...new Set(values(operation.details.csharp.alias, parsedAlias).toArray())]; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to command ${newCommandName}.` + }); + } + } + } + + continue; + } + + if (isWhereModelDirective(directive)) { + const selectType = directive.select; + const modelNameRegex = getPatternToMatch(directive.where['model-name']); + const modelFullNameRegex = getPatternToMatch(directive.where['model-fullname']); + const modelNamespaceRegex = getPatternToMatch(directive.where['model-namespace']); + const propertyNameRegex = getPatternToMatch(directive.where['property-name']); + + const modelNameReplacer = directive.set['model-name']; + const propertyNameReplacer = directive.set['property-name']; + const propertyDescriptionReplacer = directive.set['property-description']; + const formatTable = directive.set['format-table']; + const suppressFormat = directive.set['suppress-format']; + + // select all models + let models = [...state.model.schemas.objects ?? []]; + // let models = values(state.model.schemas).toArray(); + if (modelNameRegex) { + models = values(models) + .where(model => + !!`${model.language.csharp?.name}`.match(modelNameRegex)) + .toArray(); + } + + if (modelFullNameRegex) { + models = values(models) + .where(model => + !!`${model.language.csharp?.fullname}`.match(modelFullNameRegex)) + .toArray(); + } + + if (modelNamespaceRegex) { + models = values(models) + .where(model => + !!`${model.language.csharp?.namespace}`.match(modelNamespaceRegex)) + .toArray(); + } + + if (propertyNameRegex && selectType === 'model') { + models = values(models) + .where(model => values(allVirtualProperties(model.language.csharp?.virtualProperties)) + .any(property => !!`${property.name}`.match(propertyNameRegex))) + .toArray(); + } + + if (propertyNameRegex && (selectType === undefined || selectType === 'property')) { + const properties = values(models) + .selectMany(model => allVirtualProperties(model.language.csharp?.virtualProperties)) + .where(property => !!`${property.name}`.match(propertyNameRegex)) + .toArray(); + for (const property of values(properties)) { + const prevName = property.name; + property.name = propertyNameReplacer ? propertyNameRegex ? property.name.replace(propertyNameRegex, propertyNameReplacer) : propertyNameReplacer : property.name; + property.description = propertyDescriptionReplacer ? propertyDescriptionReplacer : property.description; + + if (!property.name) { + state.message({ Channel: Channel.Error, Text: `Directive '${directive.where['model-name'] || directive.where['model-fullname']}/${directive.where['property-name']}' attempted to change '${prevName}' to '' ` }); + } + if (propertyNameRegex) { + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Changed property-name from ${prevName} to ${property.name}.` + }); + } + } + + } else if (models) { + for (const model of values(models)) { + + if (suppressFormat && model.language.csharp) { + model.language.csharp.suppressFormat = true; + } + + if (formatTable !== undefined && !suppressFormat) { + const properties = allVirtualProperties(model.language.csharp?.virtualProperties); + const propertiesToExclude = formatTable['exclude-properties']; + const propertiesToInclude = formatTable.properties; + const labels = formatTable.labels; + const widths = formatTable.width; + if (labels) { + const parsedLabels = new Dictionary(); + for (const label of items(labels)) { + parsedLabels[label.key.toLowerCase()] = label.value; + } + + for (const property of values(properties)) { + if (Object.keys(parsedLabels).includes(property.name.toLowerCase())) { + if (property.format === undefined) { + property.format = {}; + } + + property.format.label = parsedLabels[property.name.toLowerCase()]; + } + } + } + + if (widths) { + const parsedWidths = new Dictionary(); + for (const w of items(widths)) { + parsedWidths[w.key.toLowerCase()] = w.value; + } + + for (const property of values(properties)) { + if (Object.keys(parsedWidths).includes(property.name.toLowerCase())) { + if (property.format === undefined) { + property.format = {}; + } + + property.format.width = parsedWidths[property.name.toLowerCase()]; + } + } + } + + if (propertiesToInclude) { + const indexes = new Dictionary(); + for (const item of items(propertiesToInclude)) { + indexes[item.value.toLowerCase()] = item.key; + } + + for (const property of values(properties)) { + if (propertiesToInclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { + if (property.format === undefined) { + property.format = {}; + } + + property.format.index = indexes[property.name.toLowerCase()]; + } else { + property.format = { suppressFormat: true }; + } + } + } + + if (propertiesToExclude) { + for (const property of values(properties)) { + if (propertiesToExclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { + property.format = { suppressFormat: true }; + } + } + } + } + + const prevName = model.language.csharp?.name; + if (model.language.csharp) { + model.language.csharp.name = modelNameReplacer ? modelNameRegex ? model.language.csharp.name.replace(modelNameRegex, modelNameReplacer) : modelNameReplacer : model.language.csharp.name; + } + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Changed model-name from ${prevName} to ${model.language.csharp?.name}.` + }); + } + } + + continue; + } + + if (isWhereEnumDirective(directive)) { + const enumNameRegex = getPatternToMatch(directive.where['enum-name']); + const enumValueNameRegex = getPatternToMatch(directive.where['enum-value-name']); + + const enumNameReplacer = directive.set['enum-name']; + const enumValueNameReplacer = directive.set['enum-value-name']; + + let enums = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []]; + // let enums = values(state.model.schemas) + // .where(each => each.details.csharp.enum !== undefined) + // .toArray(); + + if (enumNameRegex) { + enums = values(enums) + .where(each => !!`${each.language.csharp?.name}`.match(enumNameRegex)) + .toArray(); + } + + if (enumValueNameRegex) { + const enumsValues = values(enums) + .selectMany(each => each.language.csharp?.enum ? each.language.csharp.enum.values : []) + .where(each => !!`${(each).name}`.match(enumValueNameRegex)) + .toArray(); + for (const enumValue of values(enumsValues)) { + const prevName = (enumValue).name; + (enumValue).name = enumValueNameReplacer ? enumNameRegex ? (enumValue).name.replace(enumValueNameRegex, enumValueNameReplacer) : enumValueNameReplacer : prevName; + if (enumValueNameRegex) { + const enumNames = values(enums) + .select(each => each.language.csharp?.name) + .toArray(); + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-value-name from ${prevName} to ${(enumValue).name}. Enum: ${JSON.stringify(enumNames, null, 2)}` + }); + } + } + } else { + for (const each of values(enums)) { + const prevName = each.language.csharp?.name ?? ''; + if (each.language.csharp) { + each.language.csharp.name = enumNameReplacer ? enumNameRegex ? each.language.csharp.name.replace(enumNameRegex, enumNameReplacer) : enumNameReplacer : prevName; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-name from ${prevName} to ${each.language.csharp?.name}.` + }); + } + } + } + + continue; + } + + + if (isRemoveCommandDirective(directive)) { + const selectType = directive.select; + const subjectRegex = getPatternToMatch(directive.where.subject); + const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); + const verbRegex = getPatternToMatch(directive.where.verb); + const variantRegex = getPatternToMatch(directive.where.variant); + const parameterRegex = getPatternToMatch(directive.where['parameter-name']); + + if (subjectRegex || subjectPrefixRegex || verbRegex || variantRegex || (parameterRegex && selectType === 'command')) { + // select all operations first then reduce by finding the intersection with selectors + let operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .select(operation => operation.key) + .toArray()); + + if (subjectRegex) { + operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .where(operation => !!`${operation.value.details.csharp.subject}`.match(subjectRegex) && operationsToRemoveKeys.has(operation.key)) + .select(operation => operation.key) + .toArray()); + } + + if (subjectPrefixRegex && operationsToRemoveKeys.size > 0) { + operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .where(operation => !!`${operation.value.details.csharp.subjectPrefix}`.match(subjectPrefixRegex) && operationsToRemoveKeys.has(operation.key)) + .select(operation => operation.key) + .toArray()); + } + + if (verbRegex && operationsToRemoveKeys.size > 0) { + operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .where(operation => !!`${operation.value.details.csharp.verb}`.match(verbRegex) && operationsToRemoveKeys.has(operation.key)) + .select(operation => operation.key) + .toArray()); + } + + if (variantRegex && operationsToRemoveKeys.size > 0) { + operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .where(operation => !!`${operation.value.details.csharp.name}`.match(variantRegex) && operationsToRemoveKeys.has(operation.key)) + .select(operation => operation.key) + .toArray()); + } + + if (parameterRegex && selectType === 'command' && operationsToRemoveKeys.size > 0) { + operationsToRemoveKeys = new Set(items(state.model.commands.operations) + .where(operation => values(allVirtualParameters(operation.value.details.csharp.virtualParameters)) + .any(parameter => !!`${parameter.name}`.match(parameterRegex))) + .where(operation => operationsToRemoveKeys.has(operation.key)) + .select(operation => operation.key) + .toArray()); + } + + for (const key of values(operationsToRemoveKeys)) { + const operationInfo = state.model.commands.operations[key].details.csharp; + state.message({ + Channel: Channel.Debug, Text: `[DIRECTIVE] Removed command ${operationInfo.verb}-${operationInfo.subjectPrefix}${operationInfo.subject}${operationInfo.name ? `_${operationInfo.name}` : ''}` + }); + + delete state.model.commands.operations[key]; + } + } + + continue; + } + } + + const operationIdentities = new Set(); + for (const operation of values(state.model.commands.operations)) { + const details = operation.details.csharp; + + let fname = `${details.verb} -${details.subject} -${details.name} `; + let n = 1; + + while (operationIdentities.has(fname)) { + details.name = pascalCase(`${details.name.replace(/\d*$/g, '')} ${n++}`); + fname = pascalCase(`${details.verb} -${details.subject} -${details.name}`); + } + operationIdentities.add(fname); + } + + return state.model; +} + +export async function applyModifiersV2(service: Host) { + // dolauli implement directives + const allDirectives = await service.GetValue('directive'); + directives = values(allDirectives) + // .select(directive => directive) + .where(directive => isWhereCommandDirective(directive) || isWhereModelDirective(directive) || isWhereEnumDirective(directive) || isRemoveCommandDirective(directive)) + .toArray(); + + const state = await new NewModelState(service).init(); + const result = await tweakModel(state); + + await service.WriteFile('code-model-v4-modifiers-v2.yaml', serialize(result), undefined, 'code-model-v4'); +} diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index cede952c758..9f94a288b98 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -110,7 +110,7 @@ async function tweakModelV2(state: State): Promise { const newProp = new Property(name, param.language.default.description, param.schema); newProp.required = false; newProp.readOnly = false; - newProp.serializedName = name; + newProp.serializedName = param.language.default.serializedName; universalId.properties.push(newProp); } } @@ -172,6 +172,8 @@ async function tweakModelV2(state: State): Promise { // properties with an enum single value are constants // add the constant value property.language.default.constantValue = choiceSchema.choices[0].value; + + // xichen: Do we need skip? } } } diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index 583fb10fad7..c540ac8772d 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -9,6 +9,9 @@ import { DeepPartial, } from '@azure-tools/codegen'; import { Dictionary, values } from '@azure-tools/linq'; import { uid } from './uid'; import { Schema, ObjectSchema, Property, SchemaType } from '@azure-tools/codemodel'; +import { NewEnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; +import { NewModelClass } from '../llcsharp/model/model-class'; +import { NewModelInterface } from '../llcsharp/model/interface'; export interface PropertyDetails extends ImplementationDetails { required: boolean; @@ -93,6 +96,15 @@ export interface SchemaDetails extends ImplementationDetails { discriminatorValue?: string; suppressFormat?: boolean; + + typeDeclaration?: NewEnhancedTypeDeclaration; + classImplementation?: NewModelClass; + interfaceImplementation?: NewModelInterface; + internalInterfaceImplementation?: NewModelInterface; + interfaceName?: string; + internalInterfaceName?: string; + fullInternalInterfaceName?: string; + fullname?: string; } // export class Schema extends Extensions implements Schema { diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 02c76ec53fe..6ad6ceb5e7f 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -9,7 +9,11 @@ "basic-response-multioperation", "basic-spec-required", "basic-spec-root", - "datamodels-datatypes-array" + "datamodels-datatypes-array", + "component-param", + "component-multiparam", + "component-param-localremote", + "component-param-inbody" ], "BlackList": [ "basic-get-querystr", From a72ba58fa3bca61bdf7b93b85d1776570b5057f2 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 29 Jul 2020 19:15:34 +0800 Subject: [PATCH 21/61] Initial support for lro and paing (#644) * Initial support for lro and pagination * Fixed a paging issue --- powershell/autorest-configuration.md | 2 +- powershell/cmdlets/class.ts | 90 +++++++++---------- powershell/enums/namespace.ts | 3 +- powershell/internal/project.ts | 23 +++-- powershell/llcsharp/exports.ts | 2 +- .../llcsharp/model/model-class-serializer.ts | 2 - powershell/llcsharp/operation/method.ts | 33 ++++--- powershell/llcsharp/schema/schema-resolver.ts | 5 +- powershell/package.json | 2 +- powershell/plugins/cs-namer-v2.ts | 2 +- powershell/plugins/onbaordpipeline.md | 39 -------- .../plugins/plugin-tweak-model-azure-v2.ts | 5 +- 12 files changed, 86 insertions(+), 122 deletions(-) delete mode 100644 powershell/plugins/onbaordpipeline.md diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index e146910a3c7..6eca7c67537 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -15,7 +15,7 @@ modelerfour: ``` yaml use-extension: "@autorest/remodeler" : "~2.1.0" - "@autorest/modelerfour": "4.13.351" + "@autorest/modelerfour": "4.15.378" # will use highest 2.0.x ``` diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 41c630537af..30cef55d3bc 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -1939,15 +1939,15 @@ export class NewCmdletClass extends Class { ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ex.value}.Message) { RecommendedAction = ${ex.value}.Action } });`; }; - if (each instanceof SchemaResponse) { + if ((each).schema !== undefined) { // the schema should be the error information. // this supports both { error { message, code} } and { message, code} - let props = getAllPublicVirtualProperties(each.schema.language.csharp?.virtualProperties); - const errorProperty = values(props).first(p => p.property.details.csharp.name === 'error'); + let props = NewGetAllPublicVirtualProperties((each).schema.language.csharp?.virtualProperties); + const errorProperty = values(props).first(p => p.property.serializedName === 'error'); let ep = ''; if (errorProperty) { - props = getAllPublicVirtualProperties(errorProperty.property.schema.details.csharp.virtualProperties); + props = NewGetAllPublicVirtualProperties(errorProperty.property.schema.language.csharp?.virtualProperties); ep = `${errorProperty.name}?.`; } @@ -1992,42 +1992,41 @@ export class NewCmdletClass extends Class { yield `// ${pageable.responseType} / ${pageable.itemName || ''} / ${pageable.nextLinkName || ''}`; switch (pageable.responseType) { // the result is (or works like a x-ms-pageable) - // skip-for-time-being - // case 'pageable': - // case 'nested-array': { - // const valueProperty = schema.properties[pageable.itemName]; - // const nextLinkProperty = schema.properties[pageable.nextLinkName]; - // if (valueProperty && nextLinkProperty) { - // // it's pageable! - // const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('await response') }); - // yield result.declarationStatement; - // // write out the current contents - // const vp = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - // if (vp) { - // yield `WriteObject(${result.value}.${vp.name},true);`; - // } - // const nl = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, nextLinkProperty.serializedName); - // if (nl) { - // const nextLinkName = `${result.value}.${nl.name}`; - // yield (If(`${nextLinkName} != null`, - // If('responseMessage.RequestMessage is System.Net.Http.HttpRequestMessage requestMessage ', function* () { - // yield `requestMessage = requestMessage.Clone(new global::System.Uri( ${nextLinkName} ),${ClientRuntime.Method.Get} );`; - // yield $this.eventListener.signal(Events.FollowingNextLink); - // yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}_Call`, ...[toExpression('requestMessage'), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - // }) - // )); - // } - // return; - // } else if (valueProperty) { - // // it's just a nested array - // const p = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - // if (p) { - // yield `WriteObject((await response).${p.name}, true);`; - // } - // return; - // } - // } - // break; + case 'pageable': + case 'nested-array': { + const valueProperty = (schema).properties?.find(p => p.serializedName === pageable.itemName); + const nextLinkProperty = (schema)?.properties?.find(p => p.serializedName === pageable.nextLinkName); + if (valueProperty && nextLinkProperty) { + // it's pageable! + const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('await response') }); + yield result.declarationStatement; + // write out the current contents + const vp = NewGetVirtualPropertyFromPropertyName(schema.language.csharp?.virtualProperties, valueProperty.serializedName); + if (vp) { + yield `WriteObject(${result.value}.${vp.name},true);`; + } + const nl = NewGetVirtualPropertyFromPropertyName(schema.language.csharp?.virtualProperties, nextLinkProperty.serializedName); + if (nl) { + const nextLinkName = `${result.value}.${nl.name}`; + yield (If(`${nextLinkName} != null`, + If('responseMessage.RequestMessage is System.Net.Http.HttpRequestMessage requestMessage ', function* () { + yield `requestMessage = requestMessage.Clone(new global::System.Uri( ${nextLinkName} ),${ClientRuntime.Method.Get} );`; + yield $this.eventListener.signal(Events.FollowingNextLink); + yield `await this.${$this.$('Client').invokeMethod(`${apiCall.language.csharp?.name}_Call`, ...[toExpression('requestMessage'), ...callbackMethods, dotnet.This, pipeline]).implementation}`; + }) + )); + } + return; + } else if (valueProperty) { + // it's just a nested array + const p = getVirtualPropertyFromPropertyName(schema.language.csharp?.virtualProperties, valueProperty.serializedName); + if (p) { + yield `WriteObject((await response).${p.name}, true);`; + } + return; + } + } + break; // it's just an array, case 'array': @@ -2037,7 +2036,7 @@ export class NewCmdletClass extends Class { } // ok, let's see if the response type } - const props = getAllPublicVirtualProperties(schema.language.csharp?.virtualProperties); + const props = NewGetAllPublicVirtualProperties(schema.language.csharp?.virtualProperties); const outValue = (length(props) === 1) ? `(await response).${props[0].name}` : '(await response)'; @@ -2675,15 +2674,14 @@ export class NewCmdletClass extends Class { if (typeDeclaration instanceof NewArrayOf) { type = typeDeclaration.elementTypeDeclaration; } else if (pageableInfo && pageableInfo.responseType === 'pageable') { - if (typeDeclaration === undefined || (typeDeclaration.schema).properties?.[pageableInfo.itemName] === undefined) { + if (typeDeclaration === undefined || (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName) === undefined) { //skip-for-time-being, since operationId does not support in m4 any more //throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); throw new Error('An error needs to be more specific'); } - const nestedSchema = (typeDeclaration.schema).properties?.[pageableInfo.itemName].schema; - // skip-for-time-being - //const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); - //type = (nestedTypeDeclaration).elementTypeDeclaration; + const nestedSchema = (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName)?.schema; + const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); + type = (nestedTypeDeclaration).elementTypeDeclaration; } else { type = typeDeclaration.declaration; } diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index 8350aad788c..23f9f6b302a 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -129,7 +129,8 @@ export class NewEnumNamespace extends Namespace { constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); - const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] + //const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] + const enumInfos = [...state.model.schemas.sealedChoices || []] .filter((choice) => !choice.language.csharp?.skip) .map((choice) => { return { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index c031248bcdf..0a0a071cedf 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; +import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewBoolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; import { State, NewState } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; import { EnumNamespace, NewEnumNamespace } from '../enums/namespace'; @@ -17,7 +17,7 @@ import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, BooleanSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -59,18 +59,23 @@ export class PSSchemaResolver extends SchemaDefinitionResolver { } } +export class NewPSSwitch extends NewBoolean { + get declaration(): string { + return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`; + } + +} export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { inResolve = false; resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { const before = this.inResolve; try { - // skip-for-time-being - // if (!this.inResolve) { - // this.inResolve = true; - // if (schema && schema.type === JsonType.Boolean) { - // return new PSSwitch(schema, required); - // } - // } + if (!this.inResolve) { + this.inResolve = true; + if (schema && schema.type === SchemaType.Boolean) { + return new NewPSSwitch(schema, required); + } + } return super.resolveTypeDeclaration(schema, required, state); } finally { diff --git a/powershell/llcsharp/exports.ts b/powershell/llcsharp/exports.ts index f9d66798e8b..af1d4562506 100644 --- a/powershell/llcsharp/exports.ts +++ b/powershell/llcsharp/exports.ts @@ -13,4 +13,4 @@ export * from './schema/schema-resolver'; export * from './schema/extended-type-declaration'; export * from './model/model-class-serializer'; export * from './schema/enum'; -export { Boolean } from './schema/boolean'; +export { Boolean, NewBoolean } from './schema/boolean'; diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index d3d653e3cf7..8b9a3c7422d 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -273,7 +273,6 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { return function* () { yield '// actually deserialize '; - // skip-for-time-being for (const virtualProperty of values(>$this.allVirtualProperties)) { // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.language.default.required); @@ -281,7 +280,6 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { const cvt = type.convertObjectMethod; const t = `((${virtualProperty.originalContainingSchema.language.csharp?.fullInternalInterfaceName})this)`; const tt = type ? `(${type.declaration})` : ''; - yield `${t}.${NewGetVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${NewGetVirtualPropertyName(virtualProperty)}",${t}.${NewGetVirtualPropertyName(virtualProperty)}, ${cvt});`; } }; diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index bf7a4d05bfa..80569568164 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -933,23 +933,22 @@ export class NewCallMethod extends Method { finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); yield finalUri; break; - // skip-for-time-being - // case 'azure-asyncoperation': - // case 'azure-async-operation': - // // depending on the type of request, do the appropriate behavior - // switch ($this.opMethod.operation.method.toLowerCase()) { - // case 'post': - // case 'delete': - // finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - // yield finalUri; - // break; - // case 'patch': - // case 'put': - // // perform a final GET on the original URI. - // finalUri = originalUri; - // break; - // } - // break; + case 'azure-asyncoperation': + case 'azure-async-operation': + //depending on the type of request, do the appropriate behavior + switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) { + case 'post': + case 'delete': + finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); + yield finalUri; + break; + case 'patch': + case 'put': + // perform a final GET on the original URI. + finalUri = originalUri; + break; + } + break; default: // depending on the type of request, fall back to the appropriate behavior diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index e175248d98e..b33b5ae2d02 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -207,7 +207,7 @@ export class NewSchemaDefinitionResolver { case 64: return new NewNumeric(schema, required, required ? 'double' : 'double?'); case 32: - new NewNumeric(schema, required, required ? 'float' : 'float?'); + return new NewNumeric(schema, required, required ? 'float' : 'float?'); case 128: return new NewNumeric(schema, required, required ? 'decimal' : 'decimal?'); } @@ -223,6 +223,7 @@ export class NewSchemaDefinitionResolver { throw new Error('Unknown Model. Fatal.'); } case SchemaType.Choice: + return new NewString(schema, required); case SchemaType.SealedChoice: return new NewEnumImplementation(schema, required); case undefined: diff --git a/powershell/package.json b/powershell/package.json index 73432b459e5..308f6e460d6 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -55,7 +55,7 @@ }, "dependencies": { "js-yaml": "3.13.1", - "@azure-tools/codegen": "~2.1.0", + "@azure-tools/codegen": "^2.5.276", "@azure-tools/codegen-csharp": "~3.0.0", "@azure-tools/codemodel-v3": "~3.1.0", "@azure-tools/codemodel": "~4.13.342", diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 3fd5e67f59a..753d2e9338c 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -175,7 +175,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso operation.language.csharp = { ...details, // inherit - name: operationGroup.language.default.name + operationName, + name: getPascalIdentifier(operationGroup.language.default.name + '_' + operationName), }; // parameters are camelCased. diff --git a/powershell/plugins/onbaordpipeline.md b/powershell/plugins/onbaordpipeline.md deleted file mode 100644 index 2624fd75fa9..00000000000 --- a/powershell/plugins/onbaordpipeline.md +++ /dev/null @@ -1,39 +0,0 @@ -There are three key steps for on-boarding a new RP with AutoRest PowerShell Generator. -- Onboard request -- Design review -- PR review - -## Onboard Request -The first step is to send an onboard request to Azure PowerShell PM Damien(). And you are expected to provide information as below(maybe more). -- RP status -- Roadmap -- Contact person for customer support - -Damien will assist you to work out a speclet for your RP, which is something like combination of use-case spec and function spec. - -## Design Review -Based on the speclet, you may start to generate code. Detailed steps are below. - -- Generate code with PowerShell generator -- Customize code based on the speclet -- Write examples - -When all above steps are completed, you may file a ticket in https://github.com/Azure/azure-powershell-cmdlet-review-pr/issues for design review. -The issue should contain content below. -- Link to the speclet -- Cmdlets syntax and examples (you may copy and paste them from the ./docs folder) -- A link to the code repo which contains the docs folder - -The issue will be assigned to an engineer in Azure PowerShell team for review. If the RP is complex, a review meeting will be needed, otherwise, review may be done through comments in the ticket/emails. - -## Code Review -When design review is ongoing, you may write the test cases. After design review passes, you may file a PR against the generation branch of azure-powershell for code review. And code list is as following. -- readme.md -- custom -- examples -- test -- docs - -After code review, congratulaitions, you got the chance to take the release train, which is once every three week. - - diff --git a/powershell/plugins/plugin-tweak-model-azure-v2.ts b/powershell/plugins/plugin-tweak-model-azure-v2.ts index f1e87c034ee..9dde68f7862 100644 --- a/powershell/plugins/plugin-tweak-model-azure-v2.ts +++ b/powershell/plugins/plugin-tweak-model-azure-v2.ts @@ -114,8 +114,9 @@ async function tweakModel(state: State): Promise { }; // LRO 201 and 202 responses are handled internally, so remove any 201/202 responses in the operation - // delete operation.responses['201']; - // delete operation.responses['202']; + operation.responses = (>(operation.responses)).filter(each => each.protocol.http?.statusCodes[0] !== '201' && each.protocol.http?.statusCodes[0] !== '202'); + //delete operation.responses['201']; + //delete operation.responses['202']; } } } From 0af32f5d103f1515045af3239c80cd25e27b89df Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 3 Aug 2020 10:21:58 +0800 Subject: [PATCH 22/61] Fix the issue nested object is not supported (#646) * Fix the issue nested ojbect not supported * Add more passed test cases --- powershell/plugins/plugin-create-inline-properties.ts | 2 +- powershell/utils/schema.ts | 4 ++-- tests-upgrade/Configuration.json | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 07ecf13568c..061b706cc92 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -210,7 +210,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr property: inlinedProperty.property, private: inlinedProperty.private, nameComponents: components, - nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), + nameOptions: getNameOptions(inlinedProperty.property.schema.language.default.name, components), accessViaProperty: privateProperty, accessViaMember: inlinedProperty, accessViaSchema: schema, diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index c540ac8772d..c4117d84a6c 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -8,7 +8,7 @@ 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 } from '@azure-tools/codemodel'; +import { Schema, ObjectSchema, Property, SchemaType, isObjectSchema } from '@azure-tools/codemodel'; import { NewEnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; import { NewModelClass } from '../llcsharp/model/model-class'; import { NewModelInterface } from '../llcsharp/model/interface'; @@ -138,7 +138,7 @@ export function getPolymorphicBases(schema: Schema): Array { } export function getAllProperties(schema: Schema): Array { - if (schema instanceof ObjectSchema) { + if (isObjectSchema(schema)) { return [...values(schema.parents ? schema.parents.immediate : []).selectMany(getAllProperties), ...values(schema.properties)]; } else { return []; diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 6ad6ceb5e7f..fa0be4b88c3 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -9,11 +9,14 @@ "basic-response-multioperation", "basic-spec-required", "basic-spec-root", - "datamodels-datatypes-array", - "component-param", + "component-definitions-local", "component-multiparam", + "component-param", + "component-param-inbody", "component-param-localremote", - "component-param-inbody" + "component-param-remote", + "datamodels-datatypes-array", + "datamodels-datatypes-integer" ], "BlackList": [ "basic-get-querystr", From a377fe0844a1f5e676b15dda9fbd583d7fa3d3dc Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 3 Aug 2020 17:12:34 +0800 Subject: [PATCH 23/61] Add support for allof, datetime and enable two cases (#649) * Fix the issue nested ojbect not supported * Add more passed test cases * Add support for allOf, datetime and enable two cases --- powershell/llcsharp/model/model-class.ts | 166 +++++++++--------- powershell/llcsharp/schema/schema-resolver.ts | 5 +- .../plugin-create-inline-properties.ts | 2 +- tests-upgrade/Configuration.json | 4 +- 4 files changed, 90 insertions(+), 87 deletions(-) diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 6fbf72d0312..c80abb95ba9 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -552,10 +552,10 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { public get schema() { return this.featureImplementation.schema; } /* @internal */ validateMethod?: Method; - /* @internal */ discriminators: Map = new Map(); - /* @internal */ parentModelClasses: Array = new Array(); - /* @internal */ get modelInterface(): ModelInterface { return this.schema.language.csharp?.interfaceImplementation; } - /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } + /* @internal */ discriminators: Map = new Map(); + /* @internal */ parentModelClasses: Array = new Array(); + /* @internal */ get modelInterface(): NewModelInterface { return this.schema.language.csharp?.interfaceImplementation; } + /* @internal */ get internalModelInterface(): NewModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } /* @internal */ state: NewState; /* @internal */ backingFields = new Array(); @@ -586,8 +586,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // must be a partial class this.partial = true; - //skip-for-time-being - //this.handleDiscriminator(); + this.handleDiscriminator(); // create an interface for this model class if (!this.schema.language.csharp.interfaceImplementation) { @@ -611,12 +610,12 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // skip-for-time-being // handle parent interface implementation - // if (!this.handleAllOf()) { - // // handle the AdditionalProperties if used - // if (this.schema.additionalProperties) { - // this.dictionaryImpl = new DictionaryImplementation(this).init(); - // } - // } + if (!this.handleAllOf()) { + // handle the AdditionalProperties if used + // if (this.schema.additionalProperties) { + // this.dictionaryImpl = new DictionaryImplementation(this).init(); + // } + } // create the properties for ths schema this.createProperties(); @@ -838,7 +837,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } } - private additionalPropertiesType(aSchema: Schema): TypeDeclaration | undefined { + private additionalPropertiesType(aSchema: NewSchema): TypeDeclaration | undefined { // skip-for-time-being // if (aSchema.additionalProperties) { @@ -859,76 +858,75 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { return undefined; } - // skip-for-time-being - // private handleAllOf() { - // let hasAdditionalPropertiesInParent = false; - // // handle s - // // add an 'implements' for the interface for the allOf. - // for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.allOf)) { - // const aSchema = eachSchemaValue; - // const aState = this.state.path('allOf', eachSchemaIndex); - - // const td = this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema, true, aState); - // const parentClass = (aSchema.details.csharp.classImplementation); - // const className = parentClass.fullName; - // const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); - - // // add the interface as a parent to our interface. - // const iface = aSchema.details.csharp.interfaceImplementation; - - // // add a field for the inherited values - // const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); - // this.backingFields.push({ - // className, - // typeDeclaration: td, - // field: backingField - // }); - // this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); - // this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); - - // this.internalModelInterface.interfaces.push(aSchema.details.csharp.internalInterfaceImplementation); - // this.modelInterface.interfaces.push(iface); - - // // - // const addlPropType = this.additionalPropertiesType(aSchema); - // if (addlPropType) { - // this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); - // hasAdditionalPropertiesInParent = true; - // } - // } - // return hasAdditionalPropertiesInParent; - // } - - // private handleDiscriminator() { - // if (this.schema.discriminator) { - // // this has a discriminator property. - // // our children are expected to tell us who they are - // this.isPolymorphic = true; - // // we'll add a deserializer factory method a bit later.. - // } - - // if (this.schema.details.csharp.discriminatorValue) { - // // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. - // // um. just how do we *really* know which allOf is polymorphic? - // // that's really sad. - // for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.allOf)) { - // const parentSchema = eachAllOfValue; - // const aState = this.state.path('allOf', eachAllOfIndex); - - // // ensure the parent schema has it's class created first. - // this.state.project.modelsNamespace.resolveTypeDeclaration(parentSchema, true, aState); - - // const parentClass = parentSchema.details.csharp.classImplementation; - // if (parentClass.isPolymorphic) { - // // remember this class for later. - // this.parentModelClasses.push(parentClass); - - // // tell that parent who we are. - // parentClass.addDiscriminator(this.schema.details.csharp.discriminatorValue, this); - // } - // } - // } - // } + private handleAllOf() { + let hasAdditionalPropertiesInParent = false; + // handle s + // add an 'implements' for the interface for the allOf. + for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.parents?.immediate)) { + const aSchema = eachSchemaValue; + const aState = this.state.path('allOf', eachSchemaIndex); + + const td = this.state.project.modelsNamespace.NewResolveTypeDeclaration(aSchema, true, aState); + const parentClass = (aSchema.language.csharp?.classImplementation); + const className = parentClass.fullName; + const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); + + // add the interface as a parent to our interface. + const iface = aSchema.language.csharp?.interfaceImplementation; + + // add a field for the inherited values + const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); + this.backingFields.push({ + className, + typeDeclaration: td, + field: backingField + }); + this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); + this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); + + this.internalModelInterface.interfaces.push(aSchema.language.csharp?.internalInterfaceImplementation); + this.modelInterface.interfaces.push(iface); + + // + const addlPropType = this.additionalPropertiesType(aSchema); + if (addlPropType) { + // this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); + // hasAdditionalPropertiesInParent = true; + } + } + return hasAdditionalPropertiesInParent; + } + + private handleDiscriminator() { + if (this.schema.discriminator) { + // this has a discriminator property. + // our children are expected to tell us who they are + this.isPolymorphic = true; + // we'll add a deserializer factory method a bit later.. + } + + if (this.schema.language.csharp?.discriminatorValue) { + // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. + // um. just how do we *really* know which allOf is polymorphic? + // that's really sad. + for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.parents?.immediate)) { + const parentSchema = eachAllOfValue; + const aState = this.state.path('allOf', eachAllOfIndex); + + // ensure the parent schema has it's class created first. + this.state.project.modelsNamespace.NewResolveTypeDeclaration(parentSchema, true, aState); + + const parentClass = parentSchema.language.csharp?.classImplementation; + if (parentClass.isPolymorphic) { + // remember this class for later. + this.parentModelClasses.push(parentClass); + + // tell that parent who we are. + parentClass.addDiscriminator(this.schema.language.csharp.discriminatorValue, this); + } + } + } + } private addHeaderDeserializer() { const avp = getAllVirtualProperties(this.schema.language.csharp?.virtualProperties); const headers = new Parameter('headers', System.Net.Http.Headers.HttpResponseHeaders); @@ -960,7 +958,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { return this.featureImplementation.validatePresence(eventListener, property); } - public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { + public addDiscriminator(discriminatorValue: string, modelClass: NewModelClass) { this.discriminators.set(discriminatorValue, modelClass); // tell any polymorphic parents incase we're doing subclass of a subclass. diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index b33b5ae2d02..0885d402d7e 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -186,6 +186,9 @@ export class NewSchemaDefinitionResolver { } + case SchemaType.DateTime: + return new NewDateTime(schema, required); + case SchemaType.Boolean: return new NewBoolean(schema, required); diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 061b706cc92..84656151f90 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -238,7 +238,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr property: inlinedProperty.property, private: inlinedProperty.private, nameComponents: components, - nameOptions: getNameOptions(inlinedProperty.property.schema.details.default.name, components), + nameOptions: getNameOptions(inlinedProperty.property.schema.language.default.name, components), accessViaProperty: privateProperty, accessViaMember: inlinedProperty, accessViaSchema: schema, diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index fa0be4b88c3..19d490b1954 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -9,6 +9,7 @@ "basic-response-multioperation", "basic-spec-required", "basic-spec-root", + "component-definitions-combined", "component-definitions-local", "component-multiparam", "component-param", @@ -16,7 +17,8 @@ "component-param-localremote", "component-param-remote", "datamodels-datatypes-array", - "datamodels-datatypes-integer" + "datamodels-datatypes-integer", + "datamodels-datatypes-string" ], "BlackList": [ "basic-get-querystr", From 42ca4425eef6e796363614c62c1dbf59f5dd52d5 Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 4 Aug 2020 20:44:07 +0800 Subject: [PATCH 24/61] support header (#648) * support header * fix some issue for enum and header * fix choice * fix enum * Only validate sealedchoice Co-authored-by: xichen Co-authored-by: Xiaogang --- powershell/autorest-configuration.md | 23 ++- powershell/enums/namespace.ts | 2 +- powershell/internal/project.ts | 2 +- powershell/llcsharp/model/model-class.ts | 22 +-- powershell/llcsharp/model/namespace.ts | 5 + powershell/llcsharp/operation/api-class.ts | 4 +- powershell/llcsharp/operation/method.ts | 8 +- powershell/llcsharp/schema/schema-resolver.ts | 3 +- powershell/llcsharp/schema/string.ts | 6 +- powershell/main.ts | 2 + powershell/plugins/cs-namer-v2.ts | 5 +- powershell/plugins/plugin-tweak-m4-model.ts | 83 +++++++++ powershell/plugins/plugin-tweak-model.ts | 170 ++++++++++++++++-- powershell/utils/http-definitions.ts | 44 +++++ 14 files changed, 340 insertions(+), 39 deletions(-) create mode 100644 powershell/plugins/plugin-tweak-m4-model.ts create mode 100644 powershell/utils/http-definitions.ts diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 6eca7c67537..4ed72061ef5 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -119,8 +119,14 @@ pipeline: input: tweakcodemodel # --- extension powershell based on modelerfour - tweakcodemodel-v2: + + # Fix the code model gap between m3 and m4 + tweakm4codemodel: input: modelerfour/identity + + tweakcodemodel-v2: + input: tweakm4codemodel + # input: clicommon/identity tweakcodemodelazure-v2: input: tweakcodemodel-v2 @@ -446,4 +452,17 @@ verb-mapping: Write: Write ``` - +``` yaml +cli: + reason: 'Keep same as modelerfour' + naming: + default: + parameter: 'camel' + property: 'camel' + operation: 'pascal' + operationGroup: 'pascal' + choice: 'pascal' + choiceValue: 'pascal' + constant: 'pascal' + type: 'pascal' +``` \ No newline at end of file diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index 23f9f6b302a..63d3ff41670 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -130,7 +130,7 @@ export class NewEnumNamespace extends Namespace { super('Support', parent); this.apply(objectInitializer); //const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] - const enumInfos = [...state.model.schemas.sealedChoices || []] + const enumInfos = [...state.model.schemas.sealedChoices ?? []] .filter((choice) => !choice.language.csharp?.skip) .map((choice) => { return { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 0a0a071cedf..4878ced8f6f 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -17,7 +17,7 @@ import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; -import { Schema as NewSchema, BooleanSchema, SchemaType } from '@azure-tools/codemodel'; +import { BooleanSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index c80abb95ba9..7a962bd4363 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -18,7 +18,7 @@ import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } f import { Schema } from '../code-model'; import { DictionaryImplementation } from './model-class-dictionary'; import { Languages, Language, Schema as NewSchema } from '@azure-tools/codemodel'; -import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; +import { VirtualProperty as NewVirtualProperty, getAllVirtualProperties as newGetAllVirtualProperties } from '../../utils/schema'; export function getVirtualPropertyName(vp?: VirtualProperty): string { @@ -928,23 +928,23 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } } private addHeaderDeserializer() { - const avp = getAllVirtualProperties(this.schema.language.csharp?.virtualProperties); + const avp = newGetAllVirtualProperties(this.schema.language.csharp?.virtualProperties); const headers = new Parameter('headers', System.Net.Http.Headers.HttpResponseHeaders); const readHeaders = new Method(`${ClientRuntime.IHeaderSerializable}.ReadHeaders`, undefined, { access: Access.Explicit, parameters: [headers], }); - const used = false; + let used = false; - // skip-for-time-being - // for (const headerProperty of values(avp).where(each => each.property.details.csharp[HeaderProperty] === HeaderPropertyType.HeaderAndBody || each.property.details.csharp[HeaderProperty] === HeaderPropertyType.Header)) { - // used = true; - // const t = `((${headerProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - // const values = `__${camelCase([...deconstruct(headerProperty.property.serializedName), 'Header'])}`; - // const td = this.state.project.modelsNamespace.resolveTypeDeclaration(headerProperty.property.schema, false, this.state.path('schema')); - // readHeaders.add(If(`${valueOf(headers)}.TryGetValues("${headerProperty.property.serializedName}", out var ${values})`, `${t}.${headerProperty.name} = ${td.deserializeFromContainerMember(KnownMediaType.Header, headers, values, td.defaultOfType)};`)); - // } + for (const headerProperty of values(avp).where(each => each.property.language.csharp?.[HeaderProperty] === HeaderPropertyType.HeaderAndBody || each.property.language.csharp?.[HeaderProperty] === HeaderPropertyType.Header)) { + used = true; + headerProperty.property.schema + const t = `((${headerProperty.originalContainingSchema.language.csharp?.fullInternalInterfaceName})this)`; + const values = `__${camelCase([...deconstruct(headerProperty.property.serializedName), 'Header'])}`; + const td = this.state.project.modelsNamespace.NewResolveTypeDeclaration(headerProperty.property.schema, false, this.state); + readHeaders.add(If(`${valueOf(headers)}.TryGetValues("${headerProperty.property.serializedName}", out var ${values})`, `${t}.${headerProperty.name} = ${td.deserializeFromContainerMember(KnownMediaType.Header, headers, values, td.defaultOfType)};`)); + } if (used) { this.interfaces.push(ClientRuntime.IHeaderSerializable); this.add(readHeaders); diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index a437aa8ce57..8f1dbe0d54b 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -184,6 +184,11 @@ export class NewModelsNamespace extends Namespace { this.NewResolveTypeDeclaration(schema, true, state); } } + if (schemas.sealedChoices) { + for (const schema of schemas.sealedChoices) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } //todo, need to add support for other types } diff --git a/powershell/llcsharp/operation/api-class.ts b/powershell/llcsharp/operation/api-class.ts index f3045b86c00..34aa980a8be 100644 --- a/powershell/llcsharp/operation/api-class.ts +++ b/powershell/llcsharp/operation/api-class.ts @@ -57,7 +57,9 @@ export class ApiClass extends Class { for (const operation of operationGroup.operations) { const operationMethod = new NewOperationMethod(this, operation, false, state); this.addMethod(operationMethod); - if ([...values(operation.parameters).where(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { + // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it + const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); + if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { // method has parameters in the path, so it could support '...ViaIdentity' const identityMethod = new NewOperationMethod(this, operation, true, state); identityMethod.emitCall(false); diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 80569568164..1efd7117ed6 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -346,7 +346,6 @@ export class NewOperationMethod extends Method { this.description = this.operation.language.csharp?.description || ''; // add body paramter if there should be one. - // skip-for-time-being if (this.operation.requests && this.operation.requests.length && this.operation.requests[0].parameters && this.operation.requests[0].parameters.length) { // this request does have a request body. const param = this.operation.requests[0].parameters[0]; @@ -359,11 +358,8 @@ export class NewOperationMethod extends Method { } for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { - const responseType = (response).schema ? state.project.modelsNamespace.NewResolveTypeDeclaration(((response).schema), true, state) : null; - //skip-for-time-being - //const headerType = response.headerSchema ? state.project.modelsNamespace.NewResolveTypeDeclaration(response.headerSchema, true, state) : null; - const headerType = null; + const headerType = response.language.default.headerSchema ? state.project.modelsNamespace.NewResolveTypeDeclaration(response.language.default.headerSchema, true, state) : null; const newCallbackParameter = new NewCallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); this.addParameter(newCallbackParameter); this.callbacks.push(newCallbackParameter); @@ -473,7 +469,7 @@ export class NewOperationMethod extends Method { // content length is set when the request body is set continue; } - yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.csharp?.name || hp.param.language.default.name, ClientRuntime.SerializationMode.None); + yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.csharp?.serializedName || hp.param.language.default.serializedName, ClientRuntime.SerializationMode.None); } yield EOL; } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 0885d402d7e..6a9faa67bee 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -181,6 +181,7 @@ export class NewSchemaDefinitionResolver { } return this.add(schema, new NewObjectImplementation(schema)); } + case SchemaType.SealedChoice: case SchemaType.String: { return new NewString(schema, required); @@ -226,8 +227,6 @@ export class NewSchemaDefinitionResolver { throw new Error('Unknown Model. Fatal.'); } case SchemaType.Choice: - return new NewString(schema, required); - case SchemaType.SealedChoice: return new NewEnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index 8d8316e78fe..b49b4ac7b43 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -12,7 +12,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { ChoiceSchema, Schema as NewSchema, StringSchema } from '@azure-tools/codemodel'; +import { ChoiceSchema, Schema as NewSchema, SchemaType, SealedChoiceSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; @@ -398,10 +398,10 @@ ${this.validateEnum(eventListener, property)} return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${pattern}");`; } private validateEnum(eventListener: Variable, property: Variable): string { - if (!(this.schema instanceof ChoiceSchema)) { + if (this.schema.type !== SchemaType.SealedChoice) { return ''; } - const choiceValues = this.schema.choices.map((c) => c.value); + const choiceValues = (this.schema).choices.map((c) => c.value); return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${choiceValues.joinWith((v) => `@"${v}"`)});`; } } diff --git a/powershell/main.ts b/powershell/main.ts index 5aa78458fc3..b8cfe84ed64 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -21,6 +21,7 @@ import { llcsharpV2 } from './plugins/llcsharp-v2'; import { powershellV2 } from './plugins/powershell-v2'; import { addCompleterV2 } from './plugins/add-azure-completers-v2'; import { applyModifiersV2 } from './plugins/modifiers-v2'; +import { tweakM4ModelPlugin } from './plugins/plugin-tweak-m4-model'; require('source-map-support').install(); @@ -34,6 +35,7 @@ export async function main() { pluginHost.Add('csnamer', csnamer); pluginHost.Add('llcsharp', llcsharp); // Following are plugins moved from remodeler + pluginHost.Add('tweakm4codemodel', tweakM4ModelPlugin); pluginHost.Add('tweakcodemodel-v2', tweakModelPlugin); pluginHost.Add('tweakcodemodelazure-v2', tweakModelAzurePluginV2); pluginHost.Add('create-virtual-properties-v2', createInlinedPropertiesPlugin); diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 753d2e9338c..ac6aa0c28da 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -200,7 +200,8 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso // per responseCode const response = rsp; const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state) : undefined; - // const headerTypeDefinition = response.headerSchema ? resolver.resolveTypeDeclaration(response.headerSchema, true, state.path('schemas', response.headerSchema.details.default.name)) : undefined; + const headerSchema = response.language.default.headerSchema; + const headerTypeDefinition = headerSchema ? resolver.resolveTypeDeclaration(headerSchema, true, state.path('schemas', headerSchema.language.default.name)) : undefined; let code = (System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]] ? System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]].value : response.protocol.http?.statusCodes[0]).replace('global::System.Net.HttpStatusCode', ''); let rawValue = code.replace(/\./, ''); if (response.protocol.http?.statusCodes[0] === 'default' || rawValue === 'default' || '') { @@ -211,7 +212,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso response.language.csharp = { ...response.language.default, responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '', - headerType: '', + headerType: headerTypeDefinition ? headerTypeDefinition.declaration : '', name: (length(response.protocol.http?.mimeTypes) <= 1) ? camelCase(fixLeadingNumber(deconstruct(`on ${code}`))) : // the common type (or the only one.) camelCase(fixLeadingNumber(deconstruct(`on ${code} ${response.protocol.http?.mimeTypes[0]}`))), diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts new file mode 100644 index 00000000000..7cb8e0f7413 --- /dev/null +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { CodeModel, HttpHeader, ObjectSchema, Property } from '@azure-tools/codemodel'; +import { serialize } from '@azure-tools/codegen'; +import { PwshModel } from '../utils/PwshModel'; +import { NewModelState } from '../utils/model-state'; +import { StatusCodes } from '../utils/http-definitions'; + +import { Host } from '@azure-tools/autorest-extension-base'; + + +type State = NewModelState; + +async function tweakModel(state: State): Promise { + const model = state.model; + + addResponseHeaderSchema(model); + + return model; +} + +function addResponseHeaderSchema(model: CodeModel) { + // In remodler, each operations response headers will has its own scheam. Each header will be schema's property. But in m4, there won't be a schema for headers. + // To keep backward compatiable, we will create headers schema here + + model.operationGroups.forEach((group) => { + group.operations?.forEach((op) => { + if (!op.responses) { + return; + } + op.responses.forEach((resp) => { + const headers = resp.protocol.http?.headers as Array; + if (headers === undefined) { + return; + } + + const responseCode = resp.protocol.http?.statusCodes?.[0]; + if (responseCode === undefined) { + return; + } + + // Follow naming pattern in m3 + const code = ((StatusCodes)[responseCode] || '') || responseCode; + const schemaName = `${group.language.default.name}_${op.language.default.name} ${code} ResponseHeaders`; + + const newSchema = model.schemas.objects?.find((schema) => schema.language.default.name === schemaName) || + new ObjectSchema(schemaName, ''); + newSchema.language.default.isHeaderModel = true; + + if (!model.schemas.objects) { + model.schemas.objects = []; + } + model.schemas.objects.push(newSchema); + + headers.forEach((head) => { + // We lost description and x-ms-client-name in m4. So newProp's description is empty and use header as serializedName + const newProp = new Property(head.header, '', head.schema, { + readOnly: false, + required: false, + serializedName: head.header + }); + newProp.language.default.HeaderProperty = 'Header'; + + if (!newSchema.properties) { + newSchema.properties = []; + } + newSchema.properties.push(newProp); + }); + + // Set response header use new schema + resp.language.default.headerSchema = newSchema; + }); + }); + }); +} + + +export async function tweakM4ModelPlugin(service: Host) { + const state = await new NewModelState(service).init(); + await service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); +} \ No newline at end of file diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 9f94a288b98..4b09be14815 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,10 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Property, codeModelSchema, CodeModel, Schema, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema } from '@azure-tools/codemodel'; +import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; -import { pascalCase, deconstruct, fixLeadingNumber, serialize } from '@azure-tools/codegen'; +import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; import { items, keys, values, Dictionary, length } from '@azure-tools/linq'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; @@ -13,6 +13,7 @@ import { NewModelState } from '../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { defaultCipherList } from 'constants'; import { NewString } from '../llcsharp/schema/string'; +import { JsonType } from '../utils/schema'; export const HeaderProperty = 'HeaderProperty'; export enum HeaderPropertyType { @@ -76,12 +77,8 @@ async function tweakModelV2(state: State): Promise { const model = state.model; const schemas = model.schemas; - const allSchemas: Schema[] = []; - for (const prop of Object.values(schemas)) { - if (Array.isArray(prop) && prop.length > 0 && prop[0] instanceof Schema) { - allSchemas.push(...prop); - } - } + // xichen: do we need other schema types? + const allSchemas: Schema[] = [...schemas.objects ?? [], ...schemas.choices ?? [], ...schemas.sealedChoices ?? []]; model.commands = { operations: new Dictionary(), @@ -129,6 +126,133 @@ async function tweakModelV2(state: State): Promise { universalId.properties.push(idProp); } + // xichen: do nothing in m3 logic. Comment it out + // if an operation has a response that has a schema with string/binary we should make the response application/octet-stream + // for (const operationGroups of values(model.operationGroups)) { + // for (const operation of values(operationGroups.operations)) { + // for (const response of values(operation.responses)) { + // if ((response as any).schema) { + // const respSchema = response as any; + // if (respSchema.type === SchemaType.String && respSchema.format === StringFormat.Binary) { + // // WHY WAS THIS HERE?! + // // response.mimeTypes = [KnownMediaType.Stream]; + // } + // } + // } + // } + // } + + // xichen: should be no duplicate properties in m4. Skip + // schemas that have parents and implement properties that are in the parent schemas + // will have the property dropped in the child schema + // for (const schema of values(model.schemas)) { + // if (length(schema.allOf) > 0) { + // if (!dropDuplicatePropertiesInChildSchemas(schema, state)) { + // throw new Error('Schemas are in conflict.'); + // } + // } + // } + + + if (await state.getValue('use-storage-pipeline', false)) { + // 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 operationGroups of values(model.operationGroups)) { + for (const operation of values(operationGroups.operations)) { + for (const response of values(operation.responses)) { + // for a given response, find the possible models that can be returned from the service + for (const header of values(response.protocol.http?.headers)) { + + if (!(response as any).schema) { + // no response schema? can we fake one? + // service.Message({ Channel: Channel.Debug, Text: `${header.key} is in ${operation.details.default.name} but there is no response model` }); + continue; + } + + + // 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 ((response as any).schema.type === SchemaType.Object) { + const respSchema = (response as any).schema as ObjectSchema; + const curHeader = header as any; + const headerKey = curHeader as string; + + respSchema.language.default.hasHeaders = true; + + const property = values(getAllProperties(respSchema)).first((each) => each.language.default.name === headerKey); + if (!property) { + state.message({ Channel: Channel.Debug, Text: `Adding header property '${headerKey}' to model ${respSchema.language.default.name}` }); + + // create a property for the header value + const newProperty = new Property(headerKey, curHeader.description, curHeader.schema); + newProperty.language.default.required = false; + + // mark it that it's a header-only property + newProperty.language.default[HeaderProperty] = HeaderPropertyType.Header; + + // add it to this model. + if (!respSchema.properties) { + respSchema.properties = []; + } + respSchema.properties.push(newProperty); + } else { + // there is a property with this name already. + // was this previously declared as a header only property? + if (!property.language.default[HeaderProperty]) { + + state.message({ Channel: Channel.Debug, Text: `Property ${headerKey} in model ${respSchema.language.default.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.language.default[HeaderProperty] = HeaderPropertyType.HeaderAndBody; + property.language.default.name = headerKey; + } + } + } + } + } + } + } + } + + // remove well-known header parameters from operations and add mark the operation has supporting that feature + + for (const operationGruops of values(model.operationGroups)) { + for (const operation of values(operationGruops.operations)) { + // if we have an operation with a body, and content-type is a multipart/formdata + // then we should go thru the parameters of the body and look for a string/binary parameters + // and remember to add another parameter for the filename of the string/binary + const request = operation.requests?.[0]; + request?.parameters?.filter((param) => param.schema.type !== SchemaType.Object && param.protocol.http?.in === 'body' && param.protocol.http?.style === KnownMediaType.Multipart) + .forEach((param) => { + for (const prop of values(getAllProperties(param.schema as ObjectSchema))) { + if (prop.schema.type === SchemaType.Binary) { + prop.language.default.isNamedStream = true; + } + } + }); + + // move well-known hearder parameters into details, and we can process them in the generator how we please. + // operation.details.default.headerparameters = values(operation.parameters).where(p => p.in === ParameterLocation.Header && ['If-Match', 'If-None-Match'].includes(p.name)).toArray(); + + // remove if-match and if-none-match parameters from the operation itself. + // operation.parameters = values(operation.parameters).where(p => !(p.in === ParameterLocation.Header && ['If-Match', 'If-None-Match'].includes(p.name))).toArray(); + + } + } + // identify models that are polymorphic in nature for (const schema of allSchemas) { if (schema instanceof ObjectSchema) { @@ -172,13 +296,39 @@ async function tweakModelV2(state: State): Promise { // properties with an enum single value are constants // add the constant value property.language.default.constantValue = choiceSchema.choices[0].value; - - // xichen: Do we need skip? } } } } + // xichen: Do we need skip? + // const enumsToSkip = new Set(); + // // identify properties that are constants + // for (const schema of values(model.schemas)) { + // for (const property of values(schema.properties)) { + // if (property.details.default.required && length(property.schema.enum) === 1) { + // // properties with an enum single value are constants + // // add the constant value + // property.details.default.constantValue = property.schema.enum[0]; + + // // mark as skip the generation of this model + // enumsToSkip.add(property.schema.details.default.uid); + + // // make it a string and keep its name + // property.schema = new Schema(property.schema.details.default.name, { type: property.schema.type }); + // } else { + // enumsToSkip.delete(property.schema.details.default.uid); + // } + // } + // } + + // // mark enums that shouldn't be generated + // for (const schema of values(model.schemas)) { + // if (enumsToSkip.has(schema.details.default.uid)) { + // schema.details.default.skip = true; + // } + // } + return model; } // async function tweakModel(state: State): Promise { diff --git a/powershell/utils/http-definitions.ts b/powershell/utils/http-definitions.ts new file mode 100644 index 00000000000..cbf5a9cfd79 --- /dev/null +++ b/powershell/utils/http-definitions.ts @@ -0,0 +1,44 @@ +export const StatusCodes = { + 100: 'Continue', + 101: 'SwitchingProtocols', + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'NonAuthoritativeInformation', + 204: 'NoContent', + 205: 'ResetContent', + 206: 'PartialContent', + 300: 'Ambiguous', + 301: 'Moved', + 302: 'Redirect', + 303: 'SeeOther', + 304: 'NotModified', + 305: 'UseProxy', + 306: 'Unused', + 307: 'TemporaryRedirect', + 400: 'BadRequest', + 401: 'Unauthorized', + 402: 'PaymentRequired', + 403: 'Forbidden', + 404: 'NotFound', + 405: 'MethodNotAllowed', + 406: 'NotAcceptable', + 407: 'ProxyAuthenticationRequired', + 408: 'RequestTimeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'LengthRequired', + 412: 'PreconditionFailed', + 413: 'RequestEntityTooLarge', + 414: 'RequestUriTooLong', + 415: 'UnsupportedMediaType', + 416: 'RequestedRangeNotSatisfiable', + 417: 'ExpectationFailed', + 426: 'UpgradeRequired', + 500: 'InternalServerError', + 501: 'NotImplemented', + 502: 'BadGateway', + 503: 'ServiceUnavailable', + 504: 'GatewayTimeout', + 505: 'HttpVersionNotSupported' +}; \ No newline at end of file From 7fef9bfc5175d3bafe597b7309841b1d5144514a Mon Sep 17 00:00:00 2001 From: LucasYao93 <53558334+LucasYao93@users.noreply.github.com> Date: Wed, 5 Aug 2020 09:00:07 +0800 Subject: [PATCH 25/61] Add test cases of autorest extension. (#647) * Add test cases of autorest extension. * Add test cases of directive. * Add test case of directive. --- tests-upgrade/.gitignore | 5 +- tests-upgrade/basic-get-querystr/readme.md | 9 + tests-upgrade/basic-get-querystr/swagger.json | 61 ++++++ tests-upgrade/basic-request-methods/readme.md | 9 + .../basic-request-methods/swagger.json | 89 +++++++++ .../component-definitions-remote/readme.md | 9 + .../component-definitions-remote/swagger.json | 59 ++++++ .../component-definitions-url/readme.md | 9 + .../component-definitions-url/swagger.json | 59 ++++++ tests-upgrade/datamodels-enums/readme.md | 10 + tests-upgrade/datamodels-enums/swagger.json | 73 +++++++ .../directive-aliasremoval/readme.md | 14 ++ .../directive-aliasremoval/swagger.json | 87 ++++++++ tests-upgrade/directive-cmdlet/readme.md | 53 +++++ tests-upgrade/directive-cmdlet/swagger.json | 188 ++++++++++++++++++ tests-upgrade/directive-enum/readme.md | 16 ++ tests-upgrade/directive-enum/swagger.json | 78 ++++++++ tests-upgrade/directive-model/readme.md | 28 +++ tests-upgrade/directive-model/swagger.json | 135 +++++++++++++ tests-upgrade/directive-parameter/readme.md | 38 ++++ .../directive-parameter/swagger.json | 185 +++++++++++++++++ tests-upgrade/directive-tableformat/readme.md | 23 +++ .../directive-tableformat/swagger.json | 75 +++++++ tests-upgrade/examples/OperationsList.json | 65 ++++++ tests-upgrade/examples/RemoteDefinitions.json | 103 ++++++++++ tests-upgrade/examples/WorkspaceCreate.json | 89 +++++++++ .../WorkspaceCreateWithParameters.json | 114 +++++++++++ tests-upgrade/examples/WorkspaceDelete.json | 13 ++ tests-upgrade/examples/WorkspaceGet.json | 47 +++++ .../examples/WorkspaceGetParameters.json | 60 ++++++ tests-upgrade/examples/WorkspaceUpdate.json | 55 +++++ .../WorkspacesListByResourceGroup.json | 86 ++++++++ .../WorkspacesListBySubscription.json | 85 ++++++++ .../extension-ms-azureresource/readme.md | 10 + .../extension-ms-azureresource/swagger.json | 79 ++++++++ .../extension-ms-clientflatten/readme.md | 10 + .../extension-ms-clientflatten/swagger.json | 80 ++++++++ .../extension-ms-clientname/readme.md | 10 + .../extension-ms-clientname/swagger.json | 78 ++++++++ .../extension-ms-discriminatorvalue/readme.md | 10 + .../swagger.json | 66 ++++++ tests-upgrade/extension-ms-enum/readme.md | 10 + tests-upgrade/extension-ms-enum/swagger.json | 80 ++++++++ tests-upgrade/extension-ms-examples/readme.md | 10 + .../extension-ms-examples/swagger.json | 64 ++++++ .../readme.md | 10 + .../swagger.json | 60 ++++++ .../extension-ms-mutability/readme.md | 10 + .../extension-ms-mutability/swagger.json | 86 ++++++++ tests-upgrade/extension-ms-pageable/readme.md | 10 + .../extension-ms-pageable/swagger.json | 71 +++++++ .../extension-ms-paramlocation/readme.md | 10 + .../extension-ms-paramlocation/swagger.json | 73 +++++++ 53 files changed, 2865 insertions(+), 1 deletion(-) create mode 100644 tests-upgrade/basic-get-querystr/readme.md create mode 100644 tests-upgrade/basic-get-querystr/swagger.json create mode 100644 tests-upgrade/basic-request-methods/readme.md create mode 100644 tests-upgrade/basic-request-methods/swagger.json create mode 100644 tests-upgrade/component-definitions-remote/readme.md create mode 100644 tests-upgrade/component-definitions-remote/swagger.json create mode 100644 tests-upgrade/component-definitions-url/readme.md create mode 100644 tests-upgrade/component-definitions-url/swagger.json create mode 100644 tests-upgrade/datamodels-enums/readme.md create mode 100644 tests-upgrade/datamodels-enums/swagger.json create mode 100644 tests-upgrade/directive-aliasremoval/readme.md create mode 100644 tests-upgrade/directive-aliasremoval/swagger.json create mode 100644 tests-upgrade/directive-cmdlet/readme.md create mode 100644 tests-upgrade/directive-cmdlet/swagger.json create mode 100644 tests-upgrade/directive-enum/readme.md create mode 100644 tests-upgrade/directive-enum/swagger.json create mode 100644 tests-upgrade/directive-model/readme.md create mode 100644 tests-upgrade/directive-model/swagger.json create mode 100644 tests-upgrade/directive-parameter/readme.md create mode 100644 tests-upgrade/directive-parameter/swagger.json create mode 100644 tests-upgrade/directive-tableformat/readme.md create mode 100644 tests-upgrade/directive-tableformat/swagger.json create mode 100644 tests-upgrade/examples/OperationsList.json create mode 100644 tests-upgrade/examples/RemoteDefinitions.json create mode 100644 tests-upgrade/examples/WorkspaceCreate.json create mode 100644 tests-upgrade/examples/WorkspaceCreateWithParameters.json create mode 100644 tests-upgrade/examples/WorkspaceDelete.json create mode 100644 tests-upgrade/examples/WorkspaceGet.json create mode 100644 tests-upgrade/examples/WorkspaceGetParameters.json create mode 100644 tests-upgrade/examples/WorkspaceUpdate.json create mode 100644 tests-upgrade/examples/WorkspacesListByResourceGroup.json create mode 100644 tests-upgrade/examples/WorkspacesListBySubscription.json create mode 100644 tests-upgrade/extension-ms-azureresource/readme.md create mode 100644 tests-upgrade/extension-ms-azureresource/swagger.json create mode 100644 tests-upgrade/extension-ms-clientflatten/readme.md create mode 100644 tests-upgrade/extension-ms-clientflatten/swagger.json create mode 100644 tests-upgrade/extension-ms-clientname/readme.md create mode 100644 tests-upgrade/extension-ms-clientname/swagger.json create mode 100644 tests-upgrade/extension-ms-discriminatorvalue/readme.md create mode 100644 tests-upgrade/extension-ms-discriminatorvalue/swagger.json create mode 100644 tests-upgrade/extension-ms-enum/readme.md create mode 100644 tests-upgrade/extension-ms-enum/swagger.json create mode 100644 tests-upgrade/extension-ms-examples/readme.md create mode 100644 tests-upgrade/extension-ms-examples/swagger.json create mode 100644 tests-upgrade/extension-ms-longruningoperation/readme.md create mode 100644 tests-upgrade/extension-ms-longruningoperation/swagger.json create mode 100644 tests-upgrade/extension-ms-mutability/readme.md create mode 100644 tests-upgrade/extension-ms-mutability/swagger.json create mode 100644 tests-upgrade/extension-ms-pageable/readme.md create mode 100644 tests-upgrade/extension-ms-pageable/swagger.json create mode 100644 tests-upgrade/extension-ms-paramlocation/readme.md create mode 100644 tests-upgrade/extension-ms-paramlocation/swagger.json diff --git a/tests-upgrade/.gitignore b/tests-upgrade/.gitignore index dc9b2375c7a..6b78566a203 100644 --- a/tests-upgrade/.gitignore +++ b/tests-upgrade/.gitignore @@ -1 +1,4 @@ -generated \ No newline at end of file +generated +generate + +CompareResult \ No newline at end of file diff --git a/tests-upgrade/basic-get-querystr/readme.md b/tests-upgrade/basic-get-querystr/readme.md new file mode 100644 index 00000000000..43b8fe48491 --- /dev/null +++ b/tests-upgrade/basic-get-querystr/readme.md @@ -0,0 +1,9 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json +``` diff --git a/tests-upgrade/basic-get-querystr/swagger.json b/tests-upgrade/basic-get-querystr/swagger.json new file mode 100644 index 00000000000..8ec03daef8f --- /dev/null +++ b/tests-upgrade/basic-get-querystr/swagger.json @@ -0,0 +1,61 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/users": { + "get": { + "tags": [ + "users" + ], + "operationId": "users_Get", + "description": "get user list.", + "parameters": [ + { + "in": "query", + "name": "role", + "type": "string", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/basic-request-methods/readme.md b/tests-upgrade/basic-request-methods/readme.md new file mode 100644 index 00000000000..43b8fe48491 --- /dev/null +++ b/tests-upgrade/basic-request-methods/readme.md @@ -0,0 +1,9 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json +``` diff --git a/tests-upgrade/basic-request-methods/swagger.json b/tests-upgrade/basic-request-methods/swagger.json new file mode 100644 index 00000000000..c29f5743bb5 --- /dev/null +++ b/tests-upgrade/basic-request-methods/swagger.json @@ -0,0 +1,89 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/users": { + "get": { + "tags": [ + "users" + ], + "operationId": "users_Get", + "description": "get user list.", + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "tags": [ + "users" + ], + "operationId": "users_Delete", + "description": "delete a user.", + "responses": { + "200": { + "description": "OK" + } + } + }, + "put": { + "tags": [ + "users" + ], + "operationId": "users_CreateOrUpdate", + "description": "Create or Update a user.", + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "tags": [ + "users" + ], + "operationId": "users_Update", + "description": "Update a user.", + "responses": { + "200": { + "description": "OK" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-definitions-remote/readme.md b/tests-upgrade/component-definitions-remote/readme.md new file mode 100644 index 00000000000..43b8fe48491 --- /dev/null +++ b/tests-upgrade/component-definitions-remote/readme.md @@ -0,0 +1,9 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json +``` diff --git a/tests-upgrade/component-definitions-remote/swagger.json b/tests-upgrade/component-definitions-remote/swagger.json new file mode 100644 index 00000000000..06c53dc20f4 --- /dev/null +++ b/tests-upgrade/component-definitions-remote/swagger.json @@ -0,0 +1,59 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/xxxx-xxxx-xxxx/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListBySubscription", + "description": "Gets all the workspaces within a subscription.", + "responses": { + "200": { + "description": "OK - Returns an array of workspaces." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../examples/RemoteDefinitions.json#/definitions/ErrorResponse" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-definitions-url/readme.md b/tests-upgrade/component-definitions-url/readme.md new file mode 100644 index 00000000000..43b8fe48491 --- /dev/null +++ b/tests-upgrade/component-definitions-url/readme.md @@ -0,0 +1,9 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json +``` diff --git a/tests-upgrade/component-definitions-url/swagger.json b/tests-upgrade/component-definitions-url/swagger.json new file mode 100644 index 00000000000..3c7b35cbfe6 --- /dev/null +++ b/tests-upgrade/component-definitions-url/swagger.json @@ -0,0 +1,59 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/xxxx-xxxx-xxxx/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListBySubscription", + "description": "Gets all the workspaces within a subscription.", + "responses": { + "200": { + "description": "OK - Returns an array of workspaces." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "https://github.com/LucasYao93/autorest.powershell/tree/lucas/modelerfour-dev/tests-upgrade/examples/RemoteDefinitions.json#definitions/ErrorResponse" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-enums/readme.md b/tests-upgrade/datamodels-enums/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-enums/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-enums/swagger.json b/tests-upgrade/datamodels-enums/swagger.json new file mode 100644 index 00000000000..efa7111df69 --- /dev/null +++ b/tests-upgrade/datamodels-enums/swagger.json @@ -0,0 +1,73 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup/{resourceGroup}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + } + ], + "responses": { + "200": { + "description": "OK-Return workspace." + } + } + } + } + }, + "parameters": { + "ResourceGroupName":{ + "in": "path", + "name": "resourceGroup", + "description": "Resource group name", + "required": true, + "schema": { + "type": "string", + "enum": [ + "azure cloud", + "azure prod" + ] + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-aliasremoval/readme.md b/tests-upgrade/directive-aliasremoval/readme.md new file mode 100644 index 00000000000..0f616b88835 --- /dev/null +++ b/tests-upgrade/directive-aliasremoval/readme.md @@ -0,0 +1,14 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + parameter-name: ResourceGroupName + clear-alias: true +``` diff --git a/tests-upgrade/directive-aliasremoval/swagger.json b/tests-upgrade/directive-aliasremoval/swagger.json new file mode 100644 index 00000000000..53ed81c131f --- /dev/null +++ b/tests-upgrade/directive-aliasremoval/swagger.json @@ -0,0 +1,87 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/ResourceGroupName/{ResourceGroupName}": { + "get": { + "tags": [ + "ClearRename" + ], + "operationId": "ClearRename_Get", + "description": "rename the Model", + "parameters": [ + {"$ref": "#/parameters/ResourceGroup"} + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "parameters": { + "ResourceGroup": { + "name": "ResourceGroupName", + "in": "path", + "type": "string", + "required": true, + "description": "Resource Group Name." + } + }, + "definitions": { + "ResourceGroupName": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-cmdlet/readme.md b/tests-upgrade/directive-cmdlet/readme.md new file mode 100644 index 00000000000..ba2e53e840b --- /dev/null +++ b/tests-upgrade/directive-cmdlet/readme.md @@ -0,0 +1,53 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + verb: Get + subject: VirtualMachine + set: + subject: VM + - where: + subject: (^Configuration)(.*) + set: + subject: Config$2 + - select: command + where: + verb: Get + subject: Object + parameter-name: Id + set: + subject: obj + - where: + verb: Get + subject: ResourceGroup + set: + alias: Get-RG + - where: + verb: Get + subject: MultipleAlias + set: + alias: + - Get-MA1 + - Get-MA2 + - where: + verb: patch + subject: CmdletHide + hide: true + - where: + subject: ConfigHide.* + hide: true + - where: + verb: Get + subject: Remove + remove: true + - where: + subject: RegexRemove.* + remove: true +``` diff --git a/tests-upgrade/directive-cmdlet/swagger.json b/tests-upgrade/directive-cmdlet/swagger.json new file mode 100644 index 00000000000..d6941714ff6 --- /dev/null +++ b/tests-upgrade/directive-cmdlet/swagger.json @@ -0,0 +1,188 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/VirtualMachine": { + "get": { + "tags": [ + "VirtualMachine" + ], + "operationId": "VirtualMachine_Get", + "description": "rename the cmdlet 'Get-VirtualMachine' to 'Get-VM'", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/ConfigurationStore": { + "get": { + "tags": [ + "ConfigurationStore" + ], + "operationId": "ConfigurationStore_Get", + "description": "This will change every cmdlet where the subject starts with 'Configuration'", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/ObjectId/Id/{Id}": { + "get": { + "tags": [ + "Object" + ], + "operationId": "Object_Get", + "description": "rename the cmdlet.", + "parameters": [ + {"$ref": "#/parameters/Id"} + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/ResourceGroup": { + "get": { + "tags": [ + "ResourceGroup" + ], + "operationId": "ResourceGroup_Get", + "description": "rename the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/MultipleAlias": { + "get": { + "tags": [ + "MultipleAlias" + ], + "operationId": "MultipleAlias_Get", + "description": "rename the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/CmdletHide": { + "get": { + "tags": [ + "CmdletHide" + ], + "operationId": "CmdletHide_Get", + "description": "Hide the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "tags": [ + "CmdletHide" + ], + "operationId": "CmdletHide_Update", + "description": "Hide the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/HideRegexCmdlet": { + "get": { + "tags": [ + "HideRegexCmdlet" + ], + "operationId": "ConfigHide_Get", + "description": "Hide the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/Remove": { + "get": { + "tags": [ + "Remove" + ], + "operationId": "Remove_Get", + "description": "Remove the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/RegexRemove": { + "get": { + "tags": [ + "RegexRemove" + ], + "operationId": "RegexRemoveTest_Get", + "description": "Regex Remove the cmdlet.", + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "parameters": { + "Id": { + "name": "Id", + "in": "path", + "type": "string", + "required": true + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-enum/readme.md b/tests-upgrade/directive-enum/readme.md new file mode 100644 index 00000000000..071d8f56550 --- /dev/null +++ b/tests-upgrade/directive-enum/readme.md @@ -0,0 +1,16 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + enum-name: provisioningState + enum-value-name: Upgrading + set: + enum-value-name: Update +``` diff --git a/tests-upgrade/directive-enum/swagger.json b/tests-upgrade/directive-enum/swagger.json new file mode 100644 index 00000000000..ccb13464b7b --- /dev/null +++ b/tests-upgrade/directive-enum/swagger.json @@ -0,0 +1,78 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + } + } + } + } + }, + "definitions": { + "CanonicalSupportPlanProperties": { + "type": "object", + "description": "The properties of the Canonical support plan.", + "properties": { + "provisioningState": { + "type": "string", + "description": "The provisioning state of the resource.", + "enum": [ + "Succeeded", + "Failed", + "Cancelled", + "Purchasing", + "Downgrading", + "Cancelling", + "Upgrading" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-model/readme.md b/tests-upgrade/directive-model/readme.md new file mode 100644 index 00000000000..600c44c596b --- /dev/null +++ b/tests-upgrade/directive-model/readme.md @@ -0,0 +1,28 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + model-name: Resource + set: + model-name: AzureResource + - where: + model-name: ^KeyValue(.*) + set: + model-name: kv$1 + - where: + model-name: VirtualMachine + property-name: VirtualMachineName + set: + property-name: Name + - where: + property-name: (.*)Azure + set: + property-name: Az +``` diff --git a/tests-upgrade/directive-model/swagger.json b/tests-upgrade/directive-model/swagger.json new file mode 100644 index 00000000000..949c05c3ec9 --- /dev/null +++ b/tests-upgrade/directive-model/swagger.json @@ -0,0 +1,135 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/ModelRename": { + "get": { + "tags": [ + "ModelRename" + ], + "operationId": "ModelRename_Get", + "description": "rename the Model", + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": { + "Resource": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + } + }, + "KeyValue": { + "description": "The core properties Key value", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified Key value Id for the Key value." + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the Key value" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the Key value. " + } + } + }, + "VirtualMachine": { + "description": "The core properties of VirtualMachine", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified VirtualMachine Id for the VirtualMachine." + }, + "VirtualMachineName": { + "readOnly": true, + "type": "string", + "description": "The name of the VirtualMachine" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the VirtualMachine." + } + } + }, + "AzureEnv": { + "description": "The core properties of AzureEnv", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified AzureEnv Id for the AzureEnv." + }, + "Name": { + "readOnly": true, + "type": "string", + "description": "The name of the AzureEnv" + }, + "typeAzure": { + "readOnly": true, + "type": "string", + "description": "The type of the AzureEnv." + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-parameter/readme.md b/tests-upgrade/directive-parameter/readme.md new file mode 100644 index 00000000000..149198a96df --- /dev/null +++ b/tests-upgrade/directive-parameter/readme.md @@ -0,0 +1,38 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + parameter-name: Sku + set: + parameter-name: SkuName + - where: + verb: Get + subject: VirtualMachineSize_Get + parameter-name: VirtualMachineSize + set: + parameter-name: VMSize + - where: + parameter-name: VirtualMachine + set: + alias: + - VM + - VMachine + - where: + parameter-name: ResourceGroup + set: + parameter-description: This is resource group name. + - where: + parameter-name: SubscriptionId + set: + default: + name: SubscriptionId Default + description: Gets the SubscriptionId from the current context. + script: '(Get-AzContext).Subscription.Id' +``` diff --git a/tests-upgrade/directive-parameter/swagger.json b/tests-upgrade/directive-parameter/swagger.json new file mode 100644 index 00000000000..14a301398f7 --- /dev/null +++ b/tests-upgrade/directive-parameter/swagger.json @@ -0,0 +1,185 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/SkuName/{Sku}": { + "get": { + "tags": [ + "Sku" + ], + "operationId": "Sku_Get", + "description": "Gets the Sku.", + "parameters": [ + {"$ref": "#/parameters/Sku"} + ], + "responses": { + "200": { + "description": "OK - Returns the Sku." + } + } + } + }, + "/VirtualMachineSize/{VirtualMachineSize}": { + "get": { + "tags": [ + "VirtualMachine" + ], + "operationId": "VirtualMachineSize_Get", + "description": "Get the Virtual Machine.", + "parameters": [ + {"$ref": "#/parameters/VirtualMachineSize"} + ], + "responses": { + "200": { + "description": "OK - Returns the Virtual Machine." + } + } + } + }, + "/VirtualMachine/{VirtualMachine}": { + "get": { + "tags": [ + "VirtualMachine" + ], + "operationId": "VirtualMachine_Get", + "description": "Get the Virtual Machine.", + "parameters": [ + {"$ref": "#/parameters/VirtualMachine"} + ], + "responses": { + "200": { + "description": "OK - Returns the Virtual Machine." + } + } + } + }, + "/Workspace/WorksapceName/{WorkspaceName}": { + "get": { + "tags":[ + "Workspace" + ], + "operationId": "Workspace_Get", + "description": "Get workspace", + "parameters": [ + {"$ref": "#/parameters/WorkspaceName"} + ], + "responses": { + "200": { + "description": "OK - Returns the Workspace." + } + } + } + }, + "/ResourceGroup/{ResourceGroup}": { + "get": { + "tags":[ + "ResourceGroup" + ], + "operationId": "ResourceGroup_Get", + "description": "Get ResourceGroup", + "parameters": [ + {"$ref": "#/parameters/ResourceGroup"} + ], + "responses": { + "200": { + "description": "OK - Returns the Resource Group." + } + } + } + }, + "/SubscriptionId/{SubscriptionId}": { + "get": { + "tags":[ + "Subscription" + ], + "operationId": "Subscription_Get", + "description": "Get SubscriptionId", + "parameters": [ + {"$ref": "#/parameters/SubscriptionId"} + ], + "responses": { + "200": { + "description": "OK - Returns the Subscription." + } + } + } + } + }, + "parameters": { + "Sku": { + "name": "Sku", + "in": "path", + "type": "string", + "required": true, + "description": "SKU for the resource." + }, + "VirtualMachineSize": { + "name": "VirtualMachineSize", + "in": "path", + "type": "string", + "required": true, + "description": "Virtual machine size." + }, + "VirtualMachine": { + "name": "VirtualMachine", + "in": "path", + "type": "string", + "required": true, + "description": "Virtual machine size." + }, + "WorkspaceName": { + "name": "WorkspaceName", + "in": "path", + "type": "string", + "required": true, + "description": "Workspace Name." + }, + "ResourceGroup": { + "name": "ResourceGroup", + "in": "path", + "type": "string", + "required": true, + "description": "Resource Group Name." + }, + "SubscriptionId": { + "name": "SubscriptionId", + "in": "path", + "type": "string", + "required": true, + "description": "Subscription Id." + } + } +} \ No newline at end of file diff --git a/tests-upgrade/directive-tableformat/readme.md b/tests-upgrade/directive-tableformat/readme.md new file mode 100644 index 00000000000..d09ec83598a --- /dev/null +++ b/tests-upgrade/directive-tableformat/readme.md @@ -0,0 +1,23 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +directive: + - where: + model-name: VirtualMachine + set: + format-table: + properties: + - Name + - ResourceGroup + labels: + ResourceGroup: Resource Group + width: + Name: 60 + ResourceGroup: 80 +``` diff --git a/tests-upgrade/directive-tableformat/swagger.json b/tests-upgrade/directive-tableformat/swagger.json new file mode 100644 index 00000000000..5df9d161802 --- /dev/null +++ b/tests-upgrade/directive-tableformat/swagger.json @@ -0,0 +1,75 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/TableFormatting": { + "get": { + "tags": [ + "TableFormatting" + ], + "operationId": "TableFormatting_Get", + "description": "Table Formatting", + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": { + "VirtualMachine": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified VirtualMachine Id for the VirtualMachine. " + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the VirtualMachine" + }, + "ResourceGroup": { + "readOnly": true, + "type": "string", + "description": "The type of the resource." + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/examples/OperationsList.json b/tests-upgrade/examples/OperationsList.json new file mode 100644 index 00000000000..4da476627d5 --- /dev/null +++ b/tests-upgrade/examples/OperationsList.json @@ -0,0 +1,65 @@ +{ + "parameters": { + "api-version": "2018-04-01" + }, + "responses": { + "200": { + "body": [ + { + "name": "Microsoft.Databricks/workspaces/read", + "display": { + "provider": "Microsoft Databricks", + "resource": "Workspace", + "operation": "List Workspaces", + "description": "Retrieves a list of workspaces." + } + }, + { + "name": "Microsoft.Databricks/workspaces/write", + "display": { + "provider": "Microsoft Databricks", + "resource": "Workspace", + "operation": "Create Workspace", + "description": "Creates an workspace." + } + }, + { + "name": "Microsoft.Databricks/workspaces/delete", + "display": { + "provider": "Microsoft Databricks", + "resource": "Workspace", + "operation": "Remove Workspace", + "description": "Removes an workspace." + } + }, + { + "name": "Microsoft.Databricks/workspaces/virtualNetworkPeerings/read", + "display": { + "provider": "Microsoft Databricks", + "resource": "Virtual Network Peering", + "operation": "Get Virtual Network Peering", + "description": "Gets the virtual network peering." + } + }, + { + "name": "Microsoft.Databricks/workspaces/virtualNetworkPeerings/write", + "display": { + "provider": "Microsoft Databricks", + "resource": "Virtual Network Peering", + "operation": "Add Virtual Network Peering", + "description": "Add or modify virtual network peering" + } + }, + { + "name": "Microsoft.Databricks/workspaces/virtualNetworkPeerings/delete", + "display": { + "provider": "Microsoft Databricks", + "resource": "Virtual Network Peering", + "operation": "Delete Virtual Network Peering", + "description": "Deletes a virtual network peering" + } + } + ] + } + } +} diff --git a/tests-upgrade/examples/RemoteDefinitions.json b/tests-upgrade/examples/RemoteDefinitions.json new file mode 100644 index 00000000000..547c57f8a9b --- /dev/null +++ b/tests-upgrade/examples/RemoteDefinitions.json @@ -0,0 +1,103 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + }, + "definitions": { + "ErrorDetail": { + "title": "Error details.", + "type": "object", + "properties": { + "code": { + "description": "The error's code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "target": { + "description": "Indicates which property in the request is responsible for the error.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorInfo": { + "title": "The code and message for an error.", + "type": "object", + "properties": { + "code": { + "description": "A machine readable error code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "details": { + "description": "error details.", + "type": "string" + }, + "innererror": { + "description": "Inner error details if they exist.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorResponse": { + "title": "Error response.", + "description": "Contains details when the response code indicates an error.", + "type": "object", + "properties": { + "error": { + "description": "The error details.", + "type": "string" + } + }, + "required": [ + "error" + ] + } + } +} diff --git a/tests-upgrade/examples/WorkspaceCreate.json b/tests-upgrade/examples/WorkspaceCreate.json new file mode 100644 index 00000000000..2c296267716 --- /dev/null +++ b/tests-upgrade/examples/WorkspaceCreate.json @@ -0,0 +1,89 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "workspaceName": "myWorkspace", + "api-version": "2018-04-01", + "parameters": { + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG" + }, + "location": "westus" + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Accepted", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + } + }, + "201": { + "body": { + "name": "myWorkspace", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": { + "environment": "dev" + }, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Accepted", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z" + } + } + } + } +} diff --git a/tests-upgrade/examples/WorkspaceCreateWithParameters.json b/tests-upgrade/examples/WorkspaceCreateWithParameters.json new file mode 100644 index 00000000000..4a6d36ecbcf --- /dev/null +++ b/tests-upgrade/examples/WorkspaceCreateWithParameters.json @@ -0,0 +1,114 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "workspaceName": "myWorkspace", + "api-version": "2018-04-01", + "parameters": { + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": { + "customVirtualNetworkId": { + "value": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/myNetwork" + }, + "customPublicSubnetName": { + "value": "myPublicSubnet" + }, + "customPrivateSubnetName": { + "value": "myPrivateSubnet" + } + } + }, + "location": "westus" + } + }, + "responses": { + "200": { + "headers": {}, + "body": { + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": { + "customPrivateSubnetName": { + "type": "String", + "value": "myPrivateSubnet" + }, + "customPublicSubnetName": { + "type": "String", + "value": "myPublicSubnet" + }, + "customVirtualNetworkId": { + "type": "String", + "value": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/myNetwork" + } + }, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + } + }, + "201": { + "headers": {}, + "body": { + "name": "myWorkspace", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": { + "environment": "dev" + }, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "provisioningState": "Accepted", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z" + } + } + } + } +} diff --git a/tests-upgrade/examples/WorkspaceDelete.json b/tests-upgrade/examples/WorkspaceDelete.json new file mode 100644 index 00000000000..affad060724 --- /dev/null +++ b/tests-upgrade/examples/WorkspaceDelete.json @@ -0,0 +1,13 @@ +{ + "parameters": { + "workspaceName": "myWorkspace", + "resourceGroupName": "rg", + "api-version": "2018-04-01", + "subscriptionId": "subid" + }, + "responses": { + "200": {}, + "202": {}, + "204": {} + } +} diff --git a/tests-upgrade/examples/WorkspaceGet.json b/tests-upgrade/examples/WorkspaceGet.json new file mode 100644 index 00000000000..48fe6d0b499 --- /dev/null +++ b/tests-upgrade/examples/WorkspaceGet.json @@ -0,0 +1,47 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "workspaceName": "myWorkspace", + "api-version": "2018-04-01" + }, + "responses": { + "200": { + "headers": {}, + "body": { + "name": "myWorkspace", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "sku": { + "name": "premium" + }, + "location": "East US 2", + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + } + } + } +} diff --git a/tests-upgrade/examples/WorkspaceGetParameters.json b/tests-upgrade/examples/WorkspaceGetParameters.json new file mode 100644 index 00000000000..7babe97ee78 --- /dev/null +++ b/tests-upgrade/examples/WorkspaceGetParameters.json @@ -0,0 +1,60 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "workspaceName": "myWorkspace", + "api-version": "2018-04-01" + }, + "responses": { + "200": { + "headers": {}, + "body": { + "name": "myWorkspace", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": { + "customPrivateSubnetName": { + "type": "String", + "value": "PrivateBob" + }, + "customPublicSubnetName": { + "type": "String", + "value": "PublicSarah" + }, + "customVirtualNetworkId": { + "type": "String", + "value": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/myNetwork" + } + }, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + } + } + } +} diff --git a/tests-upgrade/examples/WorkspaceUpdate.json b/tests-upgrade/examples/WorkspaceUpdate.json new file mode 100644 index 00000000000..766bbcd7872 --- /dev/null +++ b/tests-upgrade/examples/WorkspaceUpdate.json @@ -0,0 +1,55 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "workspaceName": "myWorkspace", + "api-version": "2018-04-01", + "parameters": { + "tags": { + "mytag1": "myvalue1" + } + } + }, + "responses": { + "200": { + "headers": {}, + "body": { + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": { + "mytag1": "myvalue1" + }, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "6666666666666666", + "workspaceUrl": "adb-6666666666666666.19.azuredatabricks.net" + } + } + }, + "202": {} + } +} diff --git a/tests-upgrade/examples/WorkspacesListByResourceGroup.json b/tests-upgrade/examples/WorkspacesListByResourceGroup.json new file mode 100644 index 00000000000..f8fad446745 --- /dev/null +++ b/tests-upgrade/examples/WorkspacesListByResourceGroup.json @@ -0,0 +1,86 @@ +{ + "parameters": { + "subscriptionId": "subid", + "resourceGroupName": "rg", + "api-version": "2018-04-01" + }, + "responses": { + "200": { + "headers": {}, + "body": { + "value": [ + { + "name": "myWorkspace1", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace1", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + }, + { + "name": "myWorkspace2", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace2", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "standard" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "6666666666666666", + "workspaceUrl": "adb-6666666666666666.19.azuredatabricks.net" + } + } + ] + } + } + } +} diff --git a/tests-upgrade/examples/WorkspacesListBySubscription.json b/tests-upgrade/examples/WorkspacesListBySubscription.json new file mode 100644 index 00000000000..de92bdaeaf1 --- /dev/null +++ b/tests-upgrade/examples/WorkspacesListBySubscription.json @@ -0,0 +1,85 @@ +{ + "parameters": { + "subscriptionId": "subid", + "api-version": "2018-04-01" + }, + "responses": { + "200": { + "headers": {}, + "body": { + "value": [ + { + "name": "myWorkspace1", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace1", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "premium" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "5555555555555555", + "workspaceUrl": "adb-5555555555555555.19.azuredatabricks.net" + } + }, + { + "name": "myWorkspace2", + "id": "/subscriptions/subid/resourceGroups/rg/providers/Microsoft.Databricks/workspaces/myWorkspace2", + "type": "Microsoft.Databricks/workspaces", + "location": "East US 2", + "tags": null, + "sku": { + "name": "standard" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/subid/resourceGroups/myManagedRG", + "parameters": null, + "provisioningState": "Succeeded", + "uiDefinitionUri": "https://path/to/workspaceCreateUiDefinition.json", + "authorizations": [ + { + "principalId": "00000000-0000-0000-0000-000000000000", + "roleDefinitionId": "11111111-1111-1111-1111-111111111111" + } + ], + "createdBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "updatedBy": { + "oid": "22222222-2222-2222-2222-222222222222", + "puid": "33333333", + "applicationId": "44444444-4444-4444-4444-444444444444" + }, + "createdDateTime": "2020-02-20T00:10:29.2858439Z", + "workspaceId": "6666666666666666", + "workspaceUrl": "adb-6666666666666666.19.azuredatabricks.net" + } + } + ] + } + } + } +} diff --git a/tests-upgrade/extension-ms-azureresource/readme.md b/tests-upgrade/extension-ms-azureresource/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-azureresource/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-azureresource/swagger.json b/tests-upgrade/extension-ms-azureresource/swagger.json new file mode 100644 index 00000000000..abd0e6ce8c1 --- /dev/null +++ b/tests-upgrade/extension-ms-azureresource/swagger.json @@ -0,0 +1,79 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "Resource": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-clientflatten/readme.md b/tests-upgrade/extension-ms-clientflatten/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-clientflatten/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-clientflatten/swagger.json b/tests-upgrade/extension-ms-clientflatten/swagger.json new file mode 100644 index 00000000000..b5be373a859 --- /dev/null +++ b/tests-upgrade/extension-ms-clientflatten/swagger.json @@ -0,0 +1,80 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "Workspace": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WorkspaceProperties", + "description": "The workspace properties." + } + }, + "required": [ + "properties" + ], + "description": "Information about workspace." + }, + "WorkspaceProperties": { + "properties": { + "managedResourceGroupId": { + "type": "string", + "description": "The managed resource group Id." + } + }, + "description": "The workspace properties." + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-clientname/readme.md b/tests-upgrade/extension-ms-clientname/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-clientname/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-clientname/swagger.json b/tests-upgrade/extension-ms-clientname/swagger.json new file mode 100644 index 00000000000..ecf7132608d --- /dev/null +++ b/tests-upgrade/extension-ms-clientname/swagger.json @@ -0,0 +1,78 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "Encryption": { + "properties": { + "KeyName": { + "type": "string", + "description": "The name of KeyVault key.", + "x-ms-client-name": "KeyName" + }, + "keyversion": { + "type": "string", + "description": "The version of KeyVault key.", + "x-ms-client-name": "KeyVersion" + }, + "keyvaulturi": { + "type": "string", + "description": "The Uri of KeyVault.", + "x-ms-client-name": "KeyVaultUri" + } + }, + "description": "The object that contains details of encryption used on the workspace." + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-discriminatorvalue/readme.md b/tests-upgrade/extension-ms-discriminatorvalue/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-discriminatorvalue/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-discriminatorvalue/swagger.json b/tests-upgrade/extension-ms-discriminatorvalue/swagger.json new file mode 100644 index 00000000000..fc0749d9999 --- /dev/null +++ b/tests-upgrade/extension-ms-discriminatorvalue/swagger.json @@ -0,0 +1,66 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "SecureString": { + "x-ms-discriminator-value": "SecureString", + "properties": { + "value": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-enum/readme.md b/tests-upgrade/extension-ms-enum/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-enum/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-enum/swagger.json b/tests-upgrade/extension-ms-enum/swagger.json new file mode 100644 index 00000000000..c94b2b31512 --- /dev/null +++ b/tests-upgrade/extension-ms-enum/swagger.json @@ -0,0 +1,80 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "ProvisioningState": { + "description": "Provisioning status of the workspace.", + "readOnly": true, + "enum": [ + "Accepted", + "Running", + "Ready", + "Creating", + "Created", + "Deleting", + "Deleted", + "Canceled", + "Failed", + "Succeeded", + "Updating" + ], + "type": "string", + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-examples/readme.md b/tests-upgrade/extension-ms-examples/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-examples/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-examples/swagger.json b/tests-upgrade/extension-ms-examples/swagger.json new file mode 100644 index 00000000000..457c0601be6 --- /dev/null +++ b/tests-upgrade/extension-ms-examples/swagger.json @@ -0,0 +1,64 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "x-ms-examples": { + "Get a workspace": { + "$ref": "../examples/WorkspaceGet.json" + }, + "Get a workspace with custom parameters": { + "$ref": "../examples/WorkspaceGetParameters.json" + } + }, + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-longruningoperation/readme.md b/tests-upgrade/extension-ms-longruningoperation/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-longruningoperation/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-longruningoperation/swagger.json b/tests-upgrade/extension-ms-longruningoperation/swagger.json new file mode 100644 index 00000000000..02cd91a8e2b --- /dev/null +++ b/tests-upgrade/extension-ms-longruningoperation/swagger.json @@ -0,0 +1,60 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Deletes the workspace.", + "responses": { + "204": { + "description": "NoContent" + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "200": { + "description": "OK. The request has succeeded." + } + }, + "x-ms-long-running-operation": true + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-mutability/readme.md b/tests-upgrade/extension-ms-mutability/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-mutability/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-mutability/swagger.json b/tests-upgrade/extension-ms-mutability/swagger.json new file mode 100644 index 00000000000..2e028ce2a9b --- /dev/null +++ b/tests-upgrade/extension-ms-mutability/swagger.json @@ -0,0 +1,86 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "definitions": { + "TrackedResource": { + "description": "The resource model definition for a ARM tracked top level resource", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ] + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-pageable/readme.md b/tests-upgrade/extension-ms-pageable/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-pageable/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-pageable/swagger.json b/tests-upgrade/extension-ms-pageable/swagger.json new file mode 100644 index 00000000000..3fca89e36ab --- /dev/null +++ b/tests-upgrade/extension-ms-pageable/swagger.json @@ -0,0 +1,71 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListByResourceGroup", + "description": "Gets all the workspaces within a resource group.", + "responses": { + "200": { + "description": "OK - Returns an array of workspaces.", + "schema": { + "$ref": "#/definitions/WorkspaceList" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "WorkspaceList": { + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/extension-ms-paramlocation/readme.md b/tests-upgrade/extension-ms-paramlocation/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/extension-ms-paramlocation/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/extension-ms-paramlocation/swagger.json b/tests-upgrade/extension-ms-paramlocation/swagger.json new file mode 100644 index 00000000000..d42eebb553c --- /dev/null +++ b/tests-upgrade/extension-ms-paramlocation/swagger.json @@ -0,0 +1,73 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "parameters": [ + { + "$ref": "#/parameters/WorkspaceName" + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace." + }, + "default": { + "description": "Error response describing why the operation failed." + } + } + } + } + }, + "parameters": { + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file From 09f16fb9f43dde406376fe4789164a78c2915a30 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 5 Aug 2020 10:12:34 +0800 Subject: [PATCH 26/61] Intial support for polymorphism (#650) * Fix the issue nested ojbect not supported * Add more passed test cases * Add support for allOf, datetime and enable two cases * initial poly support * Add a test for polymorphism --- powershell/llcsharp/model/model-class-json.ts | 19 +- powershell/llcsharp/model/model-class.ts | 6 +- powershell/llcsharp/schema/schema-resolver.ts | 4 +- .../plugin-create-inline-properties.ts | 6 +- powershell/utils/schema.ts | 6 +- tests-upgrade/Configuration.json | 1 + tests-upgrade/basic-polymorphism/readme.md | 10 + tests-upgrade/basic-polymorphism/swagger.json | 1599 +++++++++++++++++ 8 files changed, 1629 insertions(+), 22 deletions(-) create mode 100644 tests-upgrade/basic-polymorphism/readme.md create mode 100644 tests-upgrade/basic-polymorphism/swagger.json diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 0bb3ebc8205..25ff3258130 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -389,16 +389,15 @@ export class NewJsonSerializableClass extends Class { yield If(Not(json.check), Return(dotnet.Null)); yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ - // skip-for-time-being - // if ($this.schema.discriminator) { - // yield Switch(toExpression(`json.StringProperty("${$this.schema.discriminator.propertyName}")`), function* () { - // for (const { key, value } of items(d)) { - // yield TerminalCase(`"${key}"`, function* () { - // yield Return(value.new(json)); - // }); - // } - // }); - // } + if ($this.schema.discriminator) { + yield Switch(toExpression(`json.StringProperty("${$this.schema.discriminator.property.serializedName}")`), function* () { + for (const { key, value } of items(d)) { + yield TerminalCase(`"${key}"`, function* () { + yield Return(value.new(json)); + }); + } + }); + } yield Return($this.new(json, toExpression($excludes.substring(1)))); } else { // just tell it to create the instance (providing that it's a JSonObject) diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 7a962bd4363..ecacf582823 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -905,11 +905,11 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // we'll add a deserializer factory method a bit later.. } - if (this.schema.language.csharp?.discriminatorValue) { + if (this.schema.discriminatorValue) { // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. // um. just how do we *really* know which allOf is polymorphic? // that's really sad. - for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.parents?.immediate)) { + for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.parents?.all)) { const parentSchema = eachAllOfValue; const aState = this.state.path('allOf', eachAllOfIndex); @@ -922,7 +922,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { this.parentModelClasses.push(parentClass); // tell that parent who we are. - parentClass.addDiscriminator(this.schema.language.csharp.discriminatorValue, this); + parentClass.addDiscriminator(this.schema.discriminatorValue, this); } } } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 6a9faa67bee..b8ddd1006eb 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -181,7 +181,7 @@ export class NewSchemaDefinitionResolver { } return this.add(schema, new NewObjectImplementation(schema)); } - case SchemaType.SealedChoice: + case SchemaType.Choice: case SchemaType.String: { return new NewString(schema, required); @@ -226,7 +226,7 @@ export class NewSchemaDefinitionResolver { state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); throw new Error('Unknown Model. Fatal.'); } - case SchemaType.Choice: + case SchemaType.SealedChoice: return new NewEnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 84656151f90..c3fa1261842 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -128,7 +128,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr originalContainingSchema: virtualProperty.originalContainingSchema, description: virtualProperty.description, alias: [], - required: virtualProperty.required, //|| !!values(schema.required).first(each => !!each && !!each.toLowerCase && each.toLowerCase() === virtualProperty.property.details.default.name.toLowerCase()), + required: virtualProperty.required || !!values(>virtualProperty.originalContainingSchema.properties).first(each => !!each && !!each.required && !!each.serializedName && each.serializedName.toLowerCase() === virtualProperty.property.language.default.name.toLowerCase()), sharedWith: virtualProperty.sharedWith, }; // add it to the list of virtual properties that share this property. @@ -190,7 +190,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr description: property.summary || '', originalContainingSchema: schema, alias: [], - required: property.language.default.required, + required: !!property.required, }; virtualProperties.owned.push(privateProperty); @@ -268,7 +268,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr description: property.summary || '', originalContainingSchema: schema, alias: [], - required: property.language.default.required + required: !!property.required }); } diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index c4117d84a6c..b5ccf61d851 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -130,11 +130,9 @@ export interface SchemaDetails extends ImplementationDetails { // } // } -export function getPolymorphicBases(schema: Schema): Array { +export function getPolymorphicBases(schema: ObjectSchema): Array { // are any of my parents polymorphic directly, or any of their parents? - // skip-for-time-being - // return [...values(schema).where(parent => parent.discriminator ? true : false), ...values(schema.allOf).selectMany(getPolymorphicBases)]; - return []; + return [...values(schema.parents?.all).where(parent => (parent).discriminator ? true : false)]; } export function getAllProperties(schema: Schema): Array { diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 19d490b1954..f74ae0b382f 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -9,6 +9,7 @@ "basic-response-multioperation", "basic-spec-required", "basic-spec-root", + "basic-polymorphism", "component-definitions-combined", "component-definitions-local", "component-multiparam", diff --git a/tests-upgrade/basic-polymorphism/readme.md b/tests-upgrade/basic-polymorphism/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/basic-polymorphism/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/basic-polymorphism/swagger.json b/tests-upgrade/basic-polymorphism/swagger.json new file mode 100644 index 00000000000..2f2c6269b45 --- /dev/null +++ b/tests-upgrade/basic-polymorphism/swagger.json @@ -0,0 +1,1599 @@ +{ + "swagger": "2.0", + "info": { + "title": "TimeSeriesInsightsClient", + "description": "Time Series Insights client", + "version": "2018-08-15-preview" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}": { + "put": { + "tags": [ + "Environments" + ], + "operationId": "Environments_CreateOrUpdate", + "x-ms-examples": { + "EnvironmentsCreate": { + "$ref": "./examples/EnvironmentsCreate.json" + } + }, + "x-ms-long-running-operation": true, + "description": "Create or update an environment in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "name": "environmentName", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "description": "Name of the environment" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EnvironmentCreateOrUpdateParameters" + }, + "description": "Parameters for creating an environment resource." + } + ], + "responses": { + "200": { + "description": "The existing environment definition was successfully updated.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "201": { + "description": "The environment create request was accepted. Environment provisioning is an asynchronous operation. You can periodically get your environment definition and monitor progress via the provisioningState property.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "404": { + "description": "The subscription or resource group could not be found." + }, + "default": { + "description": "HTTP 400 (Bad Request): The given environment request body is invalid; See the error code and message in the response for details.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "get": { + "tags": [ + "Environments" + ], + "operationId": "Environments_Get", + "x-ms-examples": { + "EnvironmentsGet": { + "$ref": "./examples/EnvironmentsGet.json" + } + }, + "description": "Gets the environment with the specified name in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ExpandParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The environment definition was successfully retrieved and is in the response. If you are polling for the completion of a provisioning or scale operation, you can check its status via the provisioningState property.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + } + }, + "definitions": { + "OperationListResult": { + "description": "Result of the request to list Time Series Insights operations. It contains a list of operations and a URL link to get the next set of results.", + "properties": { + "value": { + "description": "List of Time Series Insights operations supported by the Microsoft.TimeSeriesInsights resource provider.", + "type": "array", + "readOnly": true, + "items": { + "$ref": "#/definitions/Operation" + } + }, + "nextLink": { + "description": "URL to get the next set of operation list results if there are any.", + "type": "string", + "readOnly": true + } + } + }, + "Operation": { + "description": "A Time Series Insights REST API operation", + "type": "object", + "properties": { + "name": { + "description": "The name of the operation being performed on this particular object.", + "type": "string", + "readOnly": true + }, + "display": { + "description": "Contains the localized display information for this particular operation / action.", + "readOnly": true, + "properties": { + "provider": { + "description": "The localized friendly form of the resource provider name.", + "type": "string", + "readOnly": true + }, + "resource": { + "description": "The localized friendly form of the resource type related to this action/operation.", + "type": "string", + "readOnly": true + }, + "operation": { + "description": "The localized friendly name for the operation.", + "type": "string", + "readOnly": true + }, + "description": { + "description": "The localized friendly description for the operation.", + "type": "string", + "readOnly": true + } + } + } + } + }, + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + } + }, + "description": "Time Series Insights resource", + "x-ms-azure-resource": true + }, + "TrackedResource": { + "properties": { + "location": { + "type": "string", + "description": "Resource location", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "tags": { + "type": "string", + "description": "Resource tags" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "required": [ + "location" + ], + "description": "Time Series Insights resource that is tracked by Azure Resource Manager." + }, + "ResourceProperties": { + "properties": { + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "Provisioning state of the resource." + }, + "creationTime": { + "readOnly": true, + "type": "string", + "format": "date-time", + "description": "The time the resource was created." + } + }, + "description": "Properties that are common to all tracked resources." + }, + "ProvisioningState": { + "readOnly": true, + "type": "string", + "description": "Provisioning state of the resource.", + "enum": [ + "Accepted", + "Creating", + "Updating", + "Succeeded", + "Failed", + "Deleting" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": false + } + }, + "Sku": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of this SKU.", + "enum": [ + "S1", + "S2", + "P1", + "L1" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + } + }, + "capacity": { + "format": "int32", + "type": "integer", + "description": "The capacity of the sku. For standard environments, this value can be changed to support scale out of environments after they have been created.", + "minimum": 1, + "maximum": 10 + } + }, + "required": [ + "name", + "capacity" + ], + "description": "The sku determines the type of environment, either standard (S1 or S2) or long-term (L1). For standard environments the sku determines the capacity of the environment, the ingress rate, and the billing rate." + }, + "WarmStoreConfigurationProperties": { + "type": "object", + "properties": { + "dataRetention": { + "type": "string", + "description": "ISO8601 timespan specifying the number of days the environment's events will be available for query from the warm store." + } + }, + "required": [ + "dataRetention" + ], + "description": "The warm store configuration provides the details to create a warm store cache that will retain a copy of the environment's data available for faster query." + }, + "LongTermStorageConfigurationInput": { + "type": "object", + "properties": { + "accountName": { + "type": "string", + "description": "The name of the storage account that will hold the environment's long term data." + }, + "managementKey": { + "type": "string", + "description": "The value of the management key that grants the Time Series Insights service write access to the storage account. This property is not shown in environment responses." + } + }, + "required": [ + "accountName", + "managementKey" + ], + "description": "The storage configuration provides the connection details that allows the Time Series Insights service to connect to the customer storage account that is used to store the environment's data." + }, + "LongTermStorageConfigurationOutput": { + "type": "object", + "properties": { + "accountName": { + "type": "string", + "description": "The name of the storage account that will hold the environment's long term data." + } + }, + "required": [ + "accountName" + ], + "description": "The storage configuration provides the non-secret connection details about the customer storage account that is used to store the environment's data." + }, + "LongTermStorageConfigurationMutableProperties": { + "type": "object", + "properties": { + "managementKey": { + "type": "string", + "description": "The value of the management key that grants the Time Series Insights service write access to the storage account. This property is not shown in environment responses." + } + }, + "required": [ + "managementKey" + ], + "description": "The storage configuration provides the connection details that allows the Time Series Insights service to connect to the customer storage account that is used to store the environment's data." + }, + "CreateOrUpdateTrackedResourceProperties": { + "properties": { + "location": { + "type": "string", + "description": "The location of the resource.", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "tags": { + "type": "string", + "description": "Key-value pairs of additional properties for the resource." + } + }, + "required": [ + "location" + ], + "description": "Properties required to create any resource tracked by Azure Resource Manager." + }, + "EnvironmentCreateOrUpdateParameters": { + "discriminator": "kind", + "properties": { + "kind": { + "type": "string", + "description": "The kind of the environment.", + "enum": [ + "Standard", + "LongTerm" + ], + "x-ms-enum": { + "name": "Kind", + "modelAsString": false + } + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The sku determines the type of environment, either standard (S1 or S2) or long-term (L1). For standard environments the sku determines the capacity of the environment, the ingress rate, and the billing rate." + } + }, + "required": [ + "kind", + "sku" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ], + "description": "Parameters supplied to the CreateOrUpdate Environment operation." + }, + "StandardEnvironmentCreateOrUpdateParameters": { + "x-ms-discriminator-value": "Standard", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/StandardEnvironmentCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EnvironmentCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Environment operation for a standard environment." + }, + "LongTermEnvironmentCreateOrUpdateParameters": { + "x-ms-discriminator-value": "LongTerm", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/LongTermEnvironmentCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EnvironmentCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Environment operation for a long-term environment." + }, + "EnvironmentUpdateParameters": { + "type": "object", + "properties": { + "tags": { + "type": "string", + "description": "Key-value pairs of additional properties for the environment." + } + }, + "description": "Parameters supplied to the Update Environment operation." + }, + "StandardEnvironmentUpdateParameters": { + "type": "object", + "properties": { + "sku": { + "$ref": "#/definitions/Sku", + "description": "The sku of the environment." + }, + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/StandardEnvironmentMutableProperties", + "description": "Properties of the standard environment." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EnvironmentUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Environment operation to update a standard environment." + }, + "LongTermEnvironmentUpdateParameters": { + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/LongTermEnvironmentMutableProperties", + "description": "Properties of the long-term environment." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EnvironmentUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Environment operation to update a long-term environment." + }, + "EnvironmentListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/EnvironmentResource" + }, + "description": "Result of the List Environments operation." + } + }, + "description": "The response of the List Environments operation." + }, + "EnvironmentResource": { + "type": "object", + "discriminator": "kind", + "properties": { + "sku": { + "$ref": "#/definitions/Sku", + "description": "The sku determines the type of environment, either standard (S1 or S2) or long-term (L1). For standard environments the sku determines the capacity of the environment, the ingress rate, and the billing rate." + }, + "kind": { + "type": "string", + "description": "The kind of the environment.", + "enum": [ + "Standard", + "LongTerm" + ] + } + }, + "required": [ + "kind", + "sku" + ], + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "An environment is a set of time-series data available for query, and is the top level Azure Time Series Insights resource." + }, + "StandardEnvironmentResource": { + "x-ms-discriminator-value": "Standard", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/StandardEnvironmentResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EnvironmentResource" + } + ], + "description": "An environment is a set of time-series data available for query, and is the top level Azure Time Series Insights resource. Standard environments have data retention limits." + }, + "LongTermEnvironmentResource": { + "x-ms-discriminator-value": "LongTerm", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/LongTermEnvironmentResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EnvironmentResource" + } + ], + "description": "An environment is a set of time-series data available for query, and is the top level Azure Time Series Insights resource. LongTerm environments do not have set data retention limits." + }, + "StandardEnvironmentCreationProperties": { + "properties": { + "dataRetentionTime": { + "type": "string", + "description": "ISO8601 timespan specifying the minimum number of days the environment's events will be available for query." + }, + "storageLimitExceededBehavior": { + "type": "string", + "description": "The behavior the Time Series Insights service should take when the environment's capacity has been exceeded. If \"PauseIngress\" is specified, new events will not be read from the event source. If \"PurgeOldData\" is specified, new events will continue to be read and old events will be deleted from the environment. The default behavior is PurgeOldData.", + "enum": [ + "PurgeOldData", + "PauseIngress" + ], + "x-ms-enum": { + "name": "StorageLimitExceededBehavior", + "modelAsString": false + } + }, + "partitionKeyProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/TimeSeriesIdProperty" + }, + "description": "The list of event properties which will be used to partition data in the environment." + } + }, + "required": [ + "dataRetentionTime" + ], + "description": "Properties used to create a standard environment." + }, + "LongTermEnvironmentCreationProperties": { + "properties": { + "timeSeriesIdProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/TimeSeriesIdProperty" + }, + "description": "The list of event properties which will be used to define the environment's time series id." + }, + "storageConfiguration": { + "$ref": "#/definitions/LongTermStorageConfigurationInput", + "description": "The storage configuration provides the connection details that allows the Time Series Insights service to connect to the customer storage account that is used to store the environment's data." + }, + "warmStoreConfiguration": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WarmStoreConfigurationProperties", + "description": "The warm store configuration provides the details to create a warm store cache that will retain a copy of the environment's data available for faster query." + } + }, + "required": [ + "timeSeriesIdProperties", + "storageConfiguration" + ], + "description": "Properties used to create a long-term environment." + }, + "EnvironmentResourceProperties": { + "properties": { + "dataAccessId": { + "readOnly": true, + "type": "string", + "description": "An id used to access the environment data, e.g. to query the environment's events or upload reference data for the environment." + }, + "dataAccessFqdn": { + "readOnly": true, + "type": "string", + "description": "The fully qualified domain name used to access the environment data, e.g. to query the environment's events or upload reference data for the environment." + }, + "status": { + "$ref": "#/definitions/EnvironmentStatus", + "description": "An object that represents the status of the environment, and its internal state in the Time Series Insights service." + } + }, + "allOf": [ + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "description": "Properties of the environment." + }, + "StandardEnvironmentResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/StandardEnvironmentCreationProperties" + }, + { + "$ref": "#/definitions/EnvironmentResourceProperties" + } + ], + "required": [ + "dataRetentionTime" + ], + "description": "Properties of the standard environment." + }, + "LongTermEnvironmentResourceProperties": { + "properties": { + "timeSeriesIdProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/TimeSeriesIdProperty" + }, + "description": "The list of event properties which will be used to define the environment's time series id." + }, + "storageConfiguration": { + "$ref": "#/definitions/LongTermStorageConfigurationOutput", + "description": "The storage configuration provides the connection details that allows the Time Series Insights service to connect to the customer storage account that is used to store the environment's data." + }, + "warmStoreConfiguration": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WarmStoreConfigurationProperties", + "description": "The warm store configuration provides the details to create a warm store cache that will retain a copy of the environment's data available for faster query." + } + }, + "required": [ + "timeSeriesIdProperties", + "storageConfiguration" + ], + "allOf": [ + { + "$ref": "#/definitions/EnvironmentResourceProperties" + } + ], + "description": "Properties of the long-term environment." + }, + "StandardEnvironmentMutableProperties": { + "description": "An object that represents a set of mutable standard environment resource properties.", + "type": "object", + "properties": { + "dataRetentionTime": { + "type": "string", + "description": "ISO8601 timespan specifying the minimum number of days the environment's events will be available for query." + }, + "storageLimitExceededBehavior": { + "type": "string", + "description": "The behavior the Time Series Insights service should take when the environment's capacity has been exceeded. If \"PauseIngress\" is specified, new events will not be read from the event source. If \"PurgeOldData\" is specified, new events will continue to be read and old events will be deleted from the environment. The default behavior is PurgeOldData.", + "enum": [ + "PurgeOldData", + "PauseIngress" + ], + "x-ms-enum": { + "name": "StorageLimitExceededBehavior", + "modelAsString": false + } + }, + "partitionKeyProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/TimeSeriesIdProperty" + }, + "description": "The list of event properties which will be used to partition data in the environment." + } + } + }, + "LongTermEnvironmentMutableProperties": { + "description": "An object that represents a set of mutable long-term environment resource properties.", + "type": "object", + "properties": { + "storageConfiguration": { + "$ref": "#/definitions/LongTermStorageConfigurationMutableProperties", + "description": "The storage configuration provides the connection details that allows the Time Series Insights service to connect to the customer storage account that is used to store the environment's data." + }, + "warmStoreConfiguration": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WarmStoreConfigurationProperties", + "description": "The warm store configuration provides the details to create a warm store cache that will retain a copy of the environment's data available for faster query." + } + } + }, + "TimeSeriesIdProperty": { + "properties": { + "name": { + "type": "string", + "description": "The name of the property." + }, + "type": { + "type": "string", + "description": "The type of the property.", + "enum": [ + "String", + "123" + ], + "x-ms-enum": { + "name": "PropertyType", + "modelAsString": false + } + } + }, + "description": "The structure of the property that a time series id can have. An environment can have multiple such properties." + }, + "EnvironmentStatus": { + "readOnly": true, + "type": "object", + "description": "An object that represents the status of the environment, and its internal state in the Time Series Insights service.", + "properties": { + "ingress": { + "$ref": "#/definitions/IngressEnvironmentStatus", + "description": "An object that represents the status of ingress on an environment." + }, + "warmStorage": { + "$ref": "#/definitions/WarmStorageEnvironmentStatus", + "description": "An object that represents the status of warm storage on an environment." + } + } + }, + "IngressEnvironmentStatus": { + "readOnly": true, + "type": "object", + "description": "An object that represents the status of ingress on an environment.", + "properties": { + "state": { + "type": "string", + "description": "This string represents the state of ingress operations on an environment. It can be \"Disabled\", \"Ready\", \"Running\", \"Paused\" or \"Unknown\"", + "enum": [ + "Disabled", + "Ready", + "Running", + "Paused", + "Unknown" + ], + "x-ms-enum": { + "name": "IngressState", + "modelAsString": false + } + }, + "stateDetails": { + "$ref": "#/definitions/EnvironmentStateDetails", + "description": "An object that contains the details about an environment's state." + } + } + }, + "EnvironmentStateDetails": { + "readOnly": true, + "type": "object", + "description": "An object that contains the details about an environment's state.", + "properties": { + "code": { + "type": "string", + "description": "Contains the code that represents the reason of an environment being in a particular state. Can be used to programmatically handle specific cases." + }, + "message": { + "type": "string", + "description": "A message that describes the state in detail." + } + } + }, + "WarmStorageEnvironmentStatus": { + "readOnly": true, + "type": "object", + "description": "An object that represents the status of warm storage on an environment.", + "properties": { + "propertiesUsage": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WarmStoragePropertiesUsage", + "description": "An object that contains the status of warm storage properties usage." + } + } + }, + "WarmStoragePropertiesUsage": { + "readOnly": true, + "type": "object", + "description": "An object that contains the status of warm storage properties usage.", + "properties": { + "state": { + "type": "string", + "description": "This string represents the state of warm storage properties usage. It can be \"Ok\", \"Error\", \"Unknown\".", + "enum": [ + "Ok", + "Error", + "Unknown" + ], + "x-ms-enum": { + "name": "WarmStoragePropertiesState", + "modelAsString": false + } + }, + "stateDetails": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WarmStoragePropertiesUsageStateDetails", + "description": "An object that contains the details about warm storage properties usage state." + } + } + }, + "WarmStoragePropertiesUsageStateDetails": { + "readOnly": true, + "type": "object", + "description": "An object that contains the details about warm storage properties usage state.", + "properties": { + "currentCount": { + "format": "int32", + "type": "integer", + "description": "A value that represents the number of properties used by the environment for S1/S2 SKU and number of properties used by Warm Store for PAYG SKU", + "minimum": 1, + "maximum": 10 + }, + "maxCount": { + "format": "int32", + "type": "integer", + "description": "A value that represents the maximum number of properties used allowed by the environment for S1/S2 SKU and maximum number of properties allowed by Warm Store for PAYG SKU.", + "minimum": 1, + "maximum": 10 + } + } + }, + "EventSourceCreateOrUpdateParameters": { + "discriminator": "kind", + "properties": { + "kind": { + "type": "string", + "description": "The kind of the event source.", + "enum": [ + "Microsoft.EventHub", + "Microsoft.IoTHub" + ], + "x-ms-enum": { + "name": "Kind", + "modelAsString": false + } + } + }, + "required": [ + "kind" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation." + }, + "EventHubEventSourceCreateOrUpdateParameters": { + "x-ms-discriminator-value": "Microsoft.EventHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation for an EventHub event source." + }, + "IoTHubEventSourceCreateOrUpdateParameters": { + "x-ms-discriminator-value": "Microsoft.IoTHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation for an IoTHub event source." + }, + "EventSourceUpdateParameters": { + "type": "object", + "properties": { + "tags": { + "type": "string", + "description": "Key-value pairs of additional properties for the event source." + } + }, + "description": "Parameters supplied to the Update Event Source operation." + }, + "EventHubEventSourceUpdateParameters": { + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceMutableProperties", + "description": "Properties of the EventHub event source." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Event Source operation to update an EventHub event source." + }, + "IoTHubEventSourceUpdateParameters": { + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceMutableProperties", + "description": "Properties of the IoTHub event source." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Event Source operation to update an IoTHub event source." + }, + "EventSourceListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/EventSourceResource" + }, + "description": "Result of the List EventSources operation." + } + }, + "description": "The response of the List EventSources operation." + }, + "EventSourceResource": { + "type": "object", + "discriminator": "kind", + "properties": { + "kind": { + "type": "string", + "description": "The kind of the event source.", + "enum": [ + "Microsoft.EventHub", + "Microsoft.IoTHub" + ] + } + }, + "required": [ + "kind" + ], + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "An environment receives data from one or more event sources. Each event source has associated connection info that allows the Time Series Insights ingress pipeline to connect to and pull data from the event source" + }, + "EventHubEventSourceResource": { + "x-ms-discriminator-value": "Microsoft.EventHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceResource" + } + ], + "description": "An event source that receives its data from an Azure EventHub." + }, + "IoTHubEventSourceResource": { + "x-ms-discriminator-value": "Microsoft.IotHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceResource" + } + ], + "description": "An event source that receives its data from an Azure IoTHub." + }, + "EventSourceCommonProperties": { + "properties": { + "timestampPropertyName": { + "type": "string", + "description": "The event property that will be used as the event source's timestamp. If a value isn't specified for timestampPropertyName, or if null or empty-string is specified, the event creation time will be used." + } + }, + "allOf": [ + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "description": "Properties of the event source." + }, + "AzureEventSourceProperties": { + "properties": { + "eventSourceResourceId": { + "type": "string", + "description": "The resource id of the event source in Azure Resource Manager." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceCommonProperties" + } + ], + "required": [ + "eventSourceResourceId" + ], + "description": "Properties of an event source that reads events from an event broker in Azure." + }, + "EventHubEventSourceCommonProperties": { + "properties": { + "serviceBusNamespace": { + "type": "string", + "description": "The name of the service bus that contains the event hub." + }, + "eventHubName": { + "type": "string", + "description": "The name of the event hub." + }, + "consumerGroupName": { + "type": "string", + "description": "The name of the event hub's consumer group that holds the partitions from which events will be read." + }, + "keyName": { + "type": "string", + "description": "The name of the SAS key that grants the Time Series Insights service access to the event hub. The shared access policies for this key must grant 'Listen' permissions to the event hub." + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureEventSourceProperties" + } + ], + "required": [ + "serviceBusNamespace", + "eventHubName", + "consumerGroupName", + "keyName" + ], + "description": "Properties of the EventHub event source." + }, + "EventHubEventSourceCreationProperties": { + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the event hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventHubEventSourceCommonProperties" + } + ], + "required": [ + "sharedAccessKey" + ], + "description": "Properties of the EventHub event source that are required on create or update requests." + }, + "EventHubEventSourceResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/EventHubEventSourceCommonProperties" + } + ], + "properties": { + "sss": { + "type": "string" + } + }, + "description": "Properties of the EventHub event source resource." + }, + "IoTHubEventSourceCommonProperties": { + "properties": { + "iotHubName": { + "type": "string", + "description": "The name of the iot hub." + }, + "consumerGroupName": { + "type": "string", + "description": "The name of the iot hub's consumer group that holds the partitions from which events will be read." + }, + "keyName": { + "type": "string", + "description": "The name of the Shared Access Policy key that grants the Time Series Insights service access to the iot hub. This shared access policy key must grant 'service connect' permissions to the iot hub." + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureEventSourceProperties" + } + ], + "required": [ + "iotHubName", + "consumerGroupName", + "keyName" + ], + "description": "Properties of the IoTHub event source." + }, + "IoTHubEventSourceCreationProperties": { + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the Shared Access Policy key that grants the Time Series Insights service read access to the iot hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/IoTHubEventSourceCommonProperties" + } + ], + "required": [ + "sharedAccessKey" + ], + "description": "Properties of the IoTHub event source that are required on create or update requests." + }, + "IoTHubEventSourceResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/IoTHubEventSourceCommonProperties" + } + ], + "properties": { + "name": { + "type": "boolean" + } + }, + "description": "Properties of the IoTHub event source resource." + }, + "LocalTimestamp": { + "description": "An object that represents the local timestamp property. It contains the format of local timestamp that needs to be used and the corresponding timezone offset information. If a value isn't specified for localTimestamp, or if null, then the local timestamp will not be ingressed with the events.", + "type": "object", + "properties": { + "format": { + "description": "An enum that represents the format of the local timestamp property that needs to be set.", + "type": "string", + "enum": [ + "Embedded", + "Iana", + "TimeSpan" + ], + "x-ms-enum": { + "name": "LocalTimestampFormat", + "modelAsString": false + } + }, + "timeZoneOffset": { + "description": "An object that represents the offset information for the local timestamp format specified. Should not be specified for LocalTimestampFormat - Embedded.", + "type": "object", + "properties": { + "propertyName": { + "type": "string", + "description": "The event property that will be contain the offset information to calculate the local timestamp. When the LocalTimestampFormat is Iana, the property name will contain the name of the column which contains IANA Timezone Name (eg: Americas/Los Angeles). When LocalTimestampFormat is Timespan, it contains the name of property which contains values representing the offset (eg: P1D or 1.00:00:00)" + } + } + } + } + }, + "EventSourceMutableProperties": { + "description": "An object that represents a set of mutable event source resource properties.", + "type": "object", + "properties": { + "timestampPropertyName": { + "type": "string", + "description": "The event property that will be used as the event source's timestamp. If a value isn't specified for timestampPropertyName, or if null or empty-string is specified, the event creation time will be used." + }, + "localTimestamp": { + "$ref": "#/definitions/LocalTimestamp", + "description": "An object that represents the local timestamp property. It contains the format of local timestamp that needs to be used and the corresponding timezone offset information. If a value isn't specified for localTimestamp, or if null, then the local timestamp will not be ingressed with the events." + } + } + }, + "EventHubEventSourceMutableProperties": { + "description": "An object that represents a set of mutable EventHub event source resource properties.", + "type": "object", + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the event hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceMutableProperties" + } + ] + }, + "IoTHubEventSourceMutableProperties": { + "description": "An object that represents a set of mutable IoTHub event source resource properties.", + "type": "object", + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the iot hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceMutableProperties" + } + ] + }, + "ReferenceDataSetCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/ReferenceDataSetCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ] + }, + "ReferenceDataSetUpdateParameters": { + "type": "object", + "properties": { + "tags": { + "type": "string", + "description": "Key-value pairs of additional properties for the reference data set." + } + }, + "description": "Parameters supplied to the Update Reference Data Set operation." + }, + "ReferenceDataSetListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/ReferenceDataSetResource" + }, + "description": "Result of the List Reference Data Sets operation." + } + }, + "description": "The response of the List Reference Data Sets operation." + }, + "ReferenceDataSetResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/ReferenceDataSetResourceProperties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "A reference data set provides metadata about the events in an environment. Metadata in the reference data set will be joined with events as they are read from event sources. The metadata that makes up the reference data set is uploaded or modified through the Time Series Insights data plane APIs." + }, + "ReferenceDataSetCreationProperties": { + "properties": { + "keyProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/ReferenceDataSetKeyProperty" + }, + "description": "The list of key properties for the reference data set." + }, + "dataStringComparisonBehavior": { + "type": "string", + "description": "The reference data set key comparison behavior can be set using this property. By default, the value is 'Ordinal' - which means case sensitive key comparison will be performed while joining reference data with events or while adding new reference data. When 'OrdinalIgnoreCase' is set, case insensitive comparison will be used.", + "enum": [ + "Ordinal", + "OrdinalIgnoreCase" + ], + "x-ms-enum": { + "name": "DataStringComparisonBehavior", + "modelAsString": false + } + } + }, + "required": [ + "keyProperties" + ], + "description": "Properties used to create a reference data set." + }, + "ReferenceDataSetResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/ReferenceDataSetCreationProperties" + }, + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "required": [ + "keyProperties" + ], + "description": "Properties of the reference data set." + }, + "ReferenceDataSetKeyProperty": { + "properties": { + "name": { + "type": "string", + "description": "The name of the key property." + }, + "type": { + "type": "string", + "description": "The type of the key property.", + "enum": [ + "String", + "Double", + "Bool", + "DateTime" + ], + "x-ms-enum": { + "name": "ReferenceDataKeyPropertyType", + "modelAsString": false + } + } + }, + "description": "A key property for the reference data set. A reference data set can have multiple key properties." + }, + "AccessPolicyCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyResourceProperties" + } + }, + "required": [ + "properties" + ] + }, + "AccessPolicyUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyMutableProperties" + } + } + }, + "AccessPolicyListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/AccessPolicyResource" + }, + "description": "Result of the List access policies operation." + } + }, + "description": "The response of the List access policies operation." + }, + "AccessPolicyResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyResourceProperties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "An access policy is used to grant users and applications access to the environment. Roles are assigned to service principals in Azure Active Directory. These roles define the actions the principal can perform through the Time Series Insights data plane APIs." + }, + "AccessPolicyResourceProperties": { + "properties": { + "principalObjectId": { + "type": "string", + "description": "The objectId of the principal in Azure Active Directory." + }, + "description": { + "type": "string", + "description": "An description of the access policy." + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "description": "A role defining the data plane operations that a principal can perform on a Time Series Insights client.", + "enum": [ + "Reader", + "Contributor" + ], + "x-ms-enum": { + "name": "AccessPolicyRole", + "modelAsString": false + } + }, + "description": "The list of roles the principal is assigned on the environment." + } + } + }, + "AccessPolicyMutableProperties": { + "description": "An object that represents a set of mutable access policy resource properties.", + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "An description of the access policy." + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "description": "A role defining the data plane operations that a principal can perform on a Time Series Insights client.", + "enum": [ + "Reader", + "Contributor" + ], + "x-ms-enum": { + "name": "AccessPolicyRole", + "modelAsString": false + } + }, + "description": "The list of roles the principal is assigned on the environment." + } + } + }, + "CloudError": { + "type": "object", + "properties": { + "error": { + "$ref": "#/definitions/CloudErrorBody", + "description": "Describes a particular API error with an error code and a message." + } + }, + "description": "Contains information about an API error.", + "x-ms-external": true + }, + "CloudErrorBody": { + "type": "object", + "description": "Describes a particular API error with an error code and a message.", + "properties": { + "code": { + "type": "string", + "description": "An error code that describes the error condition more precisely than an HTTP status code. Can be used to programmatically handle specific error cases." + }, + "message": { + "type": "string", + "description": "A message that describes the error in detail and provides debugging information." + }, + "target": { + "type": "string", + "description": "The target of the particular error (for example, the name of the property in error)." + }, + "details": { + "type": "array", + "items": { + "$ref": "#/definitions/CloudErrorBody", + "description": "Describes a particular API error with an error code and a message." + }, + "description": "Contains nested errors that are related to this error." + } + }, + "x-ms-external": true + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "description": "Azure Subscription ID.", + "required": true, + "type": "string" + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "Version of the API to be used with the client request." + }, + "ExpandParameter": { + "name": "expand", + "in": "query", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Setting expand=status will include the status of the internal services of the environment in the Time Series Insights service." + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Name of an Azure Resource group." + }, + "EnvironmentNameParameter": { + "name": "environmentName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights environment associated with the specified resource group.", + "x-ms-parameter-location": "method" + }, + "EventSourceNameParameter": { + "name": "eventSourceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights event source associated with the specified environment.", + "x-ms-parameter-location": "method" + }, + "ReferenceDataSetNameParameter": { + "name": "referenceDataSetName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights reference data set associated with the specified environment.", + "x-ms-parameter-location": "method" + }, + "AccessPolicyNameParameter": { + "name": "accessPolicyName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights access policy associated with the specified environment.", + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file From 9e3a7e0b781bd6e5bd6ba313341e9731ec5a5e94 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 5 Aug 2020 16:21:38 +0800 Subject: [PATCH 27/61] Add support for duration and uuid (#652) * Fix the issue nested ojbect not supported * Add more passed test cases * Add support for allOf, datetime and enable two cases * initial poly support * Add a test for polymorphism * Add support for uuid and duration --- powershell/llcsharp/schema/schema-resolver.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index b8ddd1006eb..7b5ffdf4871 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -186,7 +186,10 @@ export class NewSchemaDefinitionResolver { return new NewString(schema, required); } - + case SchemaType.Duration: + return new NewDuration(schema, required); + case SchemaType.Uuid: + return new NewUuid(schema, required); case SchemaType.DateTime: return new NewDateTime(schema, required); From f23e48ed48fbea0c937bf3251632d79b7285bf45 Mon Sep 17 00:00:00 2001 From: LucasYao93 <53558334+LucasYao93@users.noreply.github.com> Date: Wed, 5 Aug 2020 16:38:46 +0800 Subject: [PATCH 28/61] Add test cases to AllowList. (#653) * Add test cases of autorest extension. * Add test cases of directive. * Add test case of directive. * Add test cases to AllowList. --- tests-upgrade/Configuration.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index f74ae0b382f..51c7d7c1ce7 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -5,13 +5,16 @@ "basic-get", "basic-get-delete", "basic-get-delete-put-patch", + "basic-get-querystr", "basic-get-response-operation", + "basic-polymorphism", + "basic-request-methods", "basic-response-multioperation", "basic-spec-required", "basic-spec-root", - "basic-polymorphism", "component-definitions-combined", "component-definitions-local", + "component-definitions-remote", "component-multiparam", "component-param", "component-param-inbody", @@ -19,7 +22,16 @@ "component-param-remote", "datamodels-datatypes-array", "datamodels-datatypes-integer", - "datamodels-datatypes-string" + "datamodels-datatypes-string", + "directive-model", + "directive-tableformat", + "extension-ms-azureresource", + "extension-ms-clientflatten", + "extension-ms-clientname", + "extension-ms-discriminatorvalue", + "extension-ms-examples", + "extension-ms-longruningoperation", + "extension-ms-pageable" ], "BlackList": [ "basic-get-querystr", From 656426c077c039b6061812e90a0efc7cf110aff7 Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 5 Aug 2020 17:12:44 +0800 Subject: [PATCH 29/61] support dict (#651) Co-authored-by: xichen --- powershell/cmdlets/class.ts | 121 +++++++++--------- .../llcsharp/model/model-class-dictionary.ts | 112 +++++++++++++++- powershell/llcsharp/model/model-class-json.ts | 11 +- .../llcsharp/model/model-class-serializer.ts | 36 +++--- powershell/llcsharp/model/model-class.ts | 60 +++++---- powershell/llcsharp/model/property.ts | 2 +- powershell/llcsharp/schema/schema-resolver.ts | 2 + powershell/models/model-extensions.ts | 57 ++++++++- powershell/plugins/cs-namer-v2.ts | 2 +- .../plugin-create-inline-properties.ts | 8 +- powershell/plugins/plugin-tweak-m4-model.ts | 63 ++++++++- 11 files changed, 358 insertions(+), 116 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 30cef55d3bc..febc15e7298 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter, ObjectSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; import { command, getAllProperties, JsonType, http, getAllPublicVirtualProperties, getVirtualPropertyFromPropertyName, ParameterLocation, getAllVirtualProperties, VirtualParameter, VirtualProperty } from '@azure-tools/codemodel-v3'; import { CommandOperation, VirtualParameter as NewVirtualParameter } from '../utils/command-operation'; import { getAllProperties as NewGetAllProperties, getAllPublicVirtualProperties as NewGetAllPublicVirtualProperties, getVirtualPropertyFromPropertyName as NewGetVirtualPropertyFromPropertyName, VirtualProperty as NewVirtualProperty } from '../utils/schema'; @@ -2412,21 +2412,23 @@ export class NewCmdletClass extends Class { // } cmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); } - //skip-for-time-being - // if (vSchema.additionalProperties) { - // // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // // if it's a standalone dictionary, we can just use hashtable instead - // if (length(vSchema.properties) === 0) { - // // it's a pure dictionary - // // add an attribute for changing the exported type. - // cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - // } else { - // // it's a hybrid. We need to add an additional property that puts its items into the target container - - // } - - // } + const dictSchema = vSchema.type === SchemaType.Dictionary ? vSchema : + vSchema.type === SchemaType.Object ? (vSchema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary) : + undefined; + if (dictSchema) { + // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. + // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary + // if it's a standalone dictionary, we can just use hashtable instead + if (length((vSchema).properties) === 0) { + // it's a pure dictionary + // add an attribute for changing the exported type. + cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); + } else { + // it's a hybrid. We need to add an additional property that puts its items into the target container + + } + + } const desc = (vParam.description || '.').replace(/[\r?\n]/gm, ''); cmdletParameter.description = desc; @@ -2478,31 +2480,34 @@ export class NewCmdletClass extends Class { this.add(cmdletParameter); } - // skip-for-time-being - // if (parameter.schema.additionalProperties) { - // // if there is an additional properties on this type - // // add a hashtable parameter for additionalProperties - // let apPropName = ''; - // const options = ['AdditionalProperties', 'MoreProperties', 'ExtendedProperties', 'Properties']; - // for (const n of options) { - // if (this.properties.find(each => each.name === n)) { - // continue; - // } - // apPropName = n; - // break; - // } - - // this.apProp = this.add(new Property(apPropName, System.Collections.Hashtable)); - // this.apProp.add(new Attribute(ParameterAttribute, { - // parameters: ['Mandatory = false', 'HelpMessage = "Additional Parameters"'] - // })); - // this.bodyParameterInfo = { - // type: { - // declaration: parameter.schema.details.csharp.fullname - // }, - // valueType: parameter.schema.additionalProperties === true ? System.Object : this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema.additionalProperties, true, this.state) - // }; - // } + const paramDictSchema = parameter.schema.type === SchemaType.Dictionary ? parameter.schema : + parameter.schema.type === SchemaType.Object ? (parameter.schema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary) : + undefined; + if (paramDictSchema) { + // if there is an additional properties on this type + // add a hashtable parameter for additionalProperties + let apPropName = ''; + const options = ['AdditionalProperties', 'MoreProperties', 'ExtendedProperties', 'Properties']; + for (const n of options) { + if (this.properties.find(each => each.name === n)) { + continue; + } + apPropName = n; + break; + } + + this.apProp = this.add(new Property(apPropName, System.Collections.Hashtable)); + this.apProp.add(new Attribute(ParameterAttribute, { + parameters: ['Mandatory = false', 'HelpMessage = "Additional Parameters"'] + })); + this.bodyParameterInfo = { + type: { + declaration: parameter.schema.language.csharp?.fullname + }, + valueType: (paramDictSchema).elementType.type === SchemaType.Any ? System.Object : + this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((paramDictSchema).elementType, true, this.state) + }; + } this.bodyParameter = expandedBodyParameter; continue; @@ -2550,22 +2555,24 @@ export class NewCmdletClass extends Class { description: vParam.description })); - // skip-for-time-being - // if (vSchema.additionalProperties) { - // // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // // if it's a standalone dictionary, we can just use hashtable instead - // if (length(vSchema.properties) === 0) { - // // it's a pure dictionary - // // change the property type to hashtable. - // // add an attribute to change the exported type. - // regularCmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - // } else { - // // it's a hybrid. We need to add an additional property that puts its items into the target container - - // } - - // } + const dictSchema = vSchema.type === SchemaType.Dictionary ? vSchema : + vSchema.type === SchemaType.Object ? (vSchema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary) : + undefined; + if (dictSchema) { + // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. + // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary + // if it's a standalone dictionary, we can just use hashtable instead + if (length((vSchema).properties) === 0) { + // it's a pure dictionary + // change the property type to hashtable. + // add an attribute to change the exported type. + regularCmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); + } else { + // it's a hybrid. We need to add an additional property that puts its items into the target container + + } + + } this.thingsToSerialize.push(regularCmdletParameter); diff --git a/powershell/llcsharp/model/model-class-dictionary.ts b/powershell/llcsharp/model/model-class-dictionary.ts index 728e369caee..330cdd2f3e9 100644 --- a/powershell/llcsharp/model/model-class-dictionary.ts +++ b/powershell/llcsharp/model/model-class-dictionary.ts @@ -3,11 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Field, System, Property, toExpression, dotnet, Parameter, ParameterModifier, Method, Class, TypeDeclaration, Indexer, Access, Variable, Expression, If, And, ForEach, LocalVariable, ImplicitCastOperator } from '@azure-tools/codegen-csharp'; -import { ModelClass } from './model-class'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass, NewModelClass } from './model-class'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; import { getAllVirtualProperties } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; +import { DictionarySchema, ObjectSchema, SchemaType, Schema } from '@azure-tools/codemodel'; export class DictionaryImplementation extends Class { private get state() { return this.modelClass.state; } @@ -114,3 +115,110 @@ export class DictionaryImplementation extends Class { return `${super.fileName}.dictionary`; } } + +export class NewDictionaryImplementation extends Class { + private get state() { return this.modelClass.state; } + private get schema() { return this.modelClass.schema; } + public valueType!: TypeDeclaration | NewEnhancedTypeDeclaration; + public ownsDictionary = false; + + constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { + super(modelClass.namespace, modelClass.name); + this.apply(objectInitializer); + } + + init(valueType?: TypeDeclaration, accessViaMember?: Expression) { + if (valueType && accessViaMember) { + this.valueType = valueType; + this.implementIDictionary(this, '', System.String, valueType, accessViaMember); + + } + else { + const dictSchema = (this.schema).type === SchemaType.Dictionary ? this.schema : this.schema.parents?.immediate?.find((s) => s.type === SchemaType.Dictionary); + if (dictSchema) { + this.ownsDictionary = true; + this.valueType = (dictSchema).elementType.type === SchemaType.Any ? System.Object : this.state.project.modelsNamespace.NewResolveTypeDeclaration((dictSchema).elementType, true, this.state); + this.modelClass.modelInterface.interfaces.push(this.implementIDictionary(this, 'additionalProperties', System.String, this.valueType)); + } + } + + return this; + } + + addSerialization() { + if (this.modelClass.jsonSerializer) { + // add serializer methods. + // this.modelClass.jsonSerializer + + + } + } + + implementIDictionary(targetClass: Class, name: string, keyType: TypeDeclaration, valueType: TypeDeclaration, accessViaMember?: Expression) { + const containerInterfaceType = { declaration: `${ClientRuntime}.IAssociativeArray<${valueType.declaration}>`, allProperties: [] }; + const dictionaryInterfaceType = System.Collections.Generic.IDictionary(keyType, valueType); + const itemType = System.Collections.Generic.KeyValuePair(keyType, valueType); + + // add the interface to the list of interfaces for the class + targetClass.interfaces.push(containerInterfaceType); + + // the backing field + const dictionaryType = System.Collections.Generic.Dictionary(keyType, valueType); + + accessViaMember = accessViaMember || targetClass.add(new Field(`__${name}`, dictionaryType, { access: Access.Protected, initialValue: dictionaryType.new() })); + + const indexer = targetClass.add(new Indexer(keyType, valueType, { get: toExpression(`${accessViaMember}[index]`), set: toExpression(`${accessViaMember}[index] = value`) })); + + // the parameters used in methods. + + const pKey = new Parameter('key', keyType); + const pValue = new Parameter('value', valueType); + const pOutValue = new Parameter('value', valueType, { modifier: ParameterModifier.Out }); + + targetClass.add(new Property(`${containerInterfaceType.declaration}.Keys`, System.Collections.Generic.IEnumerable(keyType), { get: toExpression(`${accessViaMember}.Keys`), getAccess: Access.Explicit })); + targetClass.add(new Property(`${containerInterfaceType.declaration}.Values`, System.Collections.Generic.IEnumerable(valueType), { get: toExpression(`${accessViaMember}.Values`), getAccess: Access.Explicit })); + targetClass.add(new Property(`${containerInterfaceType.declaration}.Count`, dotnet.Int, { get: toExpression(`${accessViaMember}.Count`), getAccess: Access.Explicit })); + if (name) { + targetClass.add(new ImplicitCastOperator(dictionaryType, targetClass, `source.${accessViaMember}`)); + targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}`), getAccess: Access.Explicit })); + } else { + targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}.AdditionalProperties`), getAccess: Access.Explicit })); + } + targetClass.add(new Method('Add', dotnet.Void, { parameters: [pKey, pValue], body: toExpression(`${accessViaMember}.Add( ${pKey}, ${pValue})`), access: Access.Public })); + targetClass.add(new Method('Clear', dotnet.Void, { body: toExpression(`${accessViaMember}.Clear()`), access: Access.Public })); + + targetClass.add(new Method('ContainsKey', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.ContainsKey( ${pKey})`), access: Access.Public })); + + targetClass.add(new Method('Remove', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.Remove( ${pKey})`), access: Access.Public })); + + targetClass.add(new Method('TryGetValue', dotnet.Bool, { parameters: [pKey, pOutValue], body: toExpression(`${accessViaMember}.TryGetValue( ${pKey}, out ${pOutValue})`), access: Access.Public })); + + const all = getAllVirtualProperties(this.schema.language.csharp?.virtualProperties); + const exclusions = all.map(each => `"${each.name}"`).join(','); + + // add a CopyFrom that takes an IDictionary or PSObject and copies the values into this dictionary + for (const pDictType of [System.Collections.IDictionary, { declaration: 'global::System.Management.Automation.PSObject' }]) { + const pDict = new Parameter('source', pDictType); + targetClass.add(new Method('CopyFrom', dotnet.Void, { + parameters: [pDict], body: function* () { + yield If(pDict.IsNotNull, function* () { + + yield ForEach('property', ` Microsoft.Rest.ClientRuntime.PowerShell.TypeConverterExtensions.GetFilteredProperties(${pDict.value}, ${System.Collections.Generic.HashSet(System.String).new()} { ${exclusions} } )`, function* () { + + yield If(And('null != property.Key', 'null != property.Value'), function* () { + yield `this.${accessViaMember}.Add(property.Key.ToString(), global::System.Management.Automation.LanguagePrimitives.ConvertTo<${valueType.declaration}>( property.Value));`; + }); + }); + }); + } + })); + } + + // return dictionaryInterfaceType; + return containerInterfaceType; + } + + public get fileName(): string { + return `${super.fileName}.dictionary`; + } +} diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 25ff3258130..08496a9350c 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema, ObjectSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, ObjectSchema, SchemaType } from '@azure-tools/codemodel'; import { KnownMediaType, HeaderProperty, HeaderPropertyType, getAllProperties } from '@azure-tools/codemodel-v3'; import { getAllProperties as newGetAllProperties } from '@azure-tools/codemodel'; import { EOL, DeepPartial, } from '@azure-tools/codegen'; @@ -25,7 +25,7 @@ import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; import { ModelClass, NewModelClass } from './model-class'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; import { ModelProperty } from './property'; @@ -310,8 +310,11 @@ export class NewJsonSerializableClass extends Class { for (const each of values(modelClass.backingFields)) { serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - const sch = (each.typeDeclaration).schema; - if (!(sch instanceof NewSchema) && (sch.additionalProperties)) { + const sch = (each.typeDeclaration).schema; + const dictSchema = sch.type === SchemaType.Dictionary ? sch : + sch.type === SchemaType.Object ? (sch).parents?.immediate.find((s) => s.type === SchemaType.Dictionary) : + undefined; + if (dictSchema) { deserializeStatements.add(`${each.field.value} = new ${each.className}(json${this.excludes});`); } else { deserializeStatements.add(`${each.field.value} = new ${each.className}(json);`); diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index 8b9a3c7422d..9ba766976a4 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -30,7 +30,7 @@ import { popTempVar, pushTempVar } from '../schema/primitive'; import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; import { getVirtualPropertyName, NewGetVirtualPropertyName } from './model-class'; import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; @@ -244,27 +244,33 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { yield `${$this.beforeDeserialize.name}(${$this.contentParameter}, ref ${returnNow.value});`; yield If(returnNow, 'return;'); yield $this.deserializeStatements; - // skip-for-time-being - // if ($this.hasAadditionalProperties($this.schema)) { - // // this type has an additional properties dictionary - // yield '// this type is a dictionary; copy elements from source to here.'; - // yield `CopyFrom(${$this.contentParameter.value});`; - // } + + if ($this.hasAadditionalProperties($this.schema)) { + // this type has an additional properties dictionary + yield '// this type is a dictionary; copy elements from source to here.'; + yield `CopyFrom(${$this.contentParameter.value});`; + } yield `${$this.afterDeserialize.name}(${$this.contentParameter});`; }); } - private hasAadditionalProperties(aSchema: Schema): boolean { - if (aSchema.additionalProperties) { + private hasAadditionalProperties(aSchema: NewSchema): boolean { + if (aSchema.type === SchemaType.Dictionary) { return true; - } else - for (const each of values(aSchema.allOf)) { - const r = this.hasAadditionalProperties(each); - if (r) { - return r; - } + } + if (aSchema.type !== SchemaType.Object) { + return false; + } + const objSchema = (aSchema).parents?.immediate; + if (!objSchema || objSchema.length === 0) { + return false; + } + for (const parent of objSchema) { + if (this.hasAadditionalProperties(parent)) { + return true; } + } return false; } diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index ecacf582823..c87075ae1bd 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -16,8 +16,8 @@ import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-j import { ModelProperty, NewModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; -import { DictionaryImplementation } from './model-class-dictionary'; -import { Languages, Language, Schema as NewSchema } from '@azure-tools/codemodel'; +import { DictionaryImplementation, NewDictionaryImplementation } from './model-class-dictionary'; +import { Languages, Language, Schema as NewSchema, SchemaType, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; import { VirtualProperty as NewVirtualProperty, getAllVirtualProperties as newGetAllVirtualProperties } from '../../utils/schema'; export function getVirtualPropertyName(vp?: VirtualProperty): string { @@ -563,7 +563,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { /* @internal */ validationEventListener: Parameter = new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive validation events.` }); /* @internal */ jsonSerializer?: NewJsonSerializableClass; // /* @internal */ xmlSerializer?: XmlSerializableClass; - /* @internal */ dictionaryImpl?: DictionaryImplementation; + /* @internal */ dictionaryImpl?: NewDictionaryImplementation; private readonly validationStatements = new Statements(); public ownedProperties = new Array(); @@ -608,13 +608,14 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // add default constructor this.addMethod(new Constructor(this, { description: `Creates an new instance.` })); // default constructor for fits and giggles. - // skip-for-time-being // handle parent interface implementation if (!this.handleAllOf()) { // handle the AdditionalProperties if used - // if (this.schema.additionalProperties) { - // this.dictionaryImpl = new DictionaryImplementation(this).init(); - // } + const dictSchema = (this.schema).type === SchemaType.Dictionary ? this.schema : + this.schema.parents?.immediate?.find((schema) => schema.type === SchemaType.Dictionary); + if (dictSchema) { + this.dictionaryImpl = new NewDictionaryImplementation(this).init(); + } } // create the properties for ths schema @@ -684,7 +685,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } } }; - // skip-for-time-being + /* Owned Properties */ for (const virtualProperty of values(>(this.schema.language.csharp.virtualProperties.owned))) { const actualProperty = virtualProperty.property; @@ -838,23 +839,25 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { } private additionalPropertiesType(aSchema: NewSchema): TypeDeclaration | undefined { - // skip-for-time-being - // if (aSchema.additionalProperties) { - - // if (aSchema.additionalProperties === true) { - // return System.Object; - - // } else { - // // we're going to implement IDictionary - // return this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema.additionalProperties, true, this.state); - // } - // } else - // for (const each of values(aSchema.allOf)) { - // const r = this.additionalPropertiesType(each); - // if (r) { - // return r; - // } - // } + const schema = aSchema.type === SchemaType.Dictionary ? aSchema : + aSchema.type === SchemaType.Object ? (aSchema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary) : + undefined; + if (schema) { + const dictSchema = schema as DictionarySchema; + if (dictSchema.elementType.type === SchemaType.Any) { + return System.Object; + + } else { + // we're going to implement IDictionary + return this.state.project.modelsNamespace.NewResolveTypeDeclaration(dictSchema.elementType, true, this.state); + } + } else + for (const each of values((aSchema).parents?.immediate)) { + const r = this.additionalPropertiesType(each); + if (r) { + return r; + } + } return undefined; } @@ -863,6 +866,9 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // handle s // add an 'implements' for the interface for the allOf. for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.parents?.immediate)) { + if (eachSchemaValue.type === SchemaType.Dictionary) { + continue; + } const aSchema = eachSchemaValue; const aState = this.state.path('allOf', eachSchemaIndex); @@ -890,8 +896,8 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // const addlPropType = this.additionalPropertiesType(aSchema); if (addlPropType) { - // this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); - // hasAdditionalPropertiesInParent = true; + this.dictionaryImpl = new NewDictionaryImplementation(this).init(addlPropType, backingField); + hasAdditionalPropertiesInParent = true; } } return hasAdditionalPropertiesInParent; diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index dd21d43c46e..0c87dd95aef 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -139,7 +139,7 @@ export class NewModelProperty extends BackedProperty implements EnhancedVariable this.apply(objectInitializer); this.description = description; this.required = isRequired; - if (this.schema.type === SchemaType.Object && isAnExpression(this.get) && schema.language.csharp?.classImplementation) { + if ((this.schema.type === SchemaType.Object || this.schema.type === SchemaType.Dictionary) && isAnExpression(this.get) && schema.language.csharp?.classImplementation) { // for objects, the getter should auto-create a new object this.get = toExpression(`(${this.get.value} = ${this.get.value} ?? new ${schema.language.csharp?.fullname}())`); } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 7b5ffdf4871..04fb661e33b 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -174,6 +174,8 @@ export class NewSchemaDefinitionResolver { return new NewArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); } + case SchemaType.Any: + case SchemaType.Dictionary: case SchemaType.Object: { const result = schema.language.csharp && this.cache.get(schema.language.csharp.fullname || ''); if (result) { diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 477c19d8e36..2032f7f4675 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema } from '@azure-tools/codemodel'; +import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, NewObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; @@ -279,11 +279,66 @@ export class NewModelExtensionsNamespace extends Namespace { // Add typeconverters to model classes (partial) for (const schemaGroup of values(schemas)) { + if (schemaGroup.length > 0 && (schemaGroup[0].type === SchemaType.Any)) { + // skip any + continue; + } for (const schema of values(schemaGroup)) { if (!schema || (schema.language.csharp && schema.language.csharp.skip)) { continue; } + if (schema.type === SchemaType.Dictionary) { + // xichen: + // Case1: dictionary schema is only used in parents: + // "definitions": { + // "PetAPInPropertiesWithAPString": { + // "type": "object", + // "properties": { + // "id": { + // "type": "integer" + // } + // }, + // "additionalProperties": { + // "type": "string" + // } + // } + // } + // + // Case2: we will have a dictionary property: + // "definitions": { + // "PetAPInProperties": { + // "type": "object", + // "properties": { + // "id": { + // "type": "integer" + // }, + // "additionalProperties": { + // "type": "object", + // "additionalProperties": { + // "type": "number" + // } + // } + // } + // } + // } + // + // We only create model class for case 2, because in m3 case 2 will has independent scheam for additionalProperties, + // But for case 1, PetAPInPropertiesWithAPString will only have additionalProperties. + // + // This is to make generated code same as m3. Actually there wont be side effect if we skip this check. + const objSchemas = schemas['objects']; + const usedByProp = schemas['objects']?.some((objSchema) => { + if ((objSchema).properties?.some((prop) => prop.schema === schema)) { + return true; + } + return false; + }); + if (!usedByProp) { + continue; + } + } + const td = this.resolver.resolveTypeDeclaration(schema, true, state); if (td instanceof NewObjectImplementation) { diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index ac6aa0c28da..3da5268c873 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -95,7 +95,7 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, thisNamespace.add(schemaName); // object types. - if (schema.type === SchemaType.Object) { + if (schema.type === SchemaType.Object || schema.type === SchemaType.Dictionary) { schema.language.csharp = { ...details, apiversion: thisApiversion, diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index c3fa1261842..0e85e2f05d5 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -158,11 +158,11 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr // this happens if there is a circular reference. // this means that this class should not attempt any inlining of that property at all . // dolauli pay attention to the condition check + const isDict = property.schema.type === SchemaType.Dictionary || (property.schema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary); const canInline = // (!property.schema.details.default['skip-inline']) && (!property.schema.language.default.byReference) && - // no additionalProperties in m4 - //(!(property.schema).additionalProperties) && + (!isDict) && (property.schema).language.default.inline === 'yes'; // the target has properties that we can inline @@ -190,7 +190,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr description: property.summary || '', originalContainingSchema: schema, alias: [], - required: !!property.required, + required: property.required || property.language.default.required, }; virtualProperties.owned.push(privateProperty); @@ -268,7 +268,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr description: property.summary || '', originalContainingSchema: schema, alias: [], - required: !!property.required + required: property.required || property.language.default.required }); } diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index 7cb8e0f7413..0f335587d91 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CodeModel, HttpHeader, ObjectSchema, Property } from '@azure-tools/codemodel'; +import { CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; @@ -10,7 +10,6 @@ import { StatusCodes } from '../utils/http-definitions'; import { Host } from '@azure-tools/autorest-extension-base'; - type State = NewModelState; async function tweakModel(state: State): Promise { @@ -18,6 +17,10 @@ async function tweakModel(state: State): Promise { addResponseHeaderSchema(model); + addDictionaryApiVersion(model); + + removeDictionaryDefaultDescription(model); + return model; } @@ -76,8 +79,60 @@ function addResponseHeaderSchema(model: CodeModel) { }); } +function addDictionaryApiVersion(model: CodeModel) { + // If object has dictionary property, this property's schema does not have api version information in m4. We should add this back. + + model.schemas.objects?.forEach((schema) => { + if (!schema.apiVersions) { + return; + } + + for (const prop of getAllProperties(schema)) { + if (prop.schema.type !== SchemaType.Dictionary || prop.schema.apiVersions) { + continue; + } + const dictSchema = prop.schema as DictionarySchema; + dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); + } + }) +} + +function removeDictionaryDefaultDescription(model: CodeModel) { + // For dictionary schema and property, if there is no description assigned, m4 will set a default description like: Dictionary of + // To keep same action as m3, we will set it to empty string + + const visited = new Set(); + [...model.schemas.objects ?? [], ...model.schemas.dictionaries ?? []].forEach((schema) => { + recursiveRemoveDefaultDescription(schema, visited); + }) +} + +function recursiveRemoveDefaultDescription(schema: Schema, visited: Set) { + if (visited.has(schema) || (schema.type !== SchemaType.Object && schema.type !== SchemaType.Dictionary)) { + return; + } + // Default description pattern in m4 + const defaultDescPattern = /Dictionary of <.*>$/; + visited.add(schema); + if (schema.type === SchemaType.Dictionary) { + const dictSchema = schema as DictionarySchema; + recursiveRemoveDefaultDescription(dictSchema.elementType, visited); + if (defaultDescPattern.test(dictSchema.language.default.description)) { + dictSchema.language.default.description = ''; + } + } else if (schema.type === SchemaType.Object) { + const objSchema = schema as ObjectSchema; + for (const prop of getAllProperties(objSchema)) { + recursiveRemoveDefaultDescription(prop.schema, visited); + if (prop.schema.type === SchemaType.Dictionary && defaultDescPattern.test(prop.language.default.description)) { + prop.language.default.description = ''; + } + } + } +} + export async function tweakM4ModelPlugin(service: Host) { const state = await new NewModelState(service).init(); - await service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); -} \ No newline at end of file + service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); +} From 666fb8213e26b5e3b3e84a3a397768a9c140beba Mon Sep 17 00:00:00 2001 From: LucasYao93 <53558334+LucasYao93@users.noreply.github.com> Date: Wed, 5 Aug 2020 22:45:46 +0800 Subject: [PATCH 30/61] Add test cases of data model. (#654) * Add test cases of autorest extension. * Add test cases of directive. * Add test case of directive. * Add test cases to AllowList. * Add test cases of datamodels. * Update AllList. --- tests-upgrade/Configuration.json | 1 + .../datamodels-combineschema/readme.md | 10 ++ .../datamodels-combineschema/swagger.json | 105 ++++++++++++++ .../datamodels-datatypes-object/readme.md | 10 ++ .../datamodels-datatypes-object/swagger.json | 131 ++++++++++++++++++ 5 files changed, 257 insertions(+) create mode 100644 tests-upgrade/datamodels-combineschema/readme.md create mode 100644 tests-upgrade/datamodels-combineschema/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-object/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-object/swagger.json diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 51c7d7c1ce7..73ac6021127 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -23,6 +23,7 @@ "datamodels-datatypes-array", "datamodels-datatypes-integer", "datamodels-datatypes-string", + "datamodels-combineschema", "directive-model", "directive-tableformat", "extension-ms-azureresource", diff --git a/tests-upgrade/datamodels-combineschema/readme.md b/tests-upgrade/datamodels-combineschema/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-combineschema/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-combineschema/swagger.json b/tests-upgrade/datamodels-combineschema/swagger.json new file mode 100644 index 00000000000..9f83a802c31 --- /dev/null +++ b/tests-upgrade/datamodels-combineschema/swagger.json @@ -0,0 +1,105 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/pets": { + "patch": { + "tags": [ + "pets" + ], + "operationId": "Pets_Update", + "description": "Gets pet list.", + "parameters": [ + { + "name": "pets", + "in": "body", + "required": true, + "description": "The pets update.", + "schema": { + "$ref":"#/definitions/Dog" + } + } + ], + "responses": { + "200": { + "description": "OK-Return workspace." + } + } + } + } + }, + "definitions": { + "Pet": { + "type": "object", + "properties": { + "petType": { + "type": "string" + } + } + }, + "Dog":{ + "type": "object", + "properties": { + "bark": { + "type": "boolean" + }, + "breed": { + "type": "string" + } + } + }, + "Cat": { + "allOf": [ + { + "$ref": "#/definitions/Pet" + + }, + { + "type": "object", + "properties": { + "hunts": { + "type": "boolean" + }, + "age": { + "type": "integer" + } + } + } + ] + + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-object/readme.md b/tests-upgrade/datamodels-datatypes-object/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-object/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-object/swagger.json b/tests-upgrade/datamodels-datatypes-object/swagger.json new file mode 100644 index 00000000000..b82571a6750 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-object/swagger.json @@ -0,0 +1,131 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + } + } + } + } + }, + "definitions": { + "Model": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer" + } + } + }, + "Model2": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ] + }, + "Model3": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "password": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ] + }, + "ContactInfo": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "phone": { + "type": "string" + } + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "contact_info": { + "$ref": "#/definitions/ContactInfo" + } + } + }, + "Model4": { + "type": "object", + "minProperties": 2, + "maxProperties": 10 + } + } +} \ No newline at end of file From ab8350cac06e901101f55fc987acf631213d9c14 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 10 Aug 2020 14:59:50 +0800 Subject: [PATCH 31/61] Add databricks, fix several issues (#658) --- powershell/llcsharp/model/interface.ts | 1 - powershell/llcsharp/model/property.ts | 2 +- powershell/models/model-extensions.ts | 4 - powershell/plugins/cs-namer-v2.ts | 9 +- powershell/plugins/plugin-tweak-m4-model.ts | 4 +- tests-upgrade/databricks/databricks.json | 1274 +++++++++++++++++++ tests-upgrade/databricks/readme.md | 105 ++ 7 files changed, 1388 insertions(+), 11 deletions(-) create mode 100644 tests-upgrade/databricks/databricks.json create mode 100644 tests-upgrade/databricks/readme.md diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index a4d8d61fd51..dd7f399a09c 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -360,7 +360,6 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla inherited: [], inlined: [] }; - // skip-for-time-being if (this.schema.language.csharp.virtualProperties) { for (const virtualProperty of values(virtualProperties.owned)) { diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index 0c87dd95aef..014eee82945 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -139,7 +139,7 @@ export class NewModelProperty extends BackedProperty implements EnhancedVariable this.apply(objectInitializer); this.description = description; this.required = isRequired; - if ((this.schema.type === SchemaType.Object || this.schema.type === SchemaType.Dictionary) && isAnExpression(this.get) && schema.language.csharp?.classImplementation) { + if ((this.schema.type === SchemaType.Object || this.schema.type === SchemaType.Dictionary || this.schema.type === SchemaType.Any) && isAnExpression(this.get) && schema.language.csharp?.classImplementation) { // for objects, the getter should auto-create a new object this.get = toExpression(`(${this.get.value} = ${this.get.value} ?? new ${schema.language.csharp?.fullname}())`); } diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 2032f7f4675..2c3051d2e65 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -279,10 +279,6 @@ export class NewModelExtensionsNamespace extends Namespace { // Add typeconverters to model classes (partial) for (const schemaGroup of values(schemas)) { - if (schemaGroup.length > 0 && (schemaGroup[0].type === SchemaType.Any)) { - // skip any - continue; - } for (const schema of values(schemaGroup)) { if (!schema || (schema.language.csharp && schema.language.csharp.skip)) { continue; diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 3da5268c873..5e15783833b 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -26,6 +26,9 @@ function setPropertyNames(schema: Schema) { return; } for (const propertySchema of values(schema.properties)) { + if (propertySchema.schema.type === SchemaType.Any) { + continue; + } const propertyDetails = propertySchema.language.default; propertyDetails.required = propertySchema.required ?? false; propertyDetails.readOnly = propertySchema.readOnly ?? false; @@ -95,7 +98,7 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, thisNamespace.add(schemaName); // object types. - if (schema.type === SchemaType.Object || schema.type === SchemaType.Dictionary) { + if (schema.type === SchemaType.Object || schema.type === SchemaType.Dictionary || schema.type === SchemaType.Any) { schema.language.csharp = { ...details, apiversion: thisApiversion, @@ -164,7 +167,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso const details = operation.language.default; // come up with a name - const oName = getPascalIdentifier(details.name); + const oName = getPascalIdentifier(operationGroup.$key + '_' + details.name); let i = 1; let operationName = oName; while (operationNames.has(operationName)) { @@ -175,7 +178,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso operation.language.csharp = { ...details, // inherit - name: getPascalIdentifier(operationGroup.language.default.name + '_' + operationName), + name: getPascalIdentifier(operationName), }; // parameters are camelCased. diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index 0f335587d91..b73b280fc01 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -88,10 +88,10 @@ function addDictionaryApiVersion(model: CodeModel) { } for (const prop of getAllProperties(schema)) { - if (prop.schema.type !== SchemaType.Dictionary || prop.schema.apiVersions) { + if ((prop.schema.type !== SchemaType.Dictionary && prop.schema.type !== SchemaType.Any) || prop.schema.apiVersions) { continue; } - const dictSchema = prop.schema as DictionarySchema; + const dictSchema = prop.schema; dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); } }) diff --git a/tests-upgrade/databricks/databricks.json b/tests-upgrade/databricks/databricks.json new file mode 100644 index 00000000000..76df17202e9 --- /dev/null +++ b/tests-upgrade/databricks/databricks.json @@ -0,0 +1,1274 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "x-ms-examples": { + "Get a workspace": { + "$ref": "./examples/WorkspaceGet.json" + }, + "Get a workspace with custom parameters": { + "$ref": "./examples/WorkspaceGetParameters.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns the workspace.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Delete", + "description": "Deletes the workspace.", + "x-ms-examples": { + "Delete a workspace": { + "$ref": "./examples/WorkspaceDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "204": { + "description": "NoContent" + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "200": { + "description": "OK. The request has succeeded." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "put": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_CreateOrUpdate", + "description": "Creates a new workspace.", + "x-ms-examples": { + "Create or update workspace": { + "$ref": "./examples/WorkspaceCreate.json" + }, + "Create or update workspace with custom parameters": { + "$ref": "./examples/WorkspaceCreateWithParameters.json" + }, + "Create a workspace which is ready for Customer-Managed Key (CMK) encryption": { + "$ref": "./examples/PrepareEncryption.json" + }, + "Enable Customer-Managed Key (CMK) encryption on a workspace which is prepared for encryption": { + "$ref": "./examples/EnableEncryption.json" + }, + "Revert Customer-Managed Key (CMK) encryption to Microsoft Managed Keys encryption on a workspace": { + "$ref": "./examples/DisableEncryption.json" + } + }, + "parameters": [ + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Workspace" + }, + "description": "Parameters supplied to the create or update a workspace." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Created - Returns information about the workspace, including provisioning status.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "201": { + "description": "Created - Returns information about the workspace, including provisioning status.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "patch": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Update", + "description": "Updates a workspace.", + "parameters": [ + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/WorkspaceUpdate" + }, + "description": "The update to the workspace." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Successfully updated the workspace.", + "schema": { + "$ref": "#/definitions/Workspace" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true, + "x-ms-examples": { + "Update a workspace's tags.": { + "$ref": "./examples/WorkspaceUpdate.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListByResourceGroup", + "description": "Gets all the workspaces within a resource group.", + "x-ms-examples": { + "Lists workspaces": { + "$ref": "./examples/WorkspacesListByResourceGroup.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns an array of workspaces.", + "schema": { + "$ref": "#/definitions/WorkspaceListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Databricks/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_ListBySubscription", + "description": "Gets all the workspaces within a subscription.", + "x-ms-examples": { + "Lists workspaces": { + "$ref": "./examples/WorkspacesListBySubscription.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK - Returns an array of workspaces.", + "schema": { + "$ref": "#/definitions/WorkspaceListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}/virtualNetworkPeerings/{peeringName}": { + "get": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_Get", + "description": "Gets the workspace vNet Peering.", + "x-ms-examples": { + "Get a workspace with vNet Peering Configured": { + "$ref": "./examples/WorkspaceVirtualNetPeeringGet.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "204": { + "description": "OK - NoContent" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_Delete", + "description": "Deletes the workspace vNetPeering.", + "x-ms-examples": { + "Delete a workspace vNet Peering": { + "$ref": "./examples/WorkspaceVirtualNetworkPeeringDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "204": { + "description": "NoContent" + }, + "200": { + "description": "OK. The request has succeeded." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + }, + "put": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_CreateOrUpdate", + "description": "Creates vNet Peering for workspace.", + "x-ms-examples": { + "Create vNet Peering for Workspace": { + "$ref": "./examples/WorkspaceVirtualNetworkPeeringCreateOrUpdate.json" + } + }, + "parameters": [ + { + "name": "VirtualNetworkPeeringParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + }, + "description": "Parameters supplied to the create workspace vNet Peering." + }, + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/PeeringNameParameter" + } + ], + "responses": { + "201": { + "description": "Created - Returns information about the workspace vNet peering, including provisioning status.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "200": { + "description": "Update succeeded - Returns information about the workspace vNet peering.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeering" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Databricks/workspaces/{workspaceName}/virtualNetworkPeerings": { + "get": { + "tags": [ + "vNetPeering" + ], + "operationId": "vNetPeering_ListByWorkspace", + "description": "Lists the workspace vNet Peerings.", + "x-ms-examples": { + "List all vNet Peerings for the workspace": { + "$ref": "./examples/WorkspaceVirtualNetPeeringList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceGroupName" + }, + { + "$ref": "#/parameters/WorkspaceName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "List succeeded. Returns the resulting resource objects in response body.", + "schema": { + "$ref": "#/definitions/VirtualNetworkPeeringList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.Databricks/operations": { + "get": { + "tags": [ + "Operations" + ], + "description": "Lists all of the available RP operations.", + "x-ms-examples": { + "Operations": { + "$ref": "./examples/OperationsList.json" + } + }, + "operationId": "Operations_List", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/OperationListResult" + } + }, + "default": { + "description": "Resource Provider error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "Workspace": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/WorkspaceProperties", + "description": "The workspace properties." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The SKU of the resource." + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "Information about workspace." + }, + "WorkspaceProperties": { + "properties": { + "managedResourceGroupId": { + "type": "string", + "description": "The managed resource group Id." + }, + "parameters": { + "$ref": "#/definitions/WorkspaceCustomParameters", + "description": "The workspace's custom parameters." + }, + "provisioningState": { + "readOnly": true, + "$ref": "#/definitions/ProvisioningState", + "description": "The workspace provisioning state." + }, + "uiDefinitionUri": { + "type": "string", + "description": "The blob URI where the UI definition file is located." + }, + "authorizations": { + "description": "The workspace provider authorizations.", + "type": "array", + "items": { + "$ref": "#/definitions/WorkspaceProviderAuthorization" + } + }, + "createdBy": { + "description": "Indicates the Object ID, PUID and Application ID of entity that created the workspace.", + "$ref": "#/definitions/CreatedBy" + }, + "updatedBy": { + "description": "Indicates the Object ID, PUID and Application ID of entity that last updated the workspace.", + "$ref": "#/definitions/CreatedBy" + }, + "createdDateTime": { + "description": "Specifies the date and time when the workspace is created.", + "$ref": "#/definitions/CreatedDateTime" + }, + "workspaceId": { + "readOnly": true, + "description": "The unique identifier of the databricks workspace in databricks control plane.", + "type": "string" + }, + "workspaceUrl": { + "readOnly": true, + "description": "The workspace URL which is of the format 'adb-{workspaceId}.{random}.azuredatabricks.net'", + "type": "string" + }, + "storageAccountIdentity": { + "description": "The details of Managed Identity of Storage Account", + "$ref": "#/definitions/ManagedIdentityConfiguration" + } + }, + "required": [ + "managedResourceGroupId" + ], + "description": "The workspace properties." + }, + "TrackedResource": { + "description": "The resource model definition for a ARM tracked top level resource", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "Resource": { + "description": "The core properties of ARM resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "Sku": { + "properties": { + "name": { + "type": "string", + "description": "The SKU name." + }, + "tier": { + "type": "string", + "description": "The SKU tier." + } + }, + "required": [ + "name" + ], + "description": "SKU for the resource." + }, + "ProvisioningState": { + "description": "Provisioning status of the workspace.", + "readOnly": true, + "enum": [ + "Accepted", + "Running", + "Ready", + "Creating", + "Created", + "Deleting", + "Deleted", + "Canceled", + "Failed", + "Succeeded", + "Updating" + ], + "type": "string", + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": false + } + }, + "PeeringProvisioningState": { + "type": "string", + "readOnly": true, + "description": "The current provisioning state.", + "enum": [ + "Succeeded", + "Updating", + "Deleting", + "Failed" + ], + "x-ms-enum": { + "name": "PeeringProvisioningState", + "modelAsString": false + } + }, + "ManagedIdentityConfiguration": { + "description": "The Managed Identity details for storage account.", + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The objectId of the Managed Identity that is linked to the Managed Storage account.", + "readOnly": true + }, + "tenantId": { + "type": "string", + "format": "uuid", + "description": "The tenant Id where the Managed Identity is created.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The type of Identity created. It can be either SystemAssigned or UserAssigned.", + "readOnly": true + } + } + }, + "WorkspaceCustomParameterType": { + "description": "Provisioning status of the workspace.", + "readOnly": true, + "enum": [ + "Bool", + "Object", + "String" + ], + "type": "string", + "x-ms-enum": { + "name": "CustomParameterType", + "modelAsString": false + } + }, + "WorkspaceCustomBooleanParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "boolean", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The value which should be used for this field." + }, + "WorkspaceCustomObjectParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "object", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The value which should be used for this field." + }, + "WorkspaceCustomStringParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "type": "string", + "description": "The value which should be used for this field." + } + }, + "required": [ + "value" + ], + "description": "The Value." + }, + "WorkspaceCustomParameters": { + "properties": { + "amlWorkspaceId": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The ID of a Azure Machine Learning workspace to link with Databricks workspace" + }, + "customVirtualNetworkId": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The ID of a Virtual Network where this Databricks Cluster should be created" + }, + "customPublicSubnetName": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The name of a Public Subnet within the Virtual Network" + }, + "customPrivateSubnetName": { + "$ref": "#/definitions/WorkspaceCustomStringParameter", + "description": "The name of the Private Subnet within the Virtual Network" + }, + "enableNoPublicIp": { + "$ref": "#/definitions/WorkspaceCustomBooleanParameter", + "description": "Should the Public IP be Disabled?" + }, + "prepareEncryption": { + "$ref": "#/definitions/WorkspaceCustomBooleanParameter", + "description": "Prepare the workspace for encryption. Enables the Managed Identity for managed storage account." + }, + "encryption": { + "$ref": "#/definitions/WorkspaceEncryptionParameter", + "description": "Contains the encryption details for Customer-Managed Key (CMK) enabled workspace." + }, + "requireInfrastructureEncryption": { + "$ref": "#/definitions/WorkspaceCustomBooleanParameter", + "description": "A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest." + } + }, + "description": "Custom Parameters used for Cluster Creation." + }, + "CreatedDateTime": { + "type": "string", + "format": "date-time", + "description": "The date and time stamp when the workspace was created.", + "readOnly": true + }, + "CreatedBy": { + "properties": { + "oid": { + "type": "string", + "format": "uuid", + "description": "The Object ID that created the workspace.", + "readOnly": true + }, + "puid": { + "type": "string", + "description": "The Personal Object ID corresponding to the object ID above", + "readOnly": true + }, + "applicationId": { + "type": "string", + "format": "uuid", + "description": "The application ID of the application that initiated the creation of the workspace. For example, Azure Portal.", + "readOnly": true + } + }, + "description": "Provides details of the entity that created/updated the workspace." + }, + "WorkspaceEncryptionParameter": { + "properties": { + "type": { + "$ref": "#/definitions/WorkspaceCustomParameterType", + "description": "The type of variable that this is" + }, + "value": { + "$ref": "#/definitions/Encryption", + "description": "The value which should be used for this field." + } + }, + "description": "The object that contains details of encryption used on the workspace." + }, + "Encryption": { + "properties": { + "keySource": { + "type": "string", + "description": "The encryption keySource (provider). Possible values (case-insensitive): Default, Microsoft.Keyvault", + "enum": [ + "Default", + "Microsoft.Keyvault" + ], + "x-ms-enum": { + "name": "KeySource", + "modelAsString": false + }, + "default": "Default" + }, + "KeyName": { + "type": "string", + "description": "The name of KeyVault key." + }, + "keyversion": { + "type": "string", + "description": "The version of KeyVault key.", + "x-ms-client-name": "KeyVersion" + }, + "keyvaulturi": { + "type": "string", + "description": "The Uri of KeyVault.", + "x-ms-client-name": "KeyVaultUri" + } + }, + "description": "The object that contains details of encryption used on the workspace." + }, + "WorkspaceProviderAuthorization": { + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The provider's principal identifier. This is the identity that the provider will use to call ARM to manage the workspace resources." + }, + "roleDefinitionId": { + "type": "string", + "format": "uuid", + "description": "The provider's role definition identifier. This role will define all the permissions that the provider must have on the workspace's container resource group. This role definition cannot have permission to delete the resource group." + } + }, + "required": [ + "principalId", + "roleDefinitionId" + ], + "description": "The workspace provider authorization." + }, + "WorkspaceUpdate": { + "description": "An update to a workspace.", + "type": "object", + "properties": { + "tags": { + "description": "Resource tags.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "ErrorDetail": { + "title": "Error details.", + "type": "object", + "properties": { + "code": { + "description": "The error's code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "target": { + "description": "Indicates which property in the request is responsible for the error.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorInfo": { + "title": "The code and message for an error.", + "type": "object", + "properties": { + "code": { + "description": "A machine readable error code.", + "type": "string" + }, + "message": { + "description": "A human readable error message.", + "type": "string" + }, + "details": { + "description": "error details.", + "type": "array", + "items": { + "$ref": "#/definitions/ErrorDetail" + } + }, + "innererror": { + "description": "Inner error details if they exist.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "ErrorResponse": { + "title": "Error response.", + "description": "Contains details when the response code indicates an error.", + "type": "object", + "properties": { + "error": { + "description": "The error details.", + "$ref": "#/definitions/ErrorInfo" + } + }, + "required": [ + "error" + ] + }, + "WorkspaceListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Workspace" + }, + "description": "The array of workspaces." + }, + "nextLink": { + "type": "string", + "description": "The URL to use for getting the next set of results." + } + }, + "description": "List of workspaces." + }, + "Operation": { + "description": "REST API operation", + "type": "object", + "properties": { + "name": { + "description": "Operation name: {provider}/{resource}/{operation}", + "type": "string" + }, + "display": { + "description": "The object that represents the operation.", + "properties": { + "provider": { + "description": "Service provider: Microsoft.ResourceProvider", + "type": "string" + }, + "resource": { + "description": "Resource on which the operation is performed.", + "type": "string" + }, + "operation": { + "description": "Operation type: Read, write, delete, etc.", + "type": "string" + } + } + } + } + }, + "OperationListResult": { + "description": "Result of the request to list Resource Provider operations. It contains a list of operations and a URL link to get the next set of results.", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Operation" + }, + "description": "List of Resource Provider operations supported by the Resource Provider resource provider." + }, + "nextLink": { + "type": "string", + "description": "URL to get the next set of operation list results if there are any." + } + } + }, + "VirtualNetworkPeeringList": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualNetworkPeering" + }, + "description": "List of virtual network peerings on workspace." + }, + "nextLink": { + "type": "string", + "description": "URL to get the next set of virtual network peering list results if there are any." + } + }, + "description": "Gets all virtual network peerings under a workspace." + }, + "VirtualNetworkPeering": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/VirtualNetworkPeeringPropertiesFormat", + "description": "List of properties for vNet Peering" + }, + "name": { + "type": "string", + "description": "Name of the virtual network peering resource", + "readOnly": true + }, + "id": { + "type": "string", + "description": "Resource ID.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "type of the virtual network peering resource", + "readOnly": true + } + }, + "required": [ + "properties" + ], + "description": "Peerings in a VirtualNetwork resource", + "x-ms-azure-resource": true + }, + "VirtualNetworkPeeringPropertiesFormat": { + "properties": { + "allowVirtualNetworkAccess": { + "type": "boolean", + "description": "Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space." + }, + "allowForwardedTraffic": { + "type": "boolean", + "description": "Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network." + }, + "allowGatewayTransit": { + "type": "boolean", + "description": "If gateway links can be used in remote virtual networking to link to this virtual network." + }, + "useRemoteGateways": { + "type": "boolean", + "description": "If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway." + }, + "databricksVirtualNetwork": { + "properties": { + "id": { + "type": "string", + "description": "The Id of the databricks virtual network." + } + }, + "description": " The remote virtual network should be in the same region. See here to learn more (https://docs.microsoft.com/en-us/azure/databricks/administration-guide/cloud-configurations/azure/vnet-peering)." + }, + "databricksAddressSpace": { + "$ref": "#/definitions/AddressSpace", + "description": "The reference to the databricks virtual network address space." + }, + "remoteVirtualNetwork": { + "properties": { + "id": { + "type": "string", + "description": "The Id of the remote virtual network." + } + }, + "description": " The remote virtual network should be in the same region. See here to learn more (https://docs.microsoft.com/en-us/azure/databricks/administration-guide/cloud-configurations/azure/vnet-peering)." + }, + "remoteAddressSpace": { + "$ref": "#/definitions/AddressSpace", + "description": "The reference to the remote virtual network address space." + }, + "peeringState": { + "type": "string", + "description": "The status of the virtual network peering.", + "enum": [ + "Initiated", + "Connected", + "Disconnected" + ], + "x-ms-enum": { + "name": "peeringState", + "modelAsString": false + }, + "readOnly": true + }, + "provisioningState": { + "readOnly": true, + "$ref": "#/definitions/PeeringProvisioningState", + "description": "The provisioning state of the virtual network peering resource." + } + }, + "required": [ + "remoteVirtualNetwork" + ], + "description": "Properties of the virtual network peering." + }, + "AddressSpace": { + "properties": { + "addressPrefixes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of address blocks reserved for this virtual network in CIDR notation." + } + }, + "description": "AddressSpace contains an array of IP address ranges that can be used by subnets of the virtual network." + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription." + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation." + }, + "ResourceGroupName": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "WorkspaceName": { + "name": "workspaceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace.", + "minLength": 3, + "maxLength": 64, + "x-ms-parameter-location": "method" + }, + "PeeringNameParameter": { + "name": "peeringName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the workspace vNet peering.", + "x-ms-parameter-location": "method" + } + } +} diff --git a/tests-upgrade/databricks/readme.md b/tests-upgrade/databricks/readme.md new file mode 100644 index 00000000000..fd7d8e5b4ef --- /dev/null +++ b/tests-upgrade/databricks/readme.md @@ -0,0 +1,105 @@ + +# Az.Databricks +This directory contains the PowerShell module for the Databricks service. + +--- +## Status +[![Az.Databricks](https://img.shields.io/powershellgallery/v/Az.Databricks.svg?style=flat-square&label=Az.Databricks "Az.Databricks")](https://www.powershellgallery.com/packages/Az.Databricks/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.Databricks`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g autorest@autorest`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest-beta` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - ./databricks.json + +module-version: 0.0.1 +title: Databricks +subject-prefix: $(service-name) + +inlining-threshold: 40 + +directive: + # Fix the error in swagger, RP actually returns 200 when deletion succeeds + # - from: swagger-document + # where: $ + # transform: return $.replace(/204/g, "200") + # Remove the unexpanded parameter set + - where: + variant: ^Create$|^CreateViaIdentity$|^CreateViaIdentityExpanded$|^Update$|^UpdateViaIdentity$ + remove: true + # Rename the parameter name to follow Azure PowerShell best practice + - where: + parameter-name: SkuName + set: + parameter-name: Sku + - where: + parameter-name: CustomVirtualNetworkIdValue + set: + parameter-name: VirtualNetworkId + - where: + parameter-name: CustomPublicSubnetNameValue + set: + parameter-name: PublicSubnetName + - where: + parameter-name: CustomPrivateSubnetNameValue + set: + parameter-name: PrivateSubnetName + # Remove the set-* cmdlet + - where: + verb: Set + remove: true + # Hide the New-* cmdlet for customization + - where: + verb: New + hide: true + - where: + model-name: Workspace + set: + format-table: + properties: + - Name + - Location + - ManagedResourceGroupId + labels: + ManagedResourceGroupId: Managed Resource Group ID +``` From 7e49371c6c4942d8d5070e1e685dd5117d26415c Mon Sep 17 00:00:00 2001 From: xichen Date: Mon, 10 Aug 2020 15:04:05 +0800 Subject: [PATCH 32/61] SupportDateTimeRfc1123 (#657) * SupportDateTimeRfc1123 * fix Co-authored-by: xichen --- powershell/llcsharp/schema/schema-resolver.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 04fb661e33b..3a667eb239a 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -183,7 +183,7 @@ export class NewSchemaDefinitionResolver { } return this.add(schema, new NewObjectImplementation(schema)); } - case SchemaType.Choice: + case SchemaType.Time: case SchemaType.String: { return new NewString(schema, required); @@ -193,8 +193,12 @@ export class NewSchemaDefinitionResolver { case SchemaType.Uuid: return new NewUuid(schema, required); case SchemaType.DateTime: + if ((schema).format === StringFormat.DateTimeRfc1123) { + return new NewDateTime1123(schema, required); + } return new NewDateTime(schema, required); - + case SchemaType.ByteArray: + return new NewByteArray(schema, required); case SchemaType.Boolean: return new NewBoolean(schema, required); @@ -227,10 +231,22 @@ export class NewSchemaDefinitionResolver { switch ((schema).valueType.type) { case SchemaType.String: return new NewEnumImplementation(schema, required); + case SchemaType.DateTime: + if ((schema).valueType.format === StringFormat.DateTimeRfc1123) { + return new NewDateTime1123(schema, required); + } + return new NewDateTime(schema, required); default: state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); throw new Error('Unknown Model. Fatal.'); } + case SchemaType.Choice: { + const choiceSchema = schema as ChoiceSchema; + if ((choiceSchema.choiceType).type === SchemaType.DateTime && (choiceSchema.choiceType).format === StringFormat.DateTimeRfc1123) { + return new NewDateTime1123(schema as DateTimeSchema, required); + } + return new NewString(schema, required); + } case SchemaType.SealedChoice: return new NewEnumImplementation(schema, required); case undefined: From 797c5d910a4e8017d42f0e09132431738d845920 Mon Sep 17 00:00:00 2001 From: Youri970410 <62531040+Youri970410@users.noreply.github.com> Date: Mon, 10 Aug 2020 16:16:42 +0800 Subject: [PATCH 33/61] Fix the BlackList issue (#656) * Fix the BlackList issue * Fix Create CompareResult Folder Issue It will not create 'CompareResult' folder if the file exists. --- tests-upgrade/AutoRestUpgradeTest.ps1 | 54 +++++++++++++++++---------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index 1d847ee0d73..e665fbfa6be 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -2,7 +2,10 @@ #Need to use the right version of node.js #nvs use 10.16.0 #Create folder to save Compare Results -New-Item CompareResult -ItemType "directory" +if(!(Test-Path CompareResult)) +{ + New-Item CompareResult -ItemType "directory" +} #Define the global param 'isError' to determine wheather throw the error $global:isError = $false #Import the Configuration Json @@ -36,6 +39,21 @@ function IsCommand([Object]$SourceFile , [Object]$TargetFile) return $isCommandResult } +#Determine the filefolder in BlackList +function IsInBlackList([Object]$JudgList,[Array]$BlackContent) +{ + $isInBlackListResult = $false + foreach($BlackDetail in $BlackContent) + { + if((!((Get-Item $JudgList.PSPath) -is [System.IO.DirectoryInfo])) -or ($JudgList.Name.Startswith($BlackDetail)) -or ($JudgList.Name.Startswith('Compare'))) + { + $isInBlackListResult = $True + break + } + } + return $isInBlackListResult +} + #Determine whether the file needs to be ignored function IsNeedIgnore([string]$inputFileName , [Array]$ignoreArray) { @@ -239,7 +257,7 @@ if($TestName -ne $null -and ($TestName -ne '')) foreach($eachTest in $whiteList) { $eachTest - cd ($PSScriptRoot+'\'+$eachTest) + cd (Join-Path $PSScriptRoot $eachTest) try { $IsGenerateSuccess = GenerateCode @@ -260,28 +278,26 @@ if($TestName -ne $null -and ($TestName -ne '')) #get each testfolder and except those tests in blacklist foreach($fileDetail in $fileList) { - foreach($blackTestName in $blackTestList) + $InBlackListResult = IsInBlackList -JudgList $fileDetail -BlackContent $blackTestList + if(!$InBlackListResult) { - - if(((Get-Item $fileDetail.PSPath) -is [System.IO.DirectoryInfo]) -and (!$fileDetail.Name.Startswith($blackTestName))) + try { - try - { - cd ($PSScriptRoot+'\'+$fileDetail.Name) - $IsGenerateSuccess = GenerateCode - if(-not $Generate -and $IsGenerateSuccess) - { - $sourceFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m3' - $targetFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m4' - CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDeatil.path - } - } - catch + Write-Host $fileDetail.Name + cd (Join-Path $PSScriptRoot $fileDetail.Name) + $IsGenerateSuccess = GenerateCode + if(-not $Generate -and $IsGenerateSuccess) { - Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + $sourceFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m3' + $targetFilePath = Join-Path $PSScriptRoot $fileDetail.Name 'generate\m4' + CompareGeneratedCode -inputSourcePath $sourceFilePath -inputTargetPath $targetFilePath -testFileName $fileDeatil.Name } } - } + catch + { + Write-Host -ForegroundColor yellow 'Generate error:' + $fileDetail.Name + } + } } } else From d18246fe098e6a5a608f518acb400192d7fd8078 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 11 Aug 2020 14:57:32 +0800 Subject: [PATCH 34/61] Fixed a completer related issue and add support for credential (#660) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential --- powershell/cmdlets/class.ts | 4 ++-- powershell/llcsharp/schema/schema-resolver.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index febc15e7298..02a10b162d9 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -2469,7 +2469,7 @@ export class NewCmdletClass extends Class { } const isEnum = propertyType.schema.language.csharp?.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } @@ -2614,7 +2614,7 @@ export class NewCmdletClass extends Class { } const isEnum = propertyType.schema.language.csharp?.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 3a667eb239a..7efda43ca1b 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -184,6 +184,7 @@ export class NewSchemaDefinitionResolver { return this.add(schema, new NewObjectImplementation(schema)); } case SchemaType.Time: + case SchemaType.Credential: case SchemaType.String: { return new NewString(schema, required); From d8fcf0cb87cc66a14480f77ca1762e4e8b748b70 Mon Sep 17 00:00:00 2001 From: xichen Date: Wed, 12 Aug 2020 11:05:43 +0800 Subject: [PATCH 35/61] Enable 3 test cases (#659) * enable test cases * disable datamodels-datatypes-object, cause we cannot handle any yet * fix dup name issue * fix comment Co-authored-by: xichen --- powershell/llcsharp/operation/method.ts | 12 ++++++------ powershell/package.json | 2 +- powershell/plugins/cs-namer-v2.ts | 2 ++ powershell/plugins/llcsharp.ts | 12 +----------- tests-upgrade/Configuration.json | 5 ++++- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 1efd7117ed6..a18586b58a3 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -396,20 +396,20 @@ export class NewOperationMethod extends Method { // replace any server params in the uri for (const pp of serverParams) { - url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + url = url.replace(`{${pp.param.language.default.serializedName}}`, `" + ${pp.name} + "`); } for (const pp of pathParams) { - rx = rx.replace(`{${pp.param.language.csharp?.name}}`, `(?<${pp.param.language.csharp?.name}>[^/]+)`); + rx = rx.replace(`{${pp.param.language.default.serializedName}}`, `(?<${pp.param.language.default.serializedName}>[^/]+)`); if (this.viaIdentity) { - url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + url = url.replace(`{${pp.param.language.default.serializedName}}`, `" + ${pp.name} + "`); } else { - url = url.replace(`{${pp.param.language.csharp?.name}}`, `" + url = url.replace(`{${pp.param.language.default.serializedName}}`, `" + ${newRemoveEncoding(pp, '', KnownMediaType.UriParameter)} + "`); } @@ -435,7 +435,7 @@ export class NewOperationMethod extends Method { yield EOL; yield '// replace URI parameters with values from identity'; for (const pp of pathParams) { - yield `var ${pp.name} = ${match.value}.Groups["${pp.param.language.csharp?.name}"].Value;`; + yield `var ${pp.name} = ${match.value}.Groups["${pp.param.language.default.serializedName}"].Value;`; } } @@ -469,7 +469,7 @@ export class NewOperationMethod extends Method { // content length is set when the request body is set continue; } - yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.csharp?.serializedName || hp.param.language.default.serializedName, ClientRuntime.SerializationMode.None); + yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.language.default.serializedName, ClientRuntime.SerializationMode.None); } yield EOL; } diff --git a/powershell/package.json b/powershell/package.json index 308f6e460d6..1579cc13cf0 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -66,4 +66,4 @@ "source-map-support": "0.5.13", "xmlbuilder": "10.1.1" } -} \ No newline at end of file +} diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 5e15783833b..260dc095464 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -140,6 +140,8 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, namespace: '', fullname: '' }; + // xichen: for invalid namespace case, we won't create model class. So we do not need consider dup case + thisNamespace.delete(schemaName); } // name each property in this schema diff --git a/powershell/plugins/llcsharp.ts b/powershell/plugins/llcsharp.ts index 0d84bd25793..b4735cdffbf 100644 --- a/powershell/plugins/llcsharp.ts +++ b/powershell/plugins/llcsharp.ts @@ -12,21 +12,11 @@ import { Dictionary } from '@azure-tools/linq'; const resources = `${__dirname}/../../resources`; -function outerTest(service: Host, project: Project, fname: string, content: string) { - service.WriteFile(join(project.apifolder, fname), test(content, project.overrides), undefined, 'source-file-csharp'); -} - -function test(content: string, overrides: Dictionary): string { - const a = applyOverrides(content, overrides); - return a; -} - export async function llcsharp(service: Host) { try { const project = await new Project(service).init(); - await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), test(content, project.overrides), undefined, 'source-file-csharp')); - await project.writeFiles(async (fname, content) => outerTest(service, project, fname, content)); + await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); // recursive copy resources await copyResources(join(resources, 'runtime', 'csharp', 'client'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 73ac6021127..2bf7cc7583e 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -32,7 +32,10 @@ "extension-ms-discriminatorvalue", "extension-ms-examples", "extension-ms-longruningoperation", - "extension-ms-pageable" + "extension-ms-pageable", + "directive-aliasremoval", + "directive-cmdlet", + "directive-parameter" ], "BlackList": [ "basic-get-querystr", From b861314a3cd4376e38b93c6b323530daffb67d7c Mon Sep 17 00:00:00 2001 From: xichen Date: Thu, 13 Aug 2020 09:26:12 +0800 Subject: [PATCH 36/61] Fix some issues (#663) Co-authored-by: xichen --- powershell/llcsharp/operation/method.ts | 3 +-- powershell/plugins/cs-namer-v2.ts | 4 +++- powershell/plugins/plugin-tweak-m4-model.ts | 8 ++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index a18586b58a3..f20a51ef635 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -383,8 +383,7 @@ export class NewOperationMethod extends Method { rx = rx.substr(0, idx); } - - let url = `${baseUrl}/${rx.startsWith('/') ? rx.substr(1) : rx}`; + let url = `${baseUrl}/${path.startsWith('/') ? path.substr(1) : path}`; const serverParams = this.methodParameters.filter(each => each.param.protocol.http?.in === ParameterLocation.Uri); diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 260dc095464..6a6c66c3911 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -153,7 +153,9 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, // and the value names themselves for (const value of values(schema.language.csharp.enum.values)) { - (value).name = getPascalIdentifier((value).name); + // In m3, enum.name and enum.value are same. But in m4, enum.name is named by m4. + // To keep same action as m3, use enum.value here + (value).name = getPascalIdentifier((value).value); } } } diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index b73b280fc01..3bf59ab1ca4 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -91,8 +91,12 @@ function addDictionaryApiVersion(model: CodeModel) { if ((prop.schema.type !== SchemaType.Dictionary && prop.schema.type !== SchemaType.Any) || prop.schema.apiVersions) { continue; } - const dictSchema = prop.schema; - dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); + const dictSchema = prop.schema as DictionarySchema; + if (dictSchema.elementType && dictSchema.elementType.apiVersions) { + dictSchema.apiVersions = JSON.parse(JSON.stringify(dictSchema.elementType.apiVersions)); + } else { + dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); + } } }) } From 7400f1741b6d80f38b7e9bf4aa14c36559368635 Mon Sep 17 00:00:00 2001 From: Youri970410 <62531040+Youri970410@users.noreply.github.com> Date: Thu, 13 Aug 2020 09:49:52 +0800 Subject: [PATCH 37/61] Update some test cases (#661) * Update some testcase Add some testcases and delete some failed testcases * Revert "Update some testcase" This reverts commit 38b9e87fce73fc500827baeb36bd9dae89b850bb. * Submit some test cases and fix some problems with the script --- tests-upgrade/AutoRestUpgradeTest.ps1 | 9 +- tests-upgrade/Configuration.json | 2 + .../component-param-additional/readme.md | 10 + .../component-param-additional/swagger.json | 362 +++++++ .../component-param-grouping/readme.md | 10 + .../component-param-grouping/swagger.json | 251 +++++ .../readme.md | 10 + .../swagger.json | 302 ++++++ .../readme.md | 10 + .../swagger.json | 969 ++++++++++++++++++ .../readme.md | 10 + .../swagger.json | 200 ++++ .../examples/bool_getFalse.json | 8 + .../examples/bool_getNull.json | 6 + .../examples/bool_getTrue.json | 9 + .../examples/bool_putFalse.json | 8 + .../examples/bool_putTrue.json | 9 + .../datamodels-datatypes-boolean/readme.md | 10 + .../datamodels-datatypes-boolean/swagger.json | 230 +++++ .../examples/byte_getEmpty.json | 8 + .../examples/byte_getInvalid.json | 8 + .../examples/byte_getNonAscii.json | 8 + .../examples/byte_getNull.json | 6 + .../examples/byte_putNonAscii.json | 8 + .../datamodels-datatypes-byte/readme.md | 10 + .../datamodels-datatypes-byte/swagger.json | 188 ++++ .../examples/date_getMaxDate.json | 8 + .../examples/date_getMinDate.json | 8 + .../examples/date_getNull.json | 8 + .../examples/date_putMaxDate.json | 8 + .../examples/date_putMinDate.json | 8 + .../datamodels-datatypes-date/readme.md | 10 + .../datamodels-datatypes-date/swagger.json | 259 +++++ ...ime_getLocalNegativeOffsetMinDateTime.json | 8 + .../datetime_getLocalNoOffsetMinDateTime.json | 8 + ...calPositiveOffsetLowercaseMaxDateTime.json | 8 + ...calPositiveOffsetUppercaseMaxDateTime.json | 8 + .../examples/datetime_getNull.json | 8 + .../datetime_getUtcLowercaseMaxDateTime.json | 8 + .../examples/datetime_getUtcMinDateTime.json | 8 + .../datetime_getUtcUppercaseMaxDateTime.json | 8 + ...ime_putLocalNegativeOffsetMinDateTime.json | 8 + ...ime_putLocalPositiveOffsetMaxDateTime.json | 8 + .../examples/datetime_putUtcMaxDateTime.json | 8 + .../examples/datetime_putUtcMinDateTime.json | 8 + .../datamodels-datatypes-datetime/readme.md | 10 + .../swagger.json | 636 ++++++++++++ .../datamodels-datatypes-file/readme.md | 10 + .../datamodels-datatypes-file/swagger.json | 64 ++ 49 files changed, 3785 insertions(+), 1 deletion(-) create mode 100644 tests-upgrade/component-param-additional/readme.md create mode 100644 tests-upgrade/component-param-additional/swagger.json create mode 100644 tests-upgrade/component-param-grouping/readme.md create mode 100644 tests-upgrade/component-param-grouping/swagger.json create mode 100644 tests-upgrade/component-param-resourceasarraay/readme.md create mode 100644 tests-upgrade/component-param-resourceasarraay/swagger.json create mode 100644 tests-upgrade/component-param-specialproperties/readme.md create mode 100644 tests-upgrade/component-param-specialproperties/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean-quirks/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-boolean-quirks/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/examples/bool_getFalse.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/examples/bool_getNull.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/examples/bool_getTrue.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/examples/bool_putFalse.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/examples/bool_putTrue.json create mode 100644 tests-upgrade/datamodels-datatypes-boolean/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-boolean/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/examples/byte_getEmpty.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/examples/byte_getInvalid.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/examples/byte_getNonAscii.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/examples/byte_getNull.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/examples/byte_putNonAscii.json create mode 100644 tests-upgrade/datamodels-datatypes-byte/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-byte/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-date/examples/date_getMaxDate.json create mode 100644 tests-upgrade/datamodels-datatypes-date/examples/date_getMinDate.json create mode 100644 tests-upgrade/datamodels-datatypes-date/examples/date_getNull.json create mode 100644 tests-upgrade/datamodels-datatypes-date/examples/date_putMaxDate.json create mode 100644 tests-upgrade/datamodels-datatypes-date/examples/date_putMinDate.json create mode 100644 tests-upgrade/datamodels-datatypes-date/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-date/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNegativeOffsetMinDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNoOffsetMinDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetLowercaseMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetUppercaseMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getNull.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcLowercaseMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcMinDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcUppercaseMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalNegativeOffsetMinDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalPositiveOffsetMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMaxDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMinDateTime.json create mode 100644 tests-upgrade/datamodels-datatypes-datetime/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-datetime/swagger.json create mode 100644 tests-upgrade/datamodels-datatypes-file/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-file/swagger.json diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index e665fbfa6be..938758f39bf 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -6,6 +6,8 @@ if(!(Test-Path CompareResult)) { New-Item CompareResult -ItemType "directory" } +#Define the success code names +$global:testNameStr #Define the global param 'isError' to determine wheather throw the error $global:isError = $false #Import the Configuration Json @@ -226,8 +228,11 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, { $global:isError=$True $filename = Join-Path $PSScriptRoot 'CompareResult' ($testFileName + (get-date -format 'yyyyMMddhhmmss') + '.csv') - $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Export-CSV -path $filename + $difArray | Select-Object -Property fileName,Path,fileFolderName,Status | Sort-Object -Property fileName | Export-CSV -path $filename Write-Warning ('There are ' + $difArray.Count + ' different files') + }else + { + $global:testNameStr+= $testFileName +"`n" } } @@ -328,6 +333,8 @@ else } } cd $PSScriptRoot +write-Host $global:testNameStr +$global:testNameStr | Out-File .\CompareResult\GenerateSuccessList.Txt #Throw error if there are some different if($global:isError) { diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 2bf7cc7583e..5c27182b76c 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -32,7 +32,9 @@ "extension-ms-discriminatorvalue", "extension-ms-examples", "extension-ms-longruningoperation", + "extension-ms-mutability", "extension-ms-pageable", + "extension-ms-paramlocation", "directive-aliasremoval", "directive-cmdlet", "directive-parameter" diff --git a/tests-upgrade/component-param-additional/readme.md b/tests-upgrade/component-param-additional/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-additional/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-additional/swagger.json b/tests-upgrade/component-param-additional/swagger.json new file mode 100644 index 00000000000..c958f3ec259 --- /dev/null +++ b/tests-upgrade/component-param-additional/swagger.json @@ -0,0 +1,362 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/additionalProperties/true": { + "put": { + "operationId": "Pets_CreateAPTrue", + "description": "Create a Pet which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "description": "The ID of the target subscription.", + "schema":{ + "$ref":"#/definitions/PetAPTrue" + } + } + ], + "responses": { + "200": { + "description": "A Pet which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/PetAPTrue" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/additionalProperties/true-subclass": { + "put":{ + "operationId": "Pets_CreateCatAPTrue", + "description": "Create a CatAPTrue which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/CatAPTrue" + } + } + ], + "responses": { + "200": { + "description": "A CatAPTrue which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/CatAPTrue" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/additionalProperties/type/object": { + "put": { + "operationId": "Pets_CreateAPObject", + "description": "Create a Pet which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PetAPObject" + } + } + ], + "responses": { + "200": { + "description": "A Pet which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/PetAPObject" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/additionalProperties/type/string": { + "put": { + "operationId": "Pets_CreateAPString", + "description": "Create a Pet which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PetAPString" + } + } + ], + "responses": { + "200": { + "description": "A Pet which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/PetAPString" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/additionalProperties/in/properties": { + "put": { + "operationId": "Pets_CreateAPInProperties", + "description": "Create a Pet which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PetAPInProperties" + } + } + ], + "responses": { + "200": { + "description": "A Pet which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/PetAPInProperties" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/additionalProperties/in/properties/with/additionalProperties/string": { + "put": { + "operationId": "Pets_CreateAPInPropertiesWithAPString", + "description": "Create a Pet which contains more properties than what is defined.", + "parameters": [ + { + "name": "createParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PetAPInPropertiesWithAPString" + } + } + ], + "responses": { + "200": { + "description": "A Pet which contains more properties than what is defined.", + "schema": { + "$ref": "#/definitions/PetAPInPropertiesWithAPString" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "PetAPTrue":{ + "required": [ + "id" + ], + "type": "object", + "properties":{ + "id": { + "type":"integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "boolean", + "readOnly": true + } + }, + "additionalProperties": true + }, + "CatAPTrue": { + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/PetAPTrue" + } + ], + "properties": { + "friendly": { + "type": "boolean" + } + } + }, + "PetAPObject": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "boolean", + "readOnly": true + } + }, + "additionalProperties": { + "type": "object" + } + }, + "PetAPString": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "boolean", + "readOnly": true + } + }, + "additionalProperties": { + "type": "string" + } + }, + "PetAPInProperties": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "boolean", + "readOnly": true + }, + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "number" + } + } + } + }, + "PetAPInPropertiesWithAPString": { + "type": "object", + "required": [ + "id", + "@odata.location" + ], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "boolean", + "readOnly": true + }, + "@odata.location": { + "type": "string" + }, + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "number" + } + } + }, + "additionalProperties": { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-param-grouping/readme.md b/tests-upgrade/component-param-grouping/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-grouping/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-grouping/swagger.json b/tests-upgrade/component-param-grouping/swagger.json new file mode 100644 index 00000000000..2df96c6d54f --- /dev/null +++ b/tests-upgrade/component-param-grouping/swagger.json @@ -0,0 +1,251 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/parameterGrouping/postRequired/{path}": { + "post": { + "operationId": "parameterGrouping_postRequired", + "description": "Post a bunch of required parameters grouped", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "description":"Post a bunch of required parameters grouped", + "schema":{ + "type":"integer", + "format":"int32" + }, + "x-ms-parameter-grouping": { + } + }, + { + "name": "customHeader", + "in": "header", + "type": "string", + "required": false, + "x-ms-parameter-grouping": { + } + }, + { + "name": "query", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "default": 30, + "description": "Query parameter with default", + "x-ms-parameter-grouping": { + } + }, + { + "name": "path", + "in": "path", + "required": true, + "type": "string", + "description": "Path parameter", + "x-ms-parameter-grouping": { + } + } + ], + "responses": { + "200": { + "description": "Success" + + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/parameterGrouping/postOptional": { + "post":{ + "operationId": "parameterGrouping_postOptional", + "description": "Post a bunch of optional parameters grouped", + "parameters": [ + { + "name": "customHeader", + "in": "header", + "type": "string", + "required": false, + "x-ms-parameter-grouping": { + } + }, + { + "name": "query", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "default": 30, + "description": "Query parameter with default", + "x-ms-parameter-grouping": { + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/parameterGrouping/postMultipleParameterGroups": { + "post": { + "operationId": "parameterGrouping_postMultiParamGroups", + "description": "Post parameters from multiple different parameter groups", + "parameters": [ + { + "name": "header-one", + "in": "header", + "type": "string", + "required": false, + "x-ms-parameter-grouping": { + "name": "first-parameter-group" + } + }, + { + "name": "query-one", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "default": 30, + "description": "Query parameter with default", + "x-ms-parameter-grouping": { + "name": "first-parameter-group" + } + }, + { + "name": "header-two", + "in": "header", + "type": "string", + "required": false, + "x-ms-parameter-grouping": { + "postfix": "second-param-group" + } + }, + { + "name": "query-two", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "default": 30, + "description": "Query parameter with default", + "x-ms-parameter-grouping": { + "postfix": "second-param-group" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/parameterGrouping/sharedParameterGroupObject": { + "put": { + "operationId": "parameterGrouping_postSharedParameterGroupObject", + "description": "Post parameters with a shared parameter group object", + "parameters": [ + { + "name": "header-one", + "in": "header", + "type": "string", + "required": false, + "x-ms-parameter-grouping": { + "name": "first-parameter-group" + } + }, + { + "name": "query-one", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "default": 30, + "description": "Query parameter with default", + "x-ms-parameter-grouping": { + "name": "first-parameter-group" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-param-resourceasarraay/readme.md b/tests-upgrade/component-param-resourceasarraay/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-resourceasarraay/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-resourceasarraay/swagger.json b/tests-upgrade/component-param-resourceasarraay/swagger.json new file mode 100644 index 00000000000..51dbe32aeeb --- /dev/null +++ b/tests-upgrade/component-param-resourceasarraay/swagger.json @@ -0,0 +1,302 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/azure/resource-flatten/array": { + "put": { + "operationId": "putArray", + "description": "Put External Resource as an Array", + "externalDocs": { + "url": "http://tempuri.org" + }, + "parameters": [ + { + "name": "ResourceArray", + "description": "External Resource as an Array to put", + "in": "body", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Resource" + } + } + } + ], + "responses": { + "200": { + "description": "Successful Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "getArray", + "description": "Get External Resource as an Array", + "externalDocs": { + "url": "http://tempuri.org" + }, + "responses": { + "200": { + "description": "External Resource as an Array from get", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/FlattenedProduct" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azure/resource-flatten/dictionary": { + "put": { + "operationId": "putDictionary", + "description": "Put External Resource as a Dictionary", + "externalDocs": { + "url": "http://tempuri.org" + }, + "parameters": [ + { + "name": "ResourceDictionary", + "description": "External Resource as a Dictionary to put", + "in": "body", + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/FlattenedProduct" + } + } + } + ], + "responses": { + "200": { + "description": "Successful Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "getDictionary", + "description": "Get External Resource as a Dictionary", + "externalDocs": { + "url": "http://tempuri.org" + }, + "responses": { + "200": { + "description": "External Resource as a Dictionary from get", + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/FlattenedProduct" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azure/resource-flatten/resourcecollection": { + "put": { + "operationId": "putResourceCollection", + "description": "Put External Resource as a ResourceCollection", + "externalDocs": { + "url": "http://tempuri.org" + }, + "parameters": [ + { + "name": "ResourceComplexObject", + "description": "External Resource as a ResourceCollection to put", + "in": "body", + "schema": { + "$ref": "#/definitions/ResourceCollection" + } + } + ], + "responses": { + "200": { + "description": "Successful Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "getResourceCollection", + "description": "Get External Resource as a ResourceCollection", + "externalDocs": { + "url": "http://tempuri.org" + }, + "responses": { + "200": { + "description": "External Resource as a ResourceCollection from get", + "schema": { + "$ref": "#/definitions/ResourceCollection" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + }, + "Resource": { + "type": "object", + "x-ms-azure-resource": true, + "description": "Some resource", + "externalDocs": { + "url": "http://tempuri.org" + }, + "properties": { + "id": { + "type": "string", + "description": "Resource Id", + "readOnly": true + }, + "type": { + "type": "string", + "description": "Resource Type", + "readOnly": true + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "location": { + "type": "string", + "description": "Resource Location" + }, + "name": { + "type": "string", + "description": "Resource Name", + "readOnly": true + } + } + }, + "FlattenedProduct": { + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/FlattenedResourceProperties" + } + } + }, + "FlattenedResourceProperties": { + "type": "object", + "properties": { + "pname": { + "type": "string" + }, + "lsize": { + "type": "integer", + "format": "int32" + }, + "provisioningState": { + "type": "string" + } + } + }, + "ResourceCollection": { + "type": "object", + "properties": { + "productresource": { + "type": "object", + "$ref": "#/definitions/FlattenedProduct" + }, + "arrayofresources": { + "type": "array", + "items": { + "$ref": "#/definitions/FlattenedProduct" + } + }, + "dictionaryofresources": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/FlattenedProduct" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/component-param-specialproperties/readme.md b/tests-upgrade/component-param-specialproperties/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/component-param-specialproperties/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/component-param-specialproperties/swagger.json b/tests-upgrade/component-param-specialproperties/swagger.json new file mode 100644 index 00000000000..718820f033b --- /dev/null +++ b/tests-upgrade/component-param-specialproperties/swagger.json @@ -0,0 +1,969 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/azurespecials/overwrite/x-ms-client-request-id/method/": { + "get": { + "operationId": "x-ms-client-request-id_Get", + "description": "Get method that overwrites x-ms-client-request header with value 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "responses": { + "200": { + "description": "Successfully received the '9C4D50EE-2D56-4CD3-8152-34347DC9F2B0' x-ms-client-request header" + }, + "default": { + "description": "Unexpected error" + } + } + } + }, + "/azurespecials/overwrite/x-ms-client-request-id/via-param/method/": { + "get": { + "operationId": "x-ms-client-request-id_ParamGet", + "description": "Get method that overwrites x-ms-client-request header with value 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "parameters": [ + { + "name": "x-ms-client-request-id", + "in": "header", + "description": "This should appear as a method parameter, use value '9C4D50EE-2D56-4CD3-8152-34347DC9F2B0'", + "type": "string", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully received the '9C4D50EE-2D56-4CD3-8152-34347DC9F2B0' x-ms-client-request header" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/method/string/none/path/global/1234-5678-9012-3456/{subscriptionId}": { + "post": { + "operationId": "subscriptionInCredentials_postMethodGlobalValid", + "description": "POST method with subscriptionId modeled in credentials. Set the credential subscriptionId to '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalSubscriptionId" + } + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from credentials" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/method/string/none/path/global/null/{subscriptionId}": { + "post": { + "operationId": "subscriptionInCredentials_postMethodGlobalNull", + "description": "POST method with subscriptionId modeled in credentials. Set the credential subscriptionId to null, and client-side validation should prevent you from making this call", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalSubscriptionId" + } + ], + "responses": { + "200": { + "description": "This should never occur - you should be prevented from calling this method with null subscription Id in credentials" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/method/string/none/path/globalNotProvided/1234-5678-9012-3456/{subscriptionId}": { + "post": { + "operationId": "subscriptionInCredentials_postMethodGlobalNotProvidedValid", + "description": "POST method with subscriptionId modeled in credentials. Set the credential subscriptionId to '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalSubscriptionId" + }, + { + "$ref": "#/parameters/globalApiVersion" + } + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from credentials" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/method/string/none/path/local/1234-5678-9012-3456/{subscriptionId}": { + "post": { + "operationId": "subscriptionInMethod_postMethodLocalValid", + "description": "POST method with subscriptionId modeled in the method. pass in subscription id = '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInMethod Operations" + ], + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "description": "This should appear as a method parameter, use value '1234-5678-9012-3456'", + "type": "string", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/method/string/none/path/local/null/{subscriptionId}": { + "post": { + "operationId": "subscriptionInMethod_postMethodLocalNull", + "description": "POST method with subscriptionId modeled in the method. pass in subscription id = null, client-side validation should prevent you from making this call", + "tags": [ + "SubscriptionInMethod Operations" + ], + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "description": "This should appear as a method parameter, use value null, client-side validation should prvenet the call", + "type": "string", + "required": true + } + ], + "responses": { + "200": { + "description": "You should not reach this response - client side validation should prevent yopu from sending a null subscriptionId" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/path/string/none/path/global/1234-5678-9012-3456/{subscriptionId}": { + "parameters": [ + { + "$ref": "#/parameters/globalSubscriptionId" + } + ], + "post": { + "operationId": "subscriptionInCredentials_postPathGlobalValid", + "description": "POST method with subscriptionId modeled in credentials. Set the credential subscriptionId to '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from credentials" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/path/string/none/path/local/1234-5678-9012-3456/{subscriptionId}": { + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "description": "Should appear as a method parameter -use value '1234-5678-9012-3456'", + "type": "string", + "required": true + } + ], + "post": { + "operationId": "subscriptionInMethod_postPathLocalValid", + "description": "POST method with subscriptionId modeled in the method. pass in subscription id = '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInMethod Operations" + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/swagger/string/none/path/global/1234-5678-9012-3456/{subscriptionId}": { + "post": { + "operationId": "subscriptionInCredentials_postSwaggerGlobalValid", + "description": "POST method with subscriptionId modeled in credentials. Set the credential subscriptionId to '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInCredentials Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalSubscriptionId" + } + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from credentials" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/subscriptionId/swagger/string/none/path/local/1234-5678-9012-3456/{subscriptionId}": { + "post": { + "operationId": "subscriptionInMethod_postSwaggerLocalValid", + "description": "POST method with subscriptionId modeled in the method. pass in subscription id = '1234-5678-9012-3456' to succeed", + "tags": [ + "SubscriptionInMethod Operations" + ], + "parameters": [ + { + "name": "subscriptionId", + "in": "path", + "description": "The subscriptionId, which appears in the path, the value is always '1234-5678-9012-3456'", + "type": "string", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully received the '1234-5678-9012-3456' credential value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/method/string/none/query/global/2015-07-01-preview": { + "get": { + "operationId": "apiVersionDefault_getMethodGlobalValid", + "description": "GET method with api-version modeled in global settings.", + "tags": [ + "ApiVersionDefault Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalApiVersion" + } + ], + "responses": { + "200": { + "description": "Successfully received the '2015-07-01-preview' api-version value from global client settings" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/method/string/none/query/globalNotProvided/2015-07-01-preview": { + "get": { + "operationId": "apiVersionDefault_getMethodGlobalNotProvidedValid", + "description": "GET method with api-version modeled in global settings.", + "tags": [ + "ApiVersionDefault Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalApiVersion" + } + ], + "responses": { + "200": { + "description": "Successfully received the '2015-07-01-preview' credential value from global client settings" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/method/string/none/query/local/2.0": { + "get": { + "operationId": "apiVersionLocal_getMethodLocalValid", + "description": "Get method with api-version modeled in the method. pass in api-version = '2.0' to succeed", + "tags": [ + "ApiVersionLocal Operations" + ], + "parameters": [ + { + "name": "api-version", + "in": "query", + "description": "This should appear as a method parameter, use value '2.0'", + "type": "string", + "required": true, + "enum": [ "2.0" ], + "x-ms-api-version": false + } + ], + "responses": { + "200": { + "description": "Successfully received the '2.0' api-version value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/method/string/none/query/local/null": { + "get": { + "operationId": "apiVersionLocal_getMethodLocalNull", + "description": "Get method with api-version modeled in the method. pass in api-version = null to succeed", + "tags": [ + "ApiVersionLocal Operations" + ], + "parameters": [ + { + "name": "api-version", + "in": "query", + "description": "This should appear as a method parameter, use value null, this should result in no serialized parameter", + "type": "string", + "x-ms-api-version": false + } + ], + "responses": { + "200": { + "description": "Successfully received no api-version value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/path/string/none/query/global/2015-07-01-preview": { + "parameters": [ + { + "$ref": "#/parameters/globalApiVersion" + } + ], + "get": { + "operationId": "apiVersionDefault_getPathGlobalValid", + "description": "GET method with api-version modeled in global settings.", + "tags": [ + "ApiVersionDefault Operations" + ], + "responses": { + "200": { + "description": "Successfully received the '2015-07-01-preview' api-version value from global client settings" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/path/string/none/query/local/2.0": { + "parameters": [ + { + "name": "api-version", + "in": "query", + "description": "This should appear as a method parameter, use value '2.0'", + "type": "string", + "required": true, + "enum": [ "2.0" ], + "x-ms-api-version": false + } + ], + "get": { + "operationId": "apiVersionLocal_getPathLocalValid", + "description": "Get method with api-version modeled in the method. pass in api-version = '2.0' to succeed", + "tags": [ + "ApiVersionLocal Operations" + ], + "responses": { + "200": { + "description": "Successfully received the '2.0' api-version value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/swagger/string/none/query/global/2015-07-01-preview": { + "get": { + "operationId": "apiVersionDefault_getSwaggerGlobalValid", + "description": "GET method with api-version modeled in global settings.", + "tags": [ + "ApiVersionDefault Operations" + ], + "parameters": [ + { + "$ref": "#/parameters/globalApiVersion" + } + ], + "responses": { + "200": { + "description": "Successfully received the '2015-07-01-preview' api-version value from global client settings" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/apiVersion/swagger/string/none/query/local/2.0": { + "get": { + "operationId": "apiVersionLocal_getSwaggerLocalValid", + "description": "Get method with api-version modeled in the method. pass in api-version = '2.0' to succeed", + "tags": [ + "ApiVersionLocal Operations" + ], + "parameters": [ + { + "name": "api-version", + "in": "query", + "description": "The api version, which appears in the query, the value is always '2.0'", + "type": "string", + "required": true, + "enum": [ "2.0" ], + "x-ms-api-version": false + } + ], + "responses": { + "200": { + "description": "Successfully received the '2.0' api-version value from the local parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/method/path/valid/{unencodedPathParam}": { + "get": { + "operationId": "skipUrlEncoding_getMethodPathValid", + "description": "Get method with unencoded path parameter with value 'path1/path2/path3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "parameters": [ + { + "name": "unencodedPathParam", + "in": "path", + "description": "Unencoded path parameter with value 'path1/path2/path3'", + "type": "string", + "required": true, + "x-ms-skip-url-encoding": true + } + ], + "responses": { + "200": { + "description": "Successfully received the path parameter with value 'path1/path2/path3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/path/path/valid/{unencodedPathParam}": { + "parameters": [ + { + "name": "unencodedPathParam", + "in": "path", + "description": "Unencoded path parameter with value 'path1/path2/path3'", + "type": "string", + "required": true, + "x-ms-skip-url-encoding": true + } + ], + "get": { + "operationId": "skipUrlEncoding_getPathPathValid", + "description": "Get method with unencoded path parameter with value 'path1/path2/path3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "responses": { + "200": { + "description": "Successfully received the path parameter with value 'path1/path2/path3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/swagger/path/valid/{unencodedPathParam}": { + "get": { + "operationId": "skipUrlEncoding_getSwaggerPathValid", + "description": "Get method with unencoded path parameter with value 'path1/path2/path3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "parameters": [ + { + "name": "unencodedPathParam", + "in": "path", + "description": "An unencoded path parameter with value 'path1/path2/path3'", + "type": "string", + "required": true, + "enum": [ "path1/path2/path3" ], + "x-ms-skip-url-encoding": true + } + ], + "responses": { + "200": { + "description": "Successfully received the path parameter with value 'path1/path2/path3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/method/query/valid": { + "get": { + "operationId": "skipUrlEncoding_getMethodQueryValid", + "description": "Get method with unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "parameters": [ + { + "name": "q1", + "in": "query", + "description": "Unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "type": "string", + "required": true, + "x-ms-skip-url-encoding": true + } + ], + "responses": { + "200": { + "description": "Successfully received the unencoded query parameter with value 'value1&q2=value2&q3=value3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/method/query/null": { + "get": { + "operationId": "skipUrlEncoding_getMethodQueryNull", + "description": "Get method with unencoded query parameter with value null", + "tags": [ + "SkipUrlEncoding Operations" + ], + "parameters": [ + { + "name": "q1", + "in": "query", + "description": "Unencoded query parameter with value null", + "type": "string", + "x-ms-skip-url-encoding": true + } + ], + "responses": { + "200": { + "description": "Successfully received no query parameter" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/path/query/valid": { + "parameters": [ + { + "name": "q1", + "in": "query", + "description": "Unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "type": "string", + "required": true, + "x-ms-skip-url-encoding": true + } + ], + "get": { + "operationId": "skipUrlEncoding_getPathQueryValid", + "description": "Get method with unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "responses": { + "200": { + "description": "Successfully received the unencoded query parameter with value 'value1&q2=value2&q3=value3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/skipUrlEncoding/swagger/query/valid": { + "get": { + "operationId": "skipUrlEncoding_getSwaggerQueryValid", + "description": "Get method with unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "tags": [ + "SkipUrlEncoding Operations" + ], + "parameters": [ + { + "name": "q1", + "in": "query", + "description": "An unencoded query parameter with value 'value1&q2=value2&q3=value3'", + "type": "string", + "enum": [ "value1&q2=value2&q3=value3" ], + "required": true, + "x-ms-skip-url-encoding": true + } + ], + "responses": { + "200": { + "description": "Successfully received the unencoded query parameter with value 'value1&q2=value2&q3=value3'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/odata/filter": { + "get": { + "operationId": "odata_getWithFilter", + "description": "Specify filter parameter with value '$filter=id gt 5 and name eq 'foo'&$orderby=id&$top=10'", + "tags": [ + "odata Operations" + ], + "parameters": [ + { + "name": "$filter", + "in": "query", + "required": false, + "type": "string", + "description": "The filter parameter with value '$filter=id gt 5 and name eq 'foo''." + }, + { + "name": "$top", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "description": "The top parameter with value 10." + }, + { + "name": "$orderby", + "in": "query", + "required": false, + "type": "string", + "description": "The orderby parameter with value id." + } + ], + "responses": { + "200": { + "description": "Successfully received filter parameter with value '$filter=id gt 5 and name eq 'foo'&$orderby=id&$top=10'" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + }, + "x-ms-odata": "#/definitions/OdataFilter" + } + }, + "/azurespecials/customNamedRequestId": { + "post": { + "operationId": "header_customNamedRequestId", + "description": "Send foo-client-request-id = 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0 in the header of the request", + "parameters": [ + { + "name": "foo-client-request-id", + "in": "header", + "required": true, + "type": "string", + "description": "The fooRequestId", + "x-ms-client-request-id": true + } + ], + "tags": [ + "Header Operations" + ], + "x-ms-request-id": "foo-request-id", + "responses": { + "200": { + "headers": { + "foo-request-id": { + "description": "Gets the foo-request-id.", + "type": "string" + } + }, + "description": "Gets the foo-request-id" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/customNamedRequestIdParamGrouping": { + "post": { + "operationId": "header_customNamedRequestIdParamGrouping", + "description": "Send foo-client-request-id = 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0 in the header of the request, via a parameter group", + "parameters": [ + { + "name": "foo-client-request-id", + "in": "header", + "required": true, + "type": "string", + "description": "The fooRequestId", + "x-ms-client-request-id": true, + "x-ms-parameter-grouping": { + } + } + ], + "tags": [ + "Header Operations" + ], + "x-ms-request-id": "foo-request-id", + "responses": { + "200": { + "headers": { + "foo-request-id": { + "description": "Gets the foo-request-id.", + "type": "string" + } + }, + "description": "Gets the foo-request-id" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/azurespecials/customNamedRequestIdHead": { + "head": { + "operationId": "header_customNamedRequestIdHead", + "description": "Send foo-client-request-id = 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0 in the header of the request", + "parameters": [ + { + "name": "foo-client-request-id", + "in": "header", + "required": true, + "type": "string", + "description": "The fooRequestId", + "x-ms-client-request-id": true + } + ], + "tags": [ + "Header Operations" + ], + "x-ms-request-id": "foo-request-id", + "responses": { + "200": { + "headers": { + "foo-request-id": { + "description": "Gets the foo-request-id.", + "type": "string" + } + }, + "description": "Gets the foo-request-id" + }, + "404": { + "description": "Gets the foo-request-id" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "parameters": { + "globalSubscriptionId": { + "name": "subscriptionId", + "in": "path", + "description": "The subscription id, which appears in the path, always modeled in credentials. The value is always '1234-5678-9012-3456'", + "type": "string", + "required": true + }, + "globalApiVersion": { + "name": "api-version", + "in": "query", + "description": "The api version, which appears in the query, the value is always '2015-07-01-preview'", + "type": "string", + "required": true + } + }, + "definitions": { + "Error": { + "type": "object", + "required": ["constantId"], + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "constantId": { + "type": "integer", + "enum": [ 1 ] + }, + "message": { + "type": "string" + } + } + }, + "OdataFilter": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } +} diff --git a/tests-upgrade/datamodels-datatypes-boolean-quirks/readme.md b/tests-upgrade/datamodels-datatypes-boolean-quirks/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean-quirks/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-boolean-quirks/swagger.json b/tests-upgrade/datamodels-datatypes-boolean-quirks/swagger.json new file mode 100644 index 00000000000..c5aa1f4a374 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean-quirks/swagger.json @@ -0,0 +1,200 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/bool/true": { + "get": { + "operationId": "bool_getTrue", + "description": "Get true Boolean value", + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The true Boolean value", + "schema": { + "type": "boolean" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "operationId": "bool_putTrue", + "description": "Set Boolean value true", + "parameters": [ + { + "name": "boolBody", + "in": "body", + "schema" : { + "type": "boolean" + }, + "required": true + } + ], + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "Empty Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/false": { + "get": { + "operationId": "bool_getFalse", + "description": "Get false Boolean value", + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The false Boolean value", + "schema": { + "type": "boolean" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "operationId": "bool_putFalse", + "description": "Set Boolean value false", + "parameters": [ + { + "name": "boolBody", + "in": "body", + "schema" : { + "type": "boolean" + }, + "required": true + } + ], + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "Empty Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/null": { + "get": { + "operationId": "bool_getNull", + "description": "Get null Boolean value", + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The null Boolean value", + "schema": { + "type": "boolean" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/invalid": { + "get": { + "operationId": "bool_getInvalid", + "description": "Get invalid Boolean value", + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The invalid Boolean value", + "schema": { + "type": "boolean" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } +}, +"definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } +} +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getFalse.json b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getFalse.json new file mode 100644 index 00000000000..0bc3b35e600 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getFalse.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": false + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getNull.json b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getNull.json new file mode 100644 index 00000000000..e24179d12d9 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getNull.json @@ -0,0 +1,6 @@ +{ + "parameters": {}, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getTrue.json b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getTrue.json new file mode 100644 index 00000000000..235cd259450 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_getTrue.json @@ -0,0 +1,9 @@ +{ + "parameters": { + }, + "responses": { + "200": { + "body": true + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putFalse.json b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putFalse.json new file mode 100644 index 00000000000..ab9238e5832 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putFalse.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "boolBody": false + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putTrue.json b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putTrue.json new file mode 100644 index 00000000000..d6adf6c69f7 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/examples/bool_putTrue.json @@ -0,0 +1,9 @@ +{ + "parameters": { + "boolBody": true + }, + "responses": { + "200": { + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-boolean/readme.md b/tests-upgrade/datamodels-datatypes-boolean/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-boolean/swagger.json b/tests-upgrade/datamodels-datatypes-boolean/swagger.json new file mode 100644 index 00000000000..d5e03f5e06c --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-boolean/swagger.json @@ -0,0 +1,230 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/bool/true": { + "get": { + "operationId": "bool_getTrue", + "description": "Get true Boolean value", + "x-ms-examples": { + "bool_getTrue": { + "$ref": "./examples/bool_getTrue.json" + } + }, + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The true Boolean value", + "schema": { + "type": "boolean", + "enum": [true] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "operationId": "bool_putTrue", + "description": "Set Boolean value true", + "x-ms-examples": { + "bool_putTrue": { + "$ref": "./examples/bool_putTrue.json" + } + }, + "parameters": [ + { + "name": "boolBody", + "in": "body", + "schema" : { + "type": "boolean", + "enum": [true] + }, + "required": true + } + ], + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "Empty Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/false": { + "get": { + "operationId": "bool_getFalse", + "description": "Get false Boolean value", + "x-ms-examples": { + "bool_getFalse": { + "$ref": "./examples/bool_getFalse.json" + } + }, + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The false Boolean value", + "schema": { + "type": "boolean", + "enum": [false] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "operationId": "bool_putFalse", + "description": "Set Boolean value false", + "x-ms-examples": { + "bool_putFalse": { + "$ref": "./examples/bool_putFalse.json" + } + }, + "parameters": [ + { + "name": "boolBody", + "in": "body", + "schema" : { + "type": "boolean", + "enum": [false] + }, + "required": true + } + ], + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "Empty Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/null": { + "get": { + "operationId": "bool_getNull", + "description": "Get null Boolean value", + "x-ms-examples": { + "bool_getNull": { + "$ref": "./examples/bool_getNull.json" + } + }, + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The null Boolean value", + "schema": { + "type": "boolean", + "x-nullable": true + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bool/invalid": { + "get": { + "operationId": "bool_getInvalid", + "description": "Get invalid Boolean value", + "tags": [ + "Bool Operations" + ], + "responses": { + "200": { + "description": "The invalid Boolean value", + "schema": { + "type": "boolean" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } +}, +"definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } +} +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/examples/byte_getEmpty.json b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getEmpty.json new file mode 100644 index 00000000000..2b04d0f8a9f --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getEmpty.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/examples/byte_getInvalid.json b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getInvalid.json new file mode 100644 index 00000000000..f47ede114d9 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getInvalid.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "::::SWAGGER::::" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNonAscii.json b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNonAscii.json new file mode 100644 index 00000000000..4fe17d43890 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNonAscii.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "//79/Pv6+fj39g==" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNull.json b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNull.json new file mode 100644 index 00000000000..e24179d12d9 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/examples/byte_getNull.json @@ -0,0 +1,6 @@ +{ + "parameters": {}, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/examples/byte_putNonAscii.json b/tests-upgrade/datamodels-datatypes-byte/examples/byte_putNonAscii.json new file mode 100644 index 00000000000..367268e0f3e --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/examples/byte_putNonAscii.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "byteBody": "//79/Pv6+fj39g==" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-byte/readme.md b/tests-upgrade/datamodels-datatypes-byte/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-byte/swagger.json b/tests-upgrade/datamodels-datatypes-byte/swagger.json new file mode 100644 index 00000000000..aa5d7a1e4ec --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-byte/swagger.json @@ -0,0 +1,188 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/byte/null": { + "get": { + "operationId": "byte_getNull", + "description": "Get null byte value", + "x-ms-examples": { + "byte_getNull": { + "$ref": "./examples/byte_getNull.json" + } + }, + "tags": [ + "Byte Operations" + ], + "responses": { + "200": { + "description": "The null byte value", + "schema": { + "description": "The null byte value", + "type": "string", + "format": "byte" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/byte/empty": { + "get": { + "operationId": "byte_getEmpty", + "description": "Get empty byte value ''", + "tags": [ + "Byte Operations" + ], + "responses": { + "200": { + "description": "The empty byte value ''", + "schema": { + "description": "The empty byte value ''", + "type": "string", + "format": "byte" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/byte/nonAscii": { + "get": { + "operationId": "byte_getNonAscii", + "description": "Get non-ascii byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "tags": [ + "Byte Operations" + ], + "responses": { + "200": { + "description": "Non-ascii base-64 encoded byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "schema": { + "description": "Non-ascii base-64 encoded byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "type": "string", + "format": "byte" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "operationId": "byte_putNonAscii", + "description": "Put non-ascii byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "parameters": [ + { + "name": "byteBody", + "in": "body", + "description": "Base64-encoded non-ascii byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "schema" : { + "description": "Base64-encoded non-ascii byte string hex(FF FE FD FC FB FA F9 F8 F7 F6)", + "type": "string", + "format": "byte" + }, + "required": true + } + ], + "tags": [ + "Byte Operations" + ], + "responses": { + "200": { + "description": "Empty Response" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/byte/invalid": { + "get": { + "operationId": "byte_getInvalid", + "description": "Get invalid byte value ':::SWAGGER::::'", + "tags": [ + "Byte Operations" + ], + "responses": { + "200": { + "description": "The invalid byte value '::::SWAGGER::::'", + "schema": { + "description": "The invalid byte value '::::SWAGGER::::'", + "type": "string", + "format": "byte" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } +}, +"definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } +} +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/examples/date_getMaxDate.json b/tests-upgrade/datamodels-datatypes-date/examples/date_getMaxDate.json new file mode 100644 index 00000000000..80c8e23555b --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/examples/date_getMaxDate.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "9999-12-31" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/examples/date_getMinDate.json b/tests-upgrade/datamodels-datatypes-date/examples/date_getMinDate.json new file mode 100644 index 00000000000..e6e618742a7 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/examples/date_getMinDate.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "0001-01-01" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/examples/date_getNull.json b/tests-upgrade/datamodels-datatypes-date/examples/date_getNull.json new file mode 100644 index 00000000000..2b04d0f8a9f --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/examples/date_getNull.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/examples/date_putMaxDate.json b/tests-upgrade/datamodels-datatypes-date/examples/date_putMaxDate.json new file mode 100644 index 00000000000..52b4c3b0c02 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/examples/date_putMaxDate.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "dateBody": "9999-12-31" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/examples/date_putMinDate.json b/tests-upgrade/datamodels-datatypes-date/examples/date_putMinDate.json new file mode 100644 index 00000000000..4818e46a278 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/examples/date_putMinDate.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "dateBody": "0001-01-01" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-date/readme.md b/tests-upgrade/datamodels-datatypes-date/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-date/swagger.json b/tests-upgrade/datamodels-datatypes-date/swagger.json new file mode 100644 index 00000000000..2ad4c3d55fa --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-date/swagger.json @@ -0,0 +1,259 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/date/null": { + "get": { + "operationId": "date_getNull", + "description": "Get null date value", + "x-ms-examples": { + "date_getNull": { + "$ref": "./examples/date_getNull.json" + } + }, + "responses": { + "200": { + "description": "The null date value", + "schema": { + "type": "string", + "format": "date", + "x-nullable": true + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/date/invaliddate": { + "get": { + "operationId": "date_getInvalidDate", + "description": "Get invalid date value", + "responses": { + "200": { + "description": "The invalid date value", + "schema": { + "type": "string", + "format": "date" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/date/overflowdate": { + "get": { + "operationId": "date_getOverflowDate", + "description": "Get overflow date value", + "responses": { + "200": { + "description": "The overflow date value", + "schema": { + "type": "string", + "format": "date" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/date/underflowdate": { + "get": { + "operationId": "date_getUnderflowDate", + "description": "Get underflow date value", + "responses": { + "200": { + "description": "The underflow date value", + "schema": { + "type": "string", + "format": "date" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/date/max": { + "put": { + "operationId": "date_putMaxDate", + "description": "Put max date value 9999-12-31", + "x-ms-examples": { + "date_putMaxDate": { + "$ref": "./examples/date_putMaxDate.json" + } + }, + "parameters": [ + { + "name": "dateBody", + "description": "date body", + "in": "body", + "schema": { + "type": "string", + "format": "date" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The max date value" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "date_getMaxDate", + "description": "Get max date value 9999-12-31", + "x-ms-examples": { + "date_getMaxDate": { + "$ref": "./examples/date_getMaxDate.json" + } + }, + "responses": { + "200": { + "description": "The max date value", + "schema": { + "type": "string", + "format": "date" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/date/min": { + "put": { + "operationId": "date_putMinDate", + "description": "Put min date value 0000-01-01", + "x-ms-examples": { + "date_putMinDate": { + "$ref": "./examples/date_putMinDate.json" + } + }, + "parameters": [ + { + "name": "dateBody", + "description": "date body", + "in": "body", + "schema": { + "type": "string", + "format": "date" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The min date value" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "date_getMinDate", + "description": "Get min date value 0000-01-01", + "x-ms-examples": { + "date_getMinDate": { + "$ref": "./examples/date_getMinDate.json" + } + }, + "responses": { + "200": { + "description": "The min date value 0000-01-01", + "schema": { + "type": "string", + "format": "date", + "enum": ["0000-01-01"] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNegativeOffsetMinDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNegativeOffsetMinDateTime.json new file mode 100644 index 00000000000..52d3a74d665 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNegativeOffsetMinDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "0001-01-01T00:00:00-14:00" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNoOffsetMinDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNoOffsetMinDateTime.json new file mode 100644 index 00000000000..93f7fa64dba --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalNoOffsetMinDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "0001-01-01T00:00:00" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetLowercaseMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetLowercaseMaxDateTime.json new file mode 100644 index 00000000000..45d97ca792c --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetLowercaseMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "9999-12-31t23:59:59.999+14:00" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetUppercaseMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetUppercaseMaxDateTime.json new file mode 100644 index 00000000000..7017f3eb651 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getLocalPositiveOffsetUppercaseMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "9999-12-31T23:59:59.999+14:00" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getNull.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getNull.json new file mode 100644 index 00000000000..2b04d0f8a9f --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getNull.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcLowercaseMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcLowercaseMaxDateTime.json new file mode 100644 index 00000000000..65c7dbe7f73 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcLowercaseMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "9999-12-31t23:59:59.999z" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcMinDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcMinDateTime.json new file mode 100644 index 00000000000..88cbd30a2a8 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcMinDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "0001-01-01T00:00:00Z" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcUppercaseMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcUppercaseMaxDateTime.json new file mode 100644 index 00000000000..a66b21645bd --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_getUtcUppercaseMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": {}, + "responses": { + "200": { + "body": "9999-12-31T23:59:59.999Z" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalNegativeOffsetMinDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalNegativeOffsetMinDateTime.json new file mode 100644 index 00000000000..0c1722ad7e6 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalNegativeOffsetMinDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "datetimeBody": "0001-01-01T00:00:00-14:00" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalPositiveOffsetMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalPositiveOffsetMaxDateTime.json new file mode 100644 index 00000000000..30d6a937fb2 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putLocalPositiveOffsetMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "datetimeBody": "9999-12-31T23:59:59.999+14:00" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMaxDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMaxDateTime.json new file mode 100644 index 00000000000..2791778a24a --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMaxDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "datetimeBody": "9999-12-31T23:59:59.999Z" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMinDateTime.json b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMinDateTime.json new file mode 100644 index 00000000000..64cf4e57c2b --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/examples/datetime_putUtcMinDateTime.json @@ -0,0 +1,8 @@ +{ + "parameters": { + "datetimeBody": "0001-01-01T00:00:00Z" + }, + "responses": { + "200": {} + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-datetime/readme.md b/tests-upgrade/datamodels-datatypes-datetime/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-datetime/swagger.json b/tests-upgrade/datamodels-datatypes-datetime/swagger.json new file mode 100644 index 00000000000..eee87438506 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-datetime/swagger.json @@ -0,0 +1,636 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/datetime/null": { + "get": { + "operationId": "datetime_getNull", + "description": "Get null datetime value", + "x-ms-examples": { + "datetime_getNull": { + "$ref": "./examples/datetime_getNull.json" + } + }, + "responses": { + "200": { + "description": "The null datetime value", + "schema": { + "type": "string", + "format": "date-time", + "x-nullable": true + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/invalid": { + "get": { + "operationId": "datetime_getInvalid", + "description": "Get invalid datetime value", + "responses": { + "200": { + "description": "The invalid datetime value", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/overflow": { + "get": { + "operationId": "datetime_getOverflow", + "description": "Get overflow datetime value", + "responses": { + "200": { + "description": "The overflow datetime value", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/underflow": { + "get": { + "operationId": "datetime_getUnderflow", + "description": "Get underflow datetime value", + "responses": { + "200": { + "description": "The underflow datetime value", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/utc": { + "put": { + "operationId": "datetime_putUtcMaxDateTime", + "description": "Put max datetime value 9999-12-31T23:59:59.999Z", + "x-ms-examples": { + "datetime_putUtcMaxDateTime": { + "$ref": "./examples/datetime_putUtcMaxDateTime.json" + } + }, + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.999Z" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/utc7ms": { + "put": { + "operationId": "datetime_putUtcMaxDateTime7Digits", + "description": "This is against the recommendation that asks for 3 digits, but allow to test what happens in that scenario", + "summary": "Put max datetime value 9999-12-31T23:59:59.9999999Z", + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.9999999Z" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/utc/lowercase": { + "get": { + "operationId": "datetime_getUtcLowercaseMaxDateTime", + "description": "Get max datetime value 9999-12-31t23:59:59.999z", + "x-ms-examples": { + "datetime_getUtcLowercaseMaxDateTime": { + "$ref": "./examples/datetime_getUtcLowercaseMaxDateTime.json" + } + }, + "responses": { + "200": { + "description": "The max datetime value 9999-12-31t23:59:59.999z", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/utc/uppercase": { + "get": { + "operationId": "datetime_getUtcUppercaseMaxDateTime", + "description": "Get max datetime value 9999-12-31T23:59:59.999Z", + "x-ms-examples": { + "datetime_getUtcUppercaseMaxDateTime": { + "$ref": "./examples/datetime_getUtcUppercaseMaxDateTime.json" + } + }, + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.999Z", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/utc7ms/uppercase": { + "get": { + "operationId": "datetime_getUtcUppercaseMaxDateTime7Digits", + "description": "This is against the recommendation that asks for 3 digits, but allow to test what happens in that scenario", + "summary": "Get max datetime value 9999-12-31T23:59:59.9999999Z", + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.9999999Z", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localpositiveoffset": { + "put": { + "operationId": "datetime_putLocalPositiveOffsetMaxDateTime", + "description": "Put max datetime value with positive numoffset 9999-12-31t23:59:59.999+14:00", + "x-ms-examples": { + "datetime_putLocalPositiveOffsetMaxDateTime": { + "$ref": "./examples/datetime_putLocalPositiveOffsetMaxDateTime.json" + } + }, + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The max datetime value with positive num offset 9999-12-31T23:59:59.999+14:00" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localpositiveoffset/lowercase": { + "get": { + "operationId": "datetime_getLocalPositiveOffsetLowercaseMaxDateTime", + "description": "Get max datetime value with positive num offset 9999-12-31t23:59:59.999+14:00", + "x-ms-examples": { + "datetime_getLocalPositiveOffsetLowercaseMaxDateTime": { + "$ref": "./examples/datetime_getLocalPositiveOffsetLowercaseMaxDateTime.json" + } + }, + "responses": { + "200": { + "description": "The max datetime value 9999-12-31t23:59:59.999+14:00", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localpositiveoffset/uppercase": { + "get": { + "operationId": "datetime_getLocalPositiveOffsetUppercaseMaxDateTime", + "description": "Get max datetime value with positive num offset 9999-12-31T23:59:59.999+14:00", + "x-ms-examples": { + "datetime_getLocalPositiveOffsetUppercaseMaxDateTime": { + "$ref": "./examples/datetime_getLocalPositiveOffsetUppercaseMaxDateTime.json" + } + }, + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.999+14:00", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localnegativeoffset": { + "put": { + "operationId": "datetime_putLocalNegativeOffsetMaxDateTime", + "description": "Put max datetime value with positive numoffset 9999-12-31t23:59:59.999-14:00", + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The max datetime value with positive num offset 9999-12-31T23:59:59.999+14:00" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localnegativeoffset/uppercase": { + "get": { + "operationId": "datetime_getLocalNegativeOffsetUppercaseMaxDateTime", + "description": "Get max datetime value with positive num offset 9999-12-31T23:59:59.999-14:00", + "responses": { + "200": { + "description": "The max datetime value 9999-12-31T23:59:59.999-14:00", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/max/localnegativeoffset/lowercase": { + "get": { + "operationId": "datetime_getLocalNegativeOffsetLowercaseMaxDateTime", + "description": "Get max datetime value with positive num offset 9999-12-31t23:59:59.999-14:00", + "responses": { + "200": { + "description": "The max datetime value 9999-12-31t23:59:59.999-14:00", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/min/utc": { + "put": { + "operationId": "datetime_putUtcMinDateTime", + "description": "Put min datetime value 0001-01-01T00:00:00Z", + "x-ms-examples": { + "datetime_putUtcMinDateTime": { + "$ref": "./examples/datetime_putUtcMinDateTime.json" + } + }, + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00Z" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "datetime_getUtcMinDateTime", + "description": "Get min datetime value 0001-01-01T00:00:00Z", + "x-ms-examples": { + "datetime_getUtcMinDateTime": { + "$ref": "./examples/datetime_getUtcMinDateTime.json" + } + }, + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00Z", + "schema": { + "type": "string", + "format": "date-time", + "enum": [ + "0001-01-01T00:00:00Z" + ] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/min/localpositiveoffset": { + "put": { + "operationId": "datetime_putLocalPositiveOffsetMinDateTime", + "description": "Put min datetime value 0001-01-01T00:00:00+14:00", + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00+14:00" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "datetime_getLocalPositiveOffsetMinDateTime", + "description": "Get min datetime value 0001-01-01T00:00:00+14:00", + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00+14:00", + "schema": { + "type": "string", + "format": "date-time", + "enum": [ + "0001-01-01t00:00:00+14:00" + ] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/min/localnegativeoffset": { + "put": { + "operationId": "datetime_putLocalNegativeOffsetMinDateTime", + "description": "Put min datetime value 0001-01-01T00:00:00-14:00", + "x-ms-examples": { + "datetime_putLocalNegativeOffsetMinDateTime": { + "$ref": "./examples/datetime_putLocalNegativeOffsetMinDateTime.json" + } + }, + "parameters": [ + { + "name": "datetimeBody", + "description": "datetime body", + "in": "body", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00+14:00" + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "operationId": "datetime_getLocalNegativeOffsetMinDateTime", + "description": "Get min datetime value 0001-01-01T00:00:00-14:00", + "x-ms-examples": { + "datetime_getLocalNegativeOffsetMinDateTime": { + "$ref": "./examples/datetime_getLocalNegativeOffsetMinDateTime.json" + } + }, + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00-14:00", + "schema": { + "type": "string", + "format": "date-time", + "enum": [ + "0001-01-01t00:00:00-14:00" + ] + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/datetime/min/localnooffset": { + "get": { + "operationId": "datetime_getLocalNoOffsetMinDateTime", + "description": "Get min datetime value 0001-01-01T00:00:00", + "x-ms-examples": { + "datetime_getLocalNoOffsetMinDateTime": { + "$ref": "./examples/datetime_getLocalNoOffsetMinDateTime.json" + } + }, + "responses": { + "200": { + "description": "The min datetime value 0001-01-01T00:00:00", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/tests-upgrade/datamodels-datatypes-file/readme.md b/tests-upgrade/datamodels-datatypes-file/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-file/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-file/swagger.json b/tests-upgrade/datamodels-datatypes-file/swagger.json new file mode 100644 index 00000000000..88f1a2f3320 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-file/swagger.json @@ -0,0 +1,64 @@ +{ + + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + } + } + } + } + }, + "definitions": { + "FilesModel": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + } + } + } +} \ No newline at end of file From 7808ff98331f764687e54d05786ca798b827538a Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 14 Aug 2020 16:00:12 +0800 Subject: [PATCH 38/61] Add two m4 configuration and fix some issues (#664) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential * Add two m4 configuration and fix some issues --- powershell/autorest-configuration.md | 2 ++ powershell/llcsharp/model/namespace.ts | 7 +++++++ powershell/plugins/cs-namer-v2.ts | 3 --- tests-upgrade/readme.azure.noprofile.md | 3 +++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 4ed72061ef5..3426260430a 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -8,6 +8,8 @@ AutoRest needs the below config to pick this up as a plug-in - see https://githu ``` yaml modelerfour: emit-yaml-tags: false + lenient-model-deduplication: true + additional-checks: false ``` > if the modeler is loaded already, use that one, otherwise grab it. diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 8f1dbe0d54b..57680266b50 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -179,6 +179,13 @@ export class NewModelsNamespace extends Namespace { this.NewResolveTypeDeclaration(schema, true, state); } } + + if (schemas.any) { + for (const schema of schemas.any) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } + if (schemas.strings) { for (const schema of schemas.strings) { this.NewResolveTypeDeclaration(schema, true, state); diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 6a6c66c3911..d5c9ac4e346 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -26,9 +26,6 @@ function setPropertyNames(schema: Schema) { return; } for (const propertySchema of values(schema.properties)) { - if (propertySchema.schema.type === SchemaType.Any) { - continue; - } const propertyDetails = propertySchema.language.default; propertyDetails.required = propertySchema.required ?? false; propertyDetails.readOnly = propertySchema.readOnly ?? false; diff --git a/tests-upgrade/readme.azure.noprofile.md b/tests-upgrade/readme.azure.noprofile.md index 82284693a17..31602028ac6 100644 --- a/tests-upgrade/readme.azure.noprofile.md +++ b/tests-upgrade/readme.azure.noprofile.md @@ -44,4 +44,7 @@ directive: set: default: script: '(Get-AzContext).Subscription.Id' + - from: swagger-document + where: $ + transform: return $.replace(/"modelAsString":\ true/g, '"modelAsString":\ false') ``` \ No newline at end of file From f9c6089367e06684a17e1335005e1e75ad345fe9 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 18 Aug 2020 09:36:39 +0800 Subject: [PATCH 39/61] Add support for enum with one value (#666) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential * Add two m4 configuration and fix some issues * Add support for enum with one value --- powershell/llcsharp/schema/schema-resolver.ts | 2 +- powershell/plugins/plugin-create-inline-properties.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 7efda43ca1b..3c724ad42fb 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -231,7 +231,7 @@ export class NewSchemaDefinitionResolver { case SchemaType.Constant: switch ((schema).valueType.type) { case SchemaType.String: - return new NewEnumImplementation(schema, required); + return new NewString(schema, required); case SchemaType.DateTime: if ((schema).valueType.format === StringFormat.DateTimeRfc1123) { return new NewDateTime1123(schema, required); diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 0e85e2f05d5..05c7646bcec 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; +import { codeModelSchema, CodeModel, ObjectSchema, ConstantSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; //import { VirtualParameter } from '@azure-tools/codemodel-v3'; import { getPascalIdentifier, removeSequentialDuplicates, pascalCase, fixLeadingNumber, deconstruct, selectName, EnglishPluralizationService, serialize } from '@azure-tools/codegen'; import { length, values, } from '@azure-tools/linq'; @@ -270,6 +270,11 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr alias: [], required: property.required || property.language.default.required }); + // dolauli, set constant value and make it readonly, if it is constant + if (property.schema.type === SchemaType.Constant) { + property.language.default.readOnly = true; + property.language.default.constantValue = (property.schema).value.value; + } } // resolve name collisions. From 27c06e73cb3fc9cbf3a28974b52a15290dfa6151 Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 18 Aug 2020 10:20:21 +0800 Subject: [PATCH 40/61] fix some issues (#665) Co-authored-by: xichen Co-authored-by: Xiaogang --- powershell/internal/project.ts | 4 +- powershell/llcsharp/schema/date-time.ts | 4 +- powershell/llcsharp/schema/date.ts | 4 +- powershell/llcsharp/schema/schema-resolver.ts | 23 +++----- powershell/models/model-extensions.ts | 51 ----------------- powershell/plugins/create-commands-v2.ts | 4 +- powershell/plugins/cs-namer-v2.ts | 4 +- powershell/plugins/plugin-tweak-m4-model.ts | 55 +++++++++++-------- powershell/plugins/plugin-tweak-model.ts | 34 ++++++++---- tests-upgrade/Configuration.json | 3 +- 10 files changed, 76 insertions(+), 110 deletions(-) diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 4878ced8f6f..7724490d74a 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -17,7 +17,7 @@ import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; -import { BooleanSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; +import { BooleanSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -72,7 +72,7 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { try { if (!this.inResolve) { this.inResolve = true; - if (schema && schema.type === SchemaType.Boolean) { + if (schema && (schema.type === SchemaType.Boolean || (schema.type === SchemaType.Constant && (schema).valueType.type === SchemaType.Boolean))) { return new NewPSSwitch(schema, required); } } diff --git a/powershell/llcsharp/schema/date-time.ts b/powershell/llcsharp/schema/date-time.ts index 165b1095f66..f09cf4940b1 100644 --- a/powershell/llcsharp/schema/date-time.ts +++ b/powershell/llcsharp/schema/date-time.ts @@ -11,7 +11,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema, DateSchema } from '@azure-tools/codemodel'; import { Primitive, NewPrimitive } from './primitive'; export class DateTime extends Primitive { @@ -183,7 +183,7 @@ export class NewDateTime extends NewPrimitive { } return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); } - constructor(schema: DateTimeSchema, public isRequired: boolean) { + constructor(schema: DateTimeSchema | DateSchema, public isRequired: boolean) { super(schema); } // public static string DateFormat = "yyyy-MM-dd"; diff --git a/powershell/llcsharp/schema/date.ts b/powershell/llcsharp/schema/date.ts index 0b231bd8b8e..62de87bcdfb 100644 --- a/powershell/llcsharp/schema/date.ts +++ b/powershell/llcsharp/schema/date.ts @@ -5,7 +5,7 @@ import { StringExpression } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { Schema as NewSchema, DateTimeSchema } from '@azure-tools/codemodel'; +import { DateSchema } from '@azure-tools/codemodel'; import { DateTime, NewDateTime } from './date-time'; export class Date extends DateTime { @@ -17,7 +17,7 @@ export class Date extends DateTime { export class NewDate extends NewDateTime { public DateTimeFormat = new StringExpression('yyyy-MM-dd'); - constructor(schema: DateTimeSchema, isRequired: boolean) { + constructor(schema: DateSchema, isRequired: boolean) { super(schema, isRequired); } } \ No newline at end of file diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 3c724ad42fb..b62f79a9980 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -189,6 +189,8 @@ export class NewSchemaDefinitionResolver { return new NewString(schema, required); } + case SchemaType.Binary: + return new NewBinary(schema, required); case SchemaType.Duration: return new NewDuration(schema, required); case SchemaType.Uuid: @@ -198,6 +200,8 @@ export class NewSchemaDefinitionResolver { return new NewDateTime1123(schema, required); } return new NewDateTime(schema, required); + case SchemaType.Date: + return new NewDate(schema, required); case SchemaType.ByteArray: return new NewByteArray(schema, required); case SchemaType.Boolean: @@ -210,6 +214,7 @@ export class NewSchemaDefinitionResolver { // skip-for-time-being // case IntegerFormat.UnixTime: // return new UnixTime(schema, required); + case 16: case 32: return new NewNumeric(schema, required, required ? 'int' : 'int?'); } @@ -229,18 +234,8 @@ export class NewSchemaDefinitionResolver { return new NewNumeric(schema, required, required ? 'float' : 'float?'); case SchemaType.Constant: - switch ((schema).valueType.type) { - case SchemaType.String: - return new NewString(schema, required); - case SchemaType.DateTime: - if ((schema).valueType.format === StringFormat.DateTimeRfc1123) { - return new NewDateTime1123(schema, required); - } - return new NewDateTime(schema, required); - default: - state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); - throw new Error('Unknown Model. Fatal.'); - } + return this.resolveTypeDeclaration((schema).valueType, required, state); + case SchemaType.Choice: { const choiceSchema = schema as ChoiceSchema; if ((choiceSchema.choiceType).type === SchemaType.DateTime && (choiceSchema.choiceType).format === StringFormat.DateTimeRfc1123) { @@ -263,4 +258,4 @@ export class NewSchemaDefinitionResolver { state.error(`Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); throw new Error('Unknown Model. Fatal.'); } -} \ No newline at end of file +} diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 2c3051d2e65..2f0e682375a 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -284,57 +284,6 @@ export class NewModelExtensionsNamespace extends Namespace { continue; } - if (schema.type === SchemaType.Dictionary) { - // xichen: - // Case1: dictionary schema is only used in parents: - // "definitions": { - // "PetAPInPropertiesWithAPString": { - // "type": "object", - // "properties": { - // "id": { - // "type": "integer" - // } - // }, - // "additionalProperties": { - // "type": "string" - // } - // } - // } - // - // Case2: we will have a dictionary property: - // "definitions": { - // "PetAPInProperties": { - // "type": "object", - // "properties": { - // "id": { - // "type": "integer" - // }, - // "additionalProperties": { - // "type": "object", - // "additionalProperties": { - // "type": "number" - // } - // } - // } - // } - // } - // - // We only create model class for case 2, because in m3 case 2 will has independent scheam for additionalProperties, - // But for case 1, PetAPInPropertiesWithAPString will only have additionalProperties. - // - // This is to make generated code same as m3. Actually there wont be side effect if we skip this check. - const objSchemas = schemas['objects']; - const usedByProp = schemas['objects']?.some((objSchema) => { - if ((objSchema).properties?.some((prop) => prop.schema === schema)) { - return true; - } - return false; - }); - if (!usedByProp) { - continue; - } - } - const td = this.resolver.resolveTypeDeclaration(schema, true, state); if (td instanceof NewObjectImplementation) { diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index ca67a3e2199..25f558d4d7c 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -287,8 +287,8 @@ export /* @internal */ class Inferrer { })); // let's add a variant where it's expanded out. - // *IF* the body is an object - if (body.schema.type === SchemaType.Object) { + // *IF* the body is an object or dictionary + if (body.schema.type === SchemaType.Object || body.schema.type === SchemaType.Dictionary) { const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); opExpanded.details.default.dropBodyParameter = true; opExpanded.parameters.push(new IParameter(`${bodyParameterName}Body`, body.schema, { diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index d5c9ac4e346..3443cd53c70 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -179,14 +179,14 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso operation.language.csharp = { ...details, // inherit - name: getPascalIdentifier(operationName), + name: operationName, }; // parameters are camelCased. for (const parameter of values(operation.parameters)) { const parameterDetails = parameter.language.default; - let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name))); + let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.serializedName))); if (propName === 'default') { propName = '@default'; diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index 3bf59ab1ca4..d3e54b796ad 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel'; +import { ArraySchema, CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; @@ -19,7 +19,7 @@ async function tweakModel(state: State): Promise { addDictionaryApiVersion(model); - removeDictionaryDefaultDescription(model); + removeM4DefaultDescription(model); return model; } @@ -80,7 +80,17 @@ function addResponseHeaderSchema(model: CodeModel) { } function addDictionaryApiVersion(model: CodeModel) { - // If object has dictionary property, this property's schema does not have api version information in m4. We should add this back. + + model.schemas.dictionaries?.forEach((schema) => { + if (schema.apiVersions) { + return; + } + if (schema.elementType && schema.elementType.apiVersions) { + schema.apiVersions = JSON.parse(JSON.stringify(schema.elementType.apiVersions)); + } + }) + + // If we cannot find api version from element type, try to get it from object schema who refers the dict or any. model.schemas.objects?.forEach((schema) => { if (!schema.apiVersions) { @@ -88,54 +98,55 @@ function addDictionaryApiVersion(model: CodeModel) { } for (const prop of getAllProperties(schema)) { - if ((prop.schema.type !== SchemaType.Dictionary && prop.schema.type !== SchemaType.Any) || prop.schema.apiVersions) { + if (prop.schema.type !== SchemaType.Dictionary || prop.schema.apiVersions) { continue; } - const dictSchema = prop.schema as DictionarySchema; - if (dictSchema.elementType && dictSchema.elementType.apiVersions) { - dictSchema.apiVersions = JSON.parse(JSON.stringify(dictSchema.elementType.apiVersions)); - } else { - dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); - } + prop.schema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions)); } }) } -function removeDictionaryDefaultDescription(model: CodeModel) { - // For dictionary schema and property, if there is no description assigned, m4 will set a default description like: Dictionary of +function removeM4DefaultDescription(model: CodeModel) { + // For dictionary and arrya schema and property, if there is no description assigned, m4 will set a default description like: Dictionary of or Array of // To keep same action as m3, we will set it to empty string const visited = new Set(); - [...model.schemas.objects ?? [], ...model.schemas.dictionaries ?? []].forEach((schema) => { - recursiveRemoveDefaultDescription(schema, visited); + [...model.schemas.objects ?? [], ...model.schemas.dictionaries ?? [], ...model.schemas.arrays ?? []].forEach((schema) => { + recursiveRemoveM4DefaultDescription(schema, visited); }) } -function recursiveRemoveDefaultDescription(schema: Schema, visited: Set) { - if (visited.has(schema) || (schema.type !== SchemaType.Object && schema.type !== SchemaType.Dictionary)) { +function recursiveRemoveM4DefaultDescription(schema: Schema, visited: Set) { + if (visited.has(schema) || (schema.type !== SchemaType.Object && schema.type !== SchemaType.Dictionary && schema.type !== SchemaType.Array)) { return; } // Default description pattern in m4 - const defaultDescPattern = /Dictionary of <.*>$/; + const defaultDictDescPattern = /Dictionary of <.?>$/; + const defaultArrayDescPattern = /Array of .?$/; visited.add(schema); if (schema.type === SchemaType.Dictionary) { const dictSchema = schema as DictionarySchema; - recursiveRemoveDefaultDescription(dictSchema.elementType, visited); - if (defaultDescPattern.test(dictSchema.language.default.description)) { + recursiveRemoveM4DefaultDescription(dictSchema.elementType, visited); + if (defaultDictDescPattern.test(dictSchema.language.default.description)) { dictSchema.language.default.description = ''; } + } else if (schema.type === SchemaType.Array) { + const arrSchema = schema as ArraySchema; + recursiveRemoveM4DefaultDescription(arrSchema.elementType, visited); + if (defaultArrayDescPattern.test(schema.language.default.description)) { + schema.language.default.description = ''; + } } else if (schema.type === SchemaType.Object) { const objSchema = schema as ObjectSchema; for (const prop of getAllProperties(objSchema)) { - recursiveRemoveDefaultDescription(prop.schema, visited); - if (prop.schema.type === SchemaType.Dictionary && defaultDescPattern.test(prop.language.default.description)) { + recursiveRemoveM4DefaultDescription(prop.schema, visited); + if (prop.schema.type === SchemaType.Dictionary && (defaultDictDescPattern.test(prop.language.default.description) || defaultArrayDescPattern.test(prop.language.default.description))) { prop.language.default.description = ''; } } } } - export async function tweakM4ModelPlugin(service: Host) { const state = await new NewModelState(service).init(); service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 4b09be14815..5171af771d2 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema } from '@azure-tools/codemodel'; +import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; @@ -99,7 +99,7 @@ async function tweakModelV2(state: State): Promise { for (const operation of values(group.operations)) { for (const param of values(operation.parameters).where(each => each.protocol?.http?.in === ParameterLocation.Path)) { const name = param.language.default.name; - const hasName = universalId.properties?.find((prop) => prop.language.default.name === name); + const hasName = universalId.properties?.find((prop) => prop.language.default.name.toLocaleLowerCase() === name.toLocaleLowerCase()); if (!hasName) { if (!universalId.properties) { universalId.properties = []; @@ -277,10 +277,15 @@ async function tweakModelV2(state: State): Promise { for (const group of values(model.operationGroups)) { for (const operation of values(group.operations)) { for (const parameter of values(operation.parameters)) { - if (parameter.required && parameter.schema instanceof ChoiceSchema) { - const choiceSchema = parameter.schema as ChoiceSchema; - if (choiceSchema.choices.length === 1) { - parameter.language.default.constantValue = choiceSchema.choices[0].value; + if (parameter.required) { + if (parameter.schema.type === SchemaType.Choice) { + const choiceSchema = parameter.schema as ChoiceSchema; + if (choiceSchema.choices.length === 1) { + parameter.language.default.constantValue = choiceSchema.choices[0].value; + } + } else if (parameter.schema.type === SchemaType.Constant) { + const constantSchema = parameter.schema as ConstantSchema; + parameter.language.default.constantValue = constantSchema.value.value; } } } @@ -290,12 +295,17 @@ async function tweakModelV2(state: State): Promise { // identify properties that are constants for (const schema of values(schemas.objects)) { for (const property of values(schema.properties)) { - if (property.required && property.schema instanceof ChoiceSchema) { - const choiceSchema = property.schema as ChoiceSchema; - if (choiceSchema.choices.length === 1) { - // properties with an enum single value are constants - // add the constant value - property.language.default.constantValue = choiceSchema.choices[0].value; + if (property.required) { + if (property.schema.type === SchemaType.Choice) { + const choiceSchema = property.schema as ChoiceSchema; + if (choiceSchema.choices.length === 1) { + // properties with an enum single value are constants + // add the constant value + property.language.default.constantValue = choiceSchema.choices[0].value; + } + } else if (property.schema.type === SchemaType.Constant) { + const constantSchema = property.schema as ConstantSchema; + property.language.default.constantValue = constantSchema.value.value; } } } diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 5c27182b76c..380e8a9c98c 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -37,7 +37,8 @@ "extension-ms-paramlocation", "directive-aliasremoval", "directive-cmdlet", - "directive-parameter" + "directive-parameter", + "datamodels-datatypes-file" ], "BlackList": [ "basic-get-querystr", From ce1b3af9f005c70a20a378b01fce8f8dff9c1cb4 Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 18 Aug 2020 17:14:29 +0800 Subject: [PATCH 41/61] fix header issue (#667) Co-authored-by: xichen --- powershell/plugins/plugin-tweak-m4-model.ts | 7 ++++++- powershell/plugins/plugin-tweak-model.ts | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index d3e54b796ad..b9a75942066 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -25,7 +25,8 @@ async function tweakModel(state: State): Promise { } function addResponseHeaderSchema(model: CodeModel) { - // In remodler, each operations response headers will has its own scheam. Each header will be schema's property. But in m4, there won't be a schema for headers. + // In remodeler, each operations response headers will has its own scheam. Each header will be schema's property. + // But in m4, if 'schema' is not explicitly defined, even 'headers' is specified, there won't be a schema for headers. // To keep backward compatiable, we will create headers schema here model.operationGroups.forEach((group) => { @@ -34,6 +35,10 @@ function addResponseHeaderSchema(model: CodeModel) { return; } op.responses.forEach((resp) => { + if ((resp).schema) { + return; + } + const headers = resp.protocol.http?.headers as Array; if (headers === undefined) { return; diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 5171af771d2..ea298ffe5ea 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -188,7 +188,7 @@ async function tweakModelV2(state: State): Promise { if ((response as any).schema.type === SchemaType.Object) { const respSchema = (response as any).schema as ObjectSchema; const curHeader = header as any; - const headerKey = curHeader as string; + const headerKey = curHeader.header as string; respSchema.language.default.hasHeaders = true; @@ -197,7 +197,7 @@ async function tweakModelV2(state: State): Promise { state.message({ Channel: Channel.Debug, Text: `Adding header property '${headerKey}' to model ${respSchema.language.default.name}` }); // create a property for the header value - const newProperty = new Property(headerKey, curHeader.description, curHeader.schema); + const newProperty = new Property(headerKey, curHeader.description || '', curHeader.schema); newProperty.language.default.required = false; // mark it that it's a header-only property From c02f5df2e0ad13e1dd19591b947982b2bcf79834 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 19 Aug 2020 13:48:47 +0800 Subject: [PATCH 42/61] Fixed an enum related issue and add some RPs in the test (#669) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential * Add two m4 configuration and fix some issues * Add support for enum with one value * Fixed an enum related issue and add some RPs in the test --- powershell/cmdlets/class.ts | 4 +- powershell/llcsharp/schema/schema-resolver.ts | 4 + powershell/llcsharp/schema/string.ts | 2 +- .../plugin-create-inline-properties.ts | 5 - powershell/plugins/plugin-tweak-model.ts | 32 +- .../datamodels-datatypes-object/swagger.json | 224 +- .../functions/helpers/AppInsights/readme.md | 114 + .../helpers/AppInsights/readme.noprofile.md | 119 + .../helpers/KeyVault/readme.noprofile.md | 21 + .../ManagedIdentity/readme.noprofile.md | 25 + .../functions/helpers/Storage/readme.md | 194 ++ .../helpers/Storage/readme.noprofile.md | 196 ++ tests-upgrade/functions/readme.md | 506 ++++ .../kubconf/kubernetesconfiguration.json | 664 +++++ tests-upgrade/kubconf/readme.md | 86 + tests-upgrade/mysql/.gitattributes | 1 + tests-upgrade/mysql/.gitignore | 14 + .../resource-management/v1/privatelinks.json | 174 ++ .../resource-management/v1/types.json | 467 +++ .../resource-management/v2/types.json | 473 +++ .../mysql/common-types/rfcs/rfc7517.json | 104 + tests-upgrade/mysql/custom/readme.md | 41 + tests-upgrade/mysql/docs/readme.md | 11 + tests-upgrade/mysql/examples/readme.md | 11 + tests-upgrade/mysql/how-to.md | 58 + tests-upgrade/mysql/license.txt | 227 ++ tests-upgrade/mysql/mysql.json | 2576 +++++++++++++++++ tests-upgrade/mysql/readme.md | 139 + tests-upgrade/mysql/resources/readme.md | 11 + tests-upgrade/mysql/test/loadEnv.ps1 | 28 + tests-upgrade/mysql/test/readme.md | 17 + .../mysql/tools/Resources/.gitattributes | 1 + .../mysql/tools/Resources/.gitignore | 14 + .../Resources/custom/New-AzDeployment.ps1 | 231 ++ .../mysql/tools/Resources/docs/readme.md | 11 + .../mysql/tools/Resources/examples/readme.md | 11 + tests-upgrade/mysql/tools/Resources/how-to.md | 58 + .../mysql/tools/Resources/license.txt | 203 ++ tests-upgrade/mysql/tools/Resources/readme.md | 440 +++ .../CmdletSurface-latest-2019-04-30.md | 598 ++++ .../tools/Resources/resources/ModelSurface.md | 1645 +++++++++++ .../mysql/tools/Resources/resources/readme.md | 11 + .../mysql/tools/Resources/test/readme.md | 17 + tests-upgrade/tsi/readme.md | 130 + tests-upgrade/tsi/timeseriesinsights.json | 2061 +++++++++++++ 45 files changed, 11855 insertions(+), 124 deletions(-) create mode 100644 tests-upgrade/functions/helpers/AppInsights/readme.md create mode 100644 tests-upgrade/functions/helpers/AppInsights/readme.noprofile.md create mode 100644 tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md create mode 100644 tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md create mode 100644 tests-upgrade/functions/helpers/Storage/readme.md create mode 100644 tests-upgrade/functions/helpers/Storage/readme.noprofile.md create mode 100644 tests-upgrade/functions/readme.md create mode 100644 tests-upgrade/kubconf/kubernetesconfiguration.json create mode 100644 tests-upgrade/kubconf/readme.md create mode 100644 tests-upgrade/mysql/.gitattributes create mode 100644 tests-upgrade/mysql/.gitignore create mode 100644 tests-upgrade/mysql/common-types/resource-management/v1/privatelinks.json create mode 100644 tests-upgrade/mysql/common-types/resource-management/v1/types.json create mode 100644 tests-upgrade/mysql/common-types/resource-management/v2/types.json create mode 100644 tests-upgrade/mysql/common-types/rfcs/rfc7517.json create mode 100644 tests-upgrade/mysql/custom/readme.md create mode 100644 tests-upgrade/mysql/docs/readme.md create mode 100644 tests-upgrade/mysql/examples/readme.md create mode 100644 tests-upgrade/mysql/how-to.md create mode 100644 tests-upgrade/mysql/license.txt create mode 100644 tests-upgrade/mysql/mysql.json create mode 100644 tests-upgrade/mysql/readme.md create mode 100644 tests-upgrade/mysql/resources/readme.md create mode 100644 tests-upgrade/mysql/test/loadEnv.ps1 create mode 100644 tests-upgrade/mysql/test/readme.md create mode 100644 tests-upgrade/mysql/tools/Resources/.gitattributes create mode 100644 tests-upgrade/mysql/tools/Resources/.gitignore create mode 100644 tests-upgrade/mysql/tools/Resources/custom/New-AzDeployment.ps1 create mode 100644 tests-upgrade/mysql/tools/Resources/docs/readme.md create mode 100644 tests-upgrade/mysql/tools/Resources/examples/readme.md create mode 100644 tests-upgrade/mysql/tools/Resources/how-to.md create mode 100644 tests-upgrade/mysql/tools/Resources/license.txt create mode 100644 tests-upgrade/mysql/tools/Resources/readme.md create mode 100644 tests-upgrade/mysql/tools/Resources/resources/CmdletSurface-latest-2019-04-30.md create mode 100644 tests-upgrade/mysql/tools/Resources/resources/ModelSurface.md create mode 100644 tests-upgrade/mysql/tools/Resources/resources/readme.md create mode 100644 tests-upgrade/mysql/tools/Resources/test/readme.md create mode 100644 tests-upgrade/tsi/readme.md create mode 100644 tests-upgrade/tsi/timeseriesinsights.json diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 02a10b162d9..6e4b01d967e 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -2468,7 +2468,7 @@ export class NewCmdletClass extends Class { addDefaultInfo(cmdletParameter, vParam); } - const isEnum = propertyType.schema.language.csharp?.enum !== undefined; + const isEnum = propertyType instanceof NewEnumImplementation;; const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); @@ -2613,7 +2613,7 @@ export class NewCmdletClass extends Class { // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); } - const isEnum = propertyType.schema.language.csharp?.enum !== undefined; + const isEnum = propertyType instanceof NewEnumImplementation; const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; if (isEnum || hasEnum) { regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index b62f79a9980..40e25040299 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -25,6 +25,7 @@ import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended- import { PwshModel } from '../../utils/PwshModel'; import { NewModelState } from '../../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; +import { schemaHasEnum } from '../validations'; export class SchemaDefinitionResolver { private readonly cache = new Map(); @@ -244,6 +245,9 @@ export class NewSchemaDefinitionResolver { return new NewString(schema, required); } case SchemaType.SealedChoice: + if (schema.language.default.skip === true) { + return new NewString(schema, required); + } return new NewEnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index b49b4ac7b43..a39aa57f1d9 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -398,7 +398,7 @@ ${this.validateEnum(eventListener, property)} return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${pattern}");`; } private validateEnum(eventListener: Variable, property: Variable): string { - if (this.schema.type !== SchemaType.SealedChoice) { + if (this.schema.type !== SchemaType.SealedChoice && this.schema.type != SchemaType.Choice) { return ''; } const choiceValues = (this.schema).choices.map((c) => c.value); diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 05c7646bcec..f05e414f25a 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -270,11 +270,6 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr alias: [], required: property.required || property.language.default.required }); - // dolauli, set constant value and make it readonly, if it is constant - if (property.schema.type === SchemaType.Constant) { - property.language.default.readOnly = true; - property.language.default.constantValue = (property.schema).value.value; - } } // resolve name collisions. diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index ea298ffe5ea..83a0401fc44 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema } from '@azure-tools/codemodel'; +import { Property, SealedChoiceSchema, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; @@ -286,6 +286,21 @@ async function tweakModelV2(state: State): Promise { } else if (parameter.schema.type === SchemaType.Constant) { const constantSchema = parameter.schema as ConstantSchema; parameter.language.default.constantValue = constantSchema.value.value; + } else if (parameter.schema.type === SchemaType.SealedChoice) { + const sealedChoiceSchema = parameter.schema as SealedChoiceSchema; + if (sealedChoiceSchema.choices.length === 1) { + parameter.language.default.constantValue = sealedChoiceSchema.choices[0].value; + if (sealedChoiceSchema.language.default.skip !== false) { + sealedChoiceSchema.language.default.skip = true; + } + } + } + } else { + if (parameter.schema.type === SchemaType.SealedChoice) { + const sealedChoiceSchema = parameter.schema as SealedChoiceSchema; + if (sealedChoiceSchema.choices.length === 1) { + sealedChoiceSchema.language.default.skip = false; + } } } } @@ -306,6 +321,21 @@ async function tweakModelV2(state: State): Promise { } else if (property.schema.type === SchemaType.Constant) { const constantSchema = property.schema as ConstantSchema; property.language.default.constantValue = constantSchema.value.value; + } else if (property.schema.type === SchemaType.SealedChoice) { + const sealedChoiceSchema = property.schema as SealedChoiceSchema; + if (sealedChoiceSchema.choices.length === 1) { + property.language.default.constantValue = sealedChoiceSchema.choices[0].value; + if (sealedChoiceSchema.language.default.skip !== false) { + sealedChoiceSchema.language.default.skip = true; + } + } + } + } else { + if (property.schema.type === SchemaType.SealedChoice) { + const sealedChoiceSchema = property.schema as SealedChoiceSchema; + if (sealedChoiceSchema.choices.length === 1) { + sealedChoiceSchema.language.default.skip = false; + } } } } diff --git a/tests-upgrade/datamodels-datatypes-object/swagger.json b/tests-upgrade/datamodels-datatypes-object/swagger.json index b82571a6750..1f3304195bd 100644 --- a/tests-upgrade/datamodels-datatypes-object/swagger.json +++ b/tests-upgrade/datamodels-datatypes-object/swagger.json @@ -1,131 +1,125 @@ { - - "swagger": "2.0", - "info": { - "title": "DatabricksClient", - "version": "2018-04-01", - "description": "ARM Databricks" - }, - "host": "management.azure.com", - "schemes": [ - "https" - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "security": [ - { - "azure_auth": [ - "user_impersonation" - ] + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" } - ], - "securityDefinitions": { - "azure_auth": { - "type": "oauth2", - "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", - "flow": "implicit", - "description": "Azure Active Directory OAuth2 Flow", - "scopes": { - "user_impersonation": "impersonate your user account" + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + } } } - }, - "paths": { - "/subscriptions/resourceGroup": { - "get": { - "tags": [ - "Workspaces" - ], - "operationId": "Workspaces_Get", - "description": "Gets the workspace.", - "responses": { - "200": { - "description": "OK-Return workspace." - } - } + } + }, + "definitions": { + "Model": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer" } } }, - "definitions": { - "Model": { - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "code": { - "type": "integer" - } - } + "Model2": { + "type": "object", + "properties": { + "id": { + "type": "integer" }, - "Model2": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "username": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "username" - ] + "username": { + "type": "string" }, - "Model3": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "readOnly": true - }, - "password": { - "type": "string" - } - }, - "required": [ - "id", - "username" - ] - }, - "ContactInfo": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email" - }, - "phone": { - "type": "string" - } + "name": { + "type": "string" } }, - "User": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "contact_info": { - "$ref": "#/definitions/ContactInfo" - } + "required": [ + "id", + "username" + ] + }, + "Model3": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "password": { + "type": "string" } }, - "Model4": { - "type": "object", - "minProperties": 2, - "maxProperties": 10 + "required": [ + "id", + "username" + ] + }, + "ContactInfo": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "phone": { + "type": "string" + } + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "contact_info": { + "$ref": "#/definitions/ContactInfo" + } } } + } } \ No newline at end of file diff --git a/tests-upgrade/functions/helpers/AppInsights/readme.md b/tests-upgrade/functions/helpers/AppInsights/readme.md new file mode 100644 index 00000000000..211e1297df0 --- /dev/null +++ b/tests-upgrade/functions/helpers/AppInsights/readme.md @@ -0,0 +1,114 @@ + +# Az.AppInsights +This directory contains the PowerShell module for the AppInsights service. + +--- +## Status +[![Az.AppInsights](https://img.shields.io/powershellgallery/v/Az.AppInsights.svg?style=flat-square&label=Az.AppInsights "Az.AppInsights")](https://www.powershellgallery.com/packages/Az.AppInsights/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.6.0 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.AppInsights`, see [how-to.md](how-to.md). + + +# Internal +This directory contains a module to handle *internal only* cmdlets. Cmdlets that you **hide** in configuration are created here. For more information on hiding, see [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression). The cmdlets in this directory are generated at **build-time**. Do not put any custom code, files, cmdlets, etc. into this directory. Please use `..\custom` for all custom implementation. + +## Info +- Modifiable: no +- Generated: all +- Committed: no +- Packaged: yes + +## Details +The `Az.Storage.internal.psm1` file is generated to this folder. This module file handles the hidden cmdlets. These cmdlets will not be exported by `Az.Storage`. Instead, this sub-module is imported by the `..\custom\Az.Storage.custom.psm1` module, allowing you to use hidden cmdlets in your custom, exposed cmdlets. To call these cmdlets in your custom scripts, simply use [module-qualified calls](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-6#qualified-names). For example, `Az.Storage.internal\Get-Example` would call an internal cmdlet named `Get-Example`. + +## Purpose +This allows you to include REST specifications for services that you *do not wish to expose from your module*, but simply want to call within custom cmdlets. For example, if you want to make a custom cmdlet that uses `Storage` services, you could include a simplified `Storage` REST specification that has only the operations you need. When you run the generator and build this module, note the generated `Storage` cmdlets. Then, in your readme configuration, use [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression) on the `Storage` cmdlets and they will *only be exposed to the custom cmdlets* you want to write, and not be exported as part of `Az.Storage`. + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +#output-folder: . +#subject-prefix: '' +#title: AppInsights +#module-version: 4.0.0 +apprepo: https://github.com/Azure/azure-rest-api-specs/blob/resource-hybrid-profile +require: + - $(this-folder)/../../readme.azure.md +``` + +## Multi-API/Profile support for AutoRest v3 generators + +AutoRest V3 generators require the use of `--tag=all-api-versions` to select api files. + +This block is updated by an automatic script. Edits may be lost! + +``` yaml $(tag) == 'all-api-versions' /* autogenerated */ +# include the azure profile definitions from the standard location +require: $(apprepo)/profiles/readme.md +appinsights: $(apprepo)/specification/applicationinsights/resource-manager + +# all the input files across all versions +input-file: + - $(appinsights)/Microsoft.Insights/stable/2015-05-01/componentApiKeys_API.json + - $(appinsights)/Microsoft.Insights/stable/2015-05-01/components_API.json +``` + +# Directives +``` yaml +directive: + - where: + verb: Clear|Remove|Set + subject: ^Component$ + remove: true + - where: + verb: Get + subject: ^ComponentPurgeStatus$ + remove: true + - where: + verb: New|Remove + subject: ^ApiKey$ + remove: true + - where: + verb: Update + subject: ^ComponentTag$ + remove: true + - where: + subject: ^Component$ + set: + subject: AppInsights + - where: + subject: ^ApiKey$ + set: + subject: AppInsightsApiKey + - where: + verb: Get|New + subject: ^AppInsights$ + hide: true + - where: + verb: Get + subject: ^AppInsightsApiKey$ + hide: true +``` diff --git a/tests-upgrade/functions/helpers/AppInsights/readme.noprofile.md b/tests-upgrade/functions/helpers/AppInsights/readme.noprofile.md new file mode 100644 index 00000000000..635fa81cba0 --- /dev/null +++ b/tests-upgrade/functions/helpers/AppInsights/readme.noprofile.md @@ -0,0 +1,119 @@ + +# Az.AppInsights +This directory contains the PowerShell module for the AppInsights service. + +--- +## Status +[![Az.AppInsights](https://img.shields.io/powershellgallery/v/Az.AppInsights.svg?style=flat-square&label=Az.AppInsights "Az.AppInsights")](https://www.powershellgallery.com/packages/Az.AppInsights/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.6.0 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.AppInsights`, see [how-to.md](how-to.md). + + +# Internal +This directory contains a module to handle *internal only* cmdlets. Cmdlets that you **hide** in configuration are created here. For more information on hiding, see [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression). The cmdlets in this directory are generated at **build-time**. Do not put any custom code, files, cmdlets, etc. into this directory. Please use `..\custom` for all custom implementation. + +## Info +- Modifiable: no +- Generated: all +- Committed: no +- Packaged: yes + +## Details +The `Az.Storage.internal.psm1` file is generated to this folder. This module file handles the hidden cmdlets. These cmdlets will not be exported by `Az.Storage`. Instead, this sub-module is imported by the `..\custom\Az.Storage.custom.psm1` module, allowing you to use hidden cmdlets in your custom, exposed cmdlets. To call these cmdlets in your custom scripts, simply use [module-qualified calls](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-6#qualified-names). For example, `Az.Storage.internal\Get-Example` would call an internal cmdlet named `Get-Example`. + +## Purpose +This allows you to include REST specifications for services that you *do not wish to expose from your module*, but simply want to call within custom cmdlets. For example, if you want to make a custom cmdlet that uses `Storage` services, you could include a simplified `Storage` REST specification that has only the operations you need. When you run the generator and build this module, note the generated `Storage` cmdlets. Then, in your readme configuration, use [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression) on the `Storage` cmdlets and they will *only be exposed to the custom cmdlets* you want to write, and not be exported as part of `Az.Storage`. + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +#output-folder: . +#subject-prefix: '' +#title: AppInsights +#module-version: 4.0.0 +require: + - $(this-folder)/../../../readme.azure.noprofile.md +``` + +## Multi-API/Profile support for AutoRest v3 generators + +AutoRest V3 generators require the use of `--tag=all-api-versions` to select api files. + +This block is updated by an automatic script. Edits may be lost! + +``` yaml +apprepo: https://github.com/Azure/azure-rest-api-specs/blob/resource-hybrid-profile +# include the azure profile definitions from the standard location +appinsights: $(apprepo)/specification/applicationinsights/resource-manager + +# all the input files across all versions +input-file: + - $(appinsights)/Microsoft.Insights/stable/2015-05-01/componentApiKeys_API.json + - $(appinsights)/Microsoft.Insights/stable/2015-05-01/components_API.json + +subject-prefix: '' +``` + +# Directives +``` yaml +directive: + - where: + verb: Clear|Remove|Set + subject: ^Component$ + remove: true + - where: + verb: Get + subject: ^ComponentPurgeStatus$ + remove: true + - where: + verb: New|Remove + subject: ^ApiKey$ + remove: true + - where: + verb: Update + subject: ^ComponentTag$ + remove: true + - where: + subject: ^Component$ + set: + subject: AppInsights + - where: + subject: ^ApiKey$ + set: + subject: AppInsightsApiKey + - where: + verb: Get|New + subject: ^AppInsights$ + hide: true + - where: + verb: Get + subject: ^AppInsightsApiKey$ + hide: true + - where: + subject: ^AppInsights.* + set: + subject-prefix: '' +``` diff --git a/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md b/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md new file mode 100644 index 00000000000..9563f3d19db --- /dev/null +++ b/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md @@ -0,0 +1,21 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../../../readme.azure.noprofile.md +input-file: + - $(repo)/specification/keyvault/resource-manager/Microsoft.KeyVault/stable/2016-10-01/keyvault.json + +# subject-prefix: '' + +directive: + # Remove unnedded cmdlets + - remove-operation: Operations_List + # hide all cmdlets + - where: + subject: ^VaultDeleted$|^Vault$|^VaultNameAvailability$|^VaultAccessPolicy$ + hide: true + set: + subject-prefix: '' +``` diff --git a/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md b/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md new file mode 100644 index 00000000000..182ddc3f059 --- /dev/null +++ b/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md @@ -0,0 +1,25 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../../../readme.azure.noprofile.md +input-file: + - $(repo)/specification/msi/resource-manager/Microsoft.ManagedIdentity/stable/2018-11-30/ManagedIdentity.json + +subject-prefix: '' + +directive: + # Remove unnedded cmdlets + - remove-operation: Operations_List + + # Hide Storage Account cmdlets + - where: + subject: ^UserAssignedIdentity.* + hide: true + - where: + subject: ^UserAssignedIdentity.* + set: + subject-prefix: '' + +``` diff --git a/tests-upgrade/functions/helpers/Storage/readme.md b/tests-upgrade/functions/helpers/Storage/readme.md new file mode 100644 index 00000000000..400c26b59a9 --- /dev/null +++ b/tests-upgrade/functions/helpers/Storage/readme.md @@ -0,0 +1,194 @@ + +# Az.Storage +This directory contains the PowerShell module for the Storage service. + +--- +## Status +[![Az.Storage](https://img.shields.io/powershellgallery/v/Az.Storage.svg?style=flat-square&label=Az.Storage "Az.Storage")](https://www.powershellgallery.com/packages/Az.Storage/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.6.0 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.Storage`, see [how-to.md](how-to.md). + + +# Internal +This directory contains a module to handle *internal only* cmdlets. Cmdlets that you **hide** in configuration are created here. For more information on hiding, see [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression). The cmdlets in this directory are generated at **build-time**. Do not put any custom code, files, cmdlets, etc. into this directory. Please use `..\custom` for all custom implementation. + +## Info +- Modifiable: no +- Generated: all +- Committed: no +- Packaged: yes + +## Details +The `Az.Storage.internal.psm1` file is generated to this folder. This module file handles the hidden cmdlets. These cmdlets will not be exported by `Az.Storage`. Instead, this sub-module is imported by the `..\custom\Az.Storage.custom.psm1` module, allowing you to use hidden cmdlets in your custom, exposed cmdlets. To call these cmdlets in your custom scripts, simply use [module-qualified calls](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-6#qualified-names). For example, `Az.Storage.internal\Get-Example` would call an internal cmdlet named `Get-Example`. + +## Purpose +This allows you to include REST specifications for services that you *do not wish to expose from your module*, but simply want to call within custom cmdlets. For example, if you want to make a custom cmdlet that uses `Storage` services, you could include a simplified `Storage` REST specification that has only the operations you need. When you run the generator and build this module, note the generated `Storage` cmdlets. Then, in your readme configuration, use [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression) on the `Storage` cmdlets and they will *only be exposed to the custom cmdlets* you want to write, and not be exported as part of `Az.Storage`. + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../../readme.azure.md + - $(repo)/specification/storage/resource-manager/readme.md + +subject-prefix: '' +# title: Storage +# module-version: 4.0.0 +# skip-model-cmdlets: true + +directive: + # Remove unnedded cmdlets + - where: + subject: ^BlobContainerLegalHold$ + remove: true + - where: + subject: ^BlobContainer$ + remove: true + - where: + subject: ^BlobContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^BlobService$ + remove: true + - where: + subject: ^BlobServiceProperty$ + remove: true + - where: + subject: ^FileService$ + remove: true + - where: + subject: ^FileServiceProperty$ + remove: true + - where: + subject: ^FileShare$ + remove: true + - where: + subject: ^ManagementPolicy$ + remove: true + - where: + subject: ^Operation$ + remove: true + - where: + subject: ^Sku$ + remove: true + - where: + subject: ^StorageAccountProperty$ + remove: true + - where: + subject: ^Usage$ + remove: true + - where: + subject: ^ExtendBlobContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^LeaseBlobContainer$ + remove: true + - where: + subject: ^StorageAccountFailover$ + remove: true + - where: + subject: ^ContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^StorageAccountUserDelegationKey$ + remove: true + - where: + subject: ^StorageAccountNameAvailability$ + remove: true + - where: + verb: Set|New|Remove|Update + subject: ^StorageAccount$ + remove: true + - where: + verb: Get + subject: ^StorageAccountServiceSas$ + remove: true + - where: + verb: Get + subject: ^StorageAccountSas$ + remove: true + - where: + verb: New + subject: ^StorageAccountKey$ + remove: true + + + # Hide Storage Account cmdlets + - where: + subject: ^StorageAccount.* + hide: true + - where: + subject: ^StorageAccount.* + set: + subject-prefix: '' + + # StorageAccount + - where: + subject: StorageAccount.* + parameter-name: AccountName + set: + parameter-name: Name + - where: + subject: StorageAccount + parameter-name: CustomDomainUseSubDomainName + set: + parameter-name: UseSubDomain + - where: + subject: StorageAccount + parameter-name: NetworkAcls(.*) + set: + parameter-name: NetworkRuleSet$1 + - where: + subject: StorageAccount + parameter-name: BlobEnabled + set: + parameter-name: EncryptBlobService + - where: + subject: StorageAccount + parameter-name: FileEnabled + set: + parameter-name: EncryptFileService + - where: + subject: StorageAccount + parameter-name: QueueEnabled + set: + parameter-name: EncryptQueueService + - where: + subject: StorageAccount + parameter-name: TableEnabled + set: + parameter-name: EncryptTableService + - where: + subject: ^StorageAccount$ + parameter-name: Keyvaultproperty(.*) + set: + parameter-name: $1 + - where: + subject: ^StorageAccount$ + parameter-name: IsHnsEnabled + set: + parameter-name: EnableHierarchicalNamespace +``` diff --git a/tests-upgrade/functions/helpers/Storage/readme.noprofile.md b/tests-upgrade/functions/helpers/Storage/readme.noprofile.md new file mode 100644 index 00000000000..8aabb9ae9db --- /dev/null +++ b/tests-upgrade/functions/helpers/Storage/readme.noprofile.md @@ -0,0 +1,196 @@ + +# Az.Storage +This directory contains the PowerShell module for the Storage service. + +--- +## Status +[![Az.Storage](https://img.shields.io/powershellgallery/v/Az.Storage.svg?style=flat-square&label=Az.Storage "Az.Storage")](https://www.powershellgallery.com/packages/Az.Storage/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.6.0 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.Storage`, see [how-to.md](how-to.md). + + +# Internal +This directory contains a module to handle *internal only* cmdlets. Cmdlets that you **hide** in configuration are created here. For more information on hiding, see [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression). The cmdlets in this directory are generated at **build-time**. Do not put any custom code, files, cmdlets, etc. into this directory. Please use `..\custom` for all custom implementation. + +## Info +- Modifiable: no +- Generated: all +- Committed: no +- Packaged: yes + +## Details +The `Az.Storage.internal.psm1` file is generated to this folder. This module file handles the hidden cmdlets. These cmdlets will not be exported by `Az.Storage`. Instead, this sub-module is imported by the `..\custom\Az.Storage.custom.psm1` module, allowing you to use hidden cmdlets in your custom, exposed cmdlets. To call these cmdlets in your custom scripts, simply use [module-qualified calls](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-6#qualified-names). For example, `Az.Storage.internal\Get-Example` would call an internal cmdlet named `Get-Example`. + +## Purpose +This allows you to include REST specifications for services that you *do not wish to expose from your module*, but simply want to call within custom cmdlets. For example, if you want to make a custom cmdlet that uses `Storage` services, you could include a simplified `Storage` REST specification that has only the operations you need. When you run the generator and build this module, note the generated `Storage` cmdlets. Then, in your readme configuration, use [cmdlet hiding](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md#cmdlet-hiding-exportation-suppression) on the `Storage` cmdlets and they will *only be exposed to the custom cmdlets* you want to write, and not be exported as part of `Az.Storage`. + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../../../readme.azure.noprofile.md +input-file: + #- $(repo)/specification/storage/resource-manager/Microsoft.Storage/stable/2019-04-01/storage.json + - $(repo)/specification/storage/resource-manager/Microsoft.Storage/stable/2019-04-01/blob.json + +subject-prefix: '' +# title: Storage +# module-version: 4.0.0 +# skip-model-cmdlets: true + +directive: + # Remove unnedded cmdlets + - where: + subject: ^BlobContainerLegalHold$ + remove: true + - where: + subject: ^BlobContainer$ + remove: true + - where: + subject: ^BlobContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^BlobService$ + remove: true + - where: + subject: ^BlobServiceProperty$ + remove: true + - where: + subject: ^FileService$ + remove: true + - where: + subject: ^FileServiceProperty$ + remove: true + - where: + subject: ^FileShare$ + remove: true + - where: + subject: ^ManagementPolicy$ + remove: true + - where: + subject: ^Operation$ + remove: true + - where: + subject: ^Sku$ + remove: true + - where: + subject: ^StorageAccountProperty$ + remove: true + - where: + subject: ^Usage$ + remove: true + - where: + subject: ^ExtendBlobContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^LeaseBlobContainer$ + remove: true + - where: + subject: ^StorageAccountFailover$ + remove: true + - where: + subject: ^ContainerImmutabilityPolicy$ + remove: true + - where: + subject: ^StorageAccountUserDelegationKey$ + remove: true + - where: + subject: ^StorageAccountNameAvailability$ + remove: true + - where: + verb: Set|New|Remove|Update + subject: ^StorageAccount$ + remove: true + - where: + verb: Get + subject: ^StorageAccountServiceSas$ + remove: true + - where: + verb: Get + subject: ^StorageAccountSas$ + remove: true + - where: + verb: New + subject: ^StorageAccountKey$ + remove: true + + + # Hide Storage Account cmdlets + - where: + subject: ^StorageAccount.* + hide: true + - where: + subject: ^StorageAccount.* + set: + subject-prefix: '' + + # StorageAccount + - where: + subject: StorageAccount.* + parameter-name: AccountName + set: + parameter-name: Name + - where: + subject: StorageAccount + parameter-name: CustomDomainUseSubDomainName + set: + parameter-name: UseSubDomain + - where: + subject: StorageAccount + parameter-name: NetworkAcls(.*) + set: + parameter-name: NetworkRuleSet$1 + - where: + subject: StorageAccount + parameter-name: BlobEnabled + set: + parameter-name: EncryptBlobService + - where: + subject: StorageAccount + parameter-name: FileEnabled + set: + parameter-name: EncryptFileService + - where: + subject: StorageAccount + parameter-name: QueueEnabled + set: + parameter-name: EncryptQueueService + - where: + subject: StorageAccount + parameter-name: TableEnabled + set: + parameter-name: EncryptTableService + - where: + subject: ^StorageAccount$ + parameter-name: Keyvaultproperty(.*) + set: + parameter-name: $1 + - where: + subject: ^StorageAccount$ + parameter-name: IsHnsEnabled + set: + parameter-name: EnableHierarchicalNamespace +``` diff --git a/tests-upgrade/functions/readme.md b/tests-upgrade/functions/readme.md new file mode 100644 index 00000000000..7b297123629 --- /dev/null +++ b/tests-upgrade/functions/readme.md @@ -0,0 +1,506 @@ + +# Az.Functions +This directory contains the PowerShell module for the Functions service. + +--- +## Status +[![Az.Functions](https://img.shields.io/powershellgallery/v/Az.Functions.svg?style=flat-square&label=Az.Functions "Az.Functions")](https://www.powershellgallery.com/packages/Az.Functions/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.Functions`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g autorest@beta`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +### Suppression + +``` yaml +directive: + - suppress: XmsResourceInPutResponse + from: WebApps.json + where: $.paths["/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/{functionName}/keys/{keyName}"].put + reason: Model type is not an Azure resource + - suppress: RequiredPropertiesMissingInResourceModel + from: WebApps.json + where: $.definitions.KeyInfo + reason: Model type is not an Azure resource + - suppress: BodyTopLevelProperties + from: WebApps.json + where: $.definitions.KeyInfo.properties + reason: Model type is not an Azure resource +``` + +``` yaml +branch: powershell-function +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(repo)/specification/web/resource-manager/Microsoft.CertificateRegistration/stable/2019-08-01/AppServiceCertificateOrders.json + - $(repo)/specification/web/resource-manager/Microsoft.CertificateRegistration/stable/2019-08-01/CertificateRegistrationProvider.json + - $(repo)/specification/web/resource-manager/Microsoft.DomainRegistration/stable/2019-08-01/Domains.json + - $(repo)/specification/web/resource-manager/Microsoft.DomainRegistration/stable/2019-08-01/TopLevelDomains.json + - $(repo)/specification/web/resource-manager/Microsoft.DomainRegistration/stable/2019-08-01/DomainRegistrationProvider.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/Certificates.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/CommonDefinitions.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/DeletedWebApps.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/Diagnostics.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/Provider.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/Recommendations.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/ResourceProvider.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/WebApps.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/StaticSites.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/AppServiceEnvironments.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/AppServicePlans.json + - $(repo)/specification/web/resource-manager/Microsoft.Web/stable/2019-08-01/ResourceHealthMetadata.json +module-version: 1.0.1 +title: Functions +subject-prefix: '' + +metadata: + authors: Microsoft Corporation + owners: Microsoft Corporation + description: 'Microsoft Azure PowerShell - Azure Functions service cmdlets for Azure Resource Manager in Windows PowerShell and PowerShell Core.\n\nFor information on Azure Functions, please visit the following: https://docs.microsoft.com/azure/azure-functions/' + copyright: Microsoft Corporation. All rights reserved. + tags: Azure ResourceManager ARM PSModule Functions + companyName: Microsoft Corporation + requireLicenseAcceptance: true + licenseUri: https://aka.ms/azps-license + projectUri: https://github.com/Azure/azure-powershell + +directive: + - from: WebApps.json + where: $.paths["/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/privateEndpointConnections/{privateEndpointConnectionName}"].delete.responses.200 + transform: delete $.schema + - from: WebApps.json + where: $.paths["/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/privateEndpointConnections/{privateEndpointConnectionName}"].delete.responses.202 + transform: delete $.schema + - from: WebApps.json + where: $.paths["/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/privateEndpointConnections/{privateEndpointConnectionName}"].delete.responses.204 + transform: delete $.schema + - from: Diagnostics.json + where: $.paths["/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName}/diagnostics/{diagnosticCategory}/analyses/{analysisName}/execute"].post + transform: delete $."x-ms-examples" + - from: swagger-document + where: $..produces + #transform: $ = $.filter( each => each === 'application/json'); + transform: $ = ["application/json"]; + reason: this spec adds produces application/xml and text/json erronously. + - where: + subject: Operation + hide: true + - where: $.definitions.Identifier.properties + suppress: R3019 +# Cmdlet renames + - where: + verb: Backup|Get|New|Remove|Restart|Restore|Publish|Set|Start|Stop|Update + subject: WebApp + variant: (.*) + set: + subject: FunctionApp + hide: true + - where: + subject: WebAppFunction + set: + subject: Function + hide: true + - where: + subject: GeoRegion + set: + subject: FunctionAppAvailableLocation + hide: true + - where: + subject: AppServicePlan + set: + subject: FunctionAppPlan + hide: true + # Formats.ps1xml + - where: + model-name: Site + set: + suppress-format: true + - where: + model-name: GeoRegion + set: + format-table: + properties: + - Name + - where: + model-name: AppServicePlan + set: + suppress-format: true + # Parameter renames + - where: + subject: Function + parameter-name: Name + set: + parameter-name: FunctionAppName + hide: true + - where: + verb: New + subject: Connection + parameter-name: Name + clear-alias: true + - where: + verb: Set + subject: Connection + parameter-name: Name + clear-alias: true +# Cmdlets to hide + - where: + subject: (.*)WebAppApplicationSetting(.*) + hide: true + - where: + subject: (.*)AzWebAppSlot(.*) + hide: true + - where: + subject: (.*)NameAvailability(.*) + hide: true + - where: + subject: (.*)WebAppConfiguration(.*) + hide: true +# Cmdlets to remove + - where: + subject: WebAppPremierAddOn(.*) + remove: true + - where: + subject: WebAppVnetConnection(.*) + remove: true + - where: + subject: WebAppSwiftVirtualNetworkConnection(.*) + remove: true + - where: + subject: WebAppRelayServiceConnection(.*) + remove: true + - where: + subject: WebAppPremierAddOnSlot(.*) + remove: true + - where: + subject: WebAppHybridConnection(.*) + remove: true + - where: + subject: WebAppDomainOwnershipIdentifier(.*) + remove: true + - where: + subject: SiteVnetConnection(.*) + remove: true + - where: + subject: SiteRelayServiceConnection(.*) + remove: true + - where: + subject: (.*)Domain(.*) + remove: true + - where: + subject: (.*)Certificate(.*) + remove: true + - where: + subject: AppServicePlanVnetRoute(.*) + remove: true + - where: + subject: AppServiceEnvironmentWorkerPool(.*) + remove: true + - where: + subject: AppServiceEnvironmentMultiRolePool(.*) + remove: true + - where: + subject: WebAppCustomHostname(.*) + remove: true + - where: + subject: HostingEnvironmentVnet(.*) + remove: true + - where: + subject: GlobalDomainRegistrationDomainPurchase(.*) + remove: true + - where: + subject: WebAppWebSiteNetworkTrace(.*) + remove: true + - where: + subject: WebAppWebSiteNetworkTraceSlot(.*) + remove: true + - where: + subject: WebAppNetworkTrace(.*) + remove: true + - where: + subject: WebAppPublicCertificate(.*) + remove: true + - where: + subject: WebAppDiagnosticLog(.*) + remove: true + - where: + subject: WebAppPerfMonCounter(.*) + remove: true + - where: + subject: WebAppMigrateMySqlStatus(.*) + remove: true + - where: + subject: WebAppMetric(.*) + remove: true + - where: + subject: SiteNetworkFeature(.*) + remove: true + - where: + subject: ResourceHealthMetadata(.*) + remove: true + - where: + subject: (.*)MultiRolePoolInstanceMetric(.*) + remove: true + - where: + subject: (.*)MultiRoleMetricDefinition(.*) + remove: true + - where: + subject: (.*)PremierAddOn(.*) + remove: true + - where: + subject: (.*)WebAppSlot(.*) + remove: true + - where: + subject: (.*)ConnectionConsent(.*) + remove: true + - where: + subject: (.*)WebAppBackup(.*) + remove: true + - where: + subject: (.*)AppServiceEnvironment(.*) + remove: true + - where: + subject: (.*)AppServicePlanHybridConnection(.*) + remove: true + - where: + subject: (.*)AppServicePlanMetric(.*) + remove: true + - where: + subject: (.*)BillingMeter(.*) + remove: true + - where: + subject: (.*)DeletedWebApp(.*) + remove: true + - where: + subject: (.*)DiagnosticSite(.*) + remove: true + - where: + subject: (.*)Global(.*) + remove: true + - where: + subject: (.*)Recommendation(.*) + remove: true + - where: + subject: (.*)ManagedApi(.*) + remove: true + - where: + subject: (.*)ManagedHosting(.*) + remove: true + - where: + subject: (.*)Provider(.*) + remove: true + - where: + subject: (.*)ServerFarm(.*) + remove: true + - where: + subject: (.*)SiteInstance(.*) + remove: true + - where: + subject: (.*)SiteOperation(.*) + remove: true + - where: + subject: (.*)SourceControl(.*) + remove: true + - where: + subject: (.*)SubscriptionDeployment(.*) + remove: true + - where: + subject: (.*)WebAppAzureStorage(.*) + remove: true + - where: + subject: (.*)WebAppConnection(.*) + remove: true + - where: + subject: (.*)WebAppContainer(.*) + remove: true + - where: + subject: (.*)WebAppContinuou(.*) + remove: true + - where: + subject: (.*)WebAppDeployment(.*) + remove: true + - where: + subject: (.*)WebAppInstance(.*) + remove: true + - where: + subject: (.*)WebAppMetadata(.*) + remove: true + - where: + subject: (.*)WebAppMS(.*) + remove: true + - where: + subject: (.*)WebAppNetwork(.*) + remove: true + - where: + subject: (.*)WebAppPrivate(.*) + remove: true + - where: + subject: (.*)WebAppPublishing(.*) + remove: true + - where: + subject: (.*)WebAppSite(.*) + remove: true + - where: + subject: (.*)WebAppSnapshot(.*) + remove: true + - where: + subject: (.*)WebAppSourceControl(.*) + remove: true + - where: + subject: (.*)WebAppSyncFunction(.*) + remove: true + - where: + subject: (.*)WebAppTriggered(.*) + remove: true + - where: + subject: (.*)WebAppUsage(.*) + remove: true + - where: + subject: (.*)AzWebAppWeb(.*) + remove: true + - where: + subject: (.*)Execute(.*) + remove: true + - where: + subject: (.*)WebAppMySql(.*) + remove: true + - where: + subject: (.*)WebAppStorage(.*) + remove: true + - where: + subject: (.*)Connection(.*) + remove: true + - where: + subject: (.*)WebAppDeployment(.*) + remove: true + - where: + subject: (.*)WebAppHost(.*) + remove: true + - where: + subject: (.*)ManagedHosting(.*) + remove: true + - where: + subject: (.*)WebAppFrom(.*) + remove: true + - where: + subject: (.*)WebAppAuthSetting(.*) + remove: true + - where: + subject: (.*)AppServicePlan(.*) + remove: true + - where: + subject: (.*)ClassicMobile(.*) + remove: true + - where: + subject: (.*)Hosting(.*) + remove: true + - where: + subject: (.*)PublishingUser(.*) + remove: true + - where: + subject: (.*)SiteIdentifier(.*) + remove: true + - where: + subject: (.*)WebAppFunctionAdmin(.*) + remove: true + - where: + subject: (.*)WebAppFunctionSecret(.*) + remove: true + - where: + subject: (.*)WebAppProcess(.*) + remove: true + - where: + subject: (.*)WebAppWebJob(.*) + remove: true + - where: + subject: (.*)WebAppWebSite(.*) + remove: true + - where: + subject: (.*)WebAppNewSite(.*) + remove: true + - where: + subject: (.*)WebAppClone(.*) + remove: true + - where: + subject: Move(.*) + remove: true + - where: + subject: (.*)WebAppRepository(.*) + remove: true + - where: + subject: (.*)WebAppFunctionTrigger(.*) + remove: true + - where: + subject: AppServicePlanWebApp + remove: true + - where: + subject: (.*)WebAppSwift(.*) + remove: true + - where: + subject: (.*)WebAppProduction(.*) + remove: true + - where: + subject: (.*)WebAppCloneable(.*) + remove: true + - where: + subject: (.*)ContainerSetting(.*) + remove: true + - where: + subject: (.*)StaticSite(.*) + remove: true + - from: source-file-csharp + where: $ + transform: $ = $.replace(/sb.AppendLine\(\$@\"\{Indent\}FormatsToProcess = \{formatList\}\"\);/, 'sb.AppendLine\(\$@\"\{Indent\}FormatsToProcess = \{formatList\}\"\);\r\nsb.AppendLine\(\$@\"\{Indent\}TypesToProcess = \'./custom/Functions.types.ps1xml\'{Environment.NewLine}\{Indent\}ScriptsToProcess = \'./custom/HelperFunctions.ps1\'{Environment.NewLine}\{Indent\}FunctionsToExport = \'Get-AzFunctionApp\', \'Get-AzFunctionAppAvailableLocation\', \'Get-AzFunctionAppPlan\', \'Get-AzFunctionAppSetting\', \'New-AzFunctionApp\', \'New-AzFunctionAppPlan\', \'Remove-AzFunctionApp\', \'Remove-AzFunctionAppPlan\', \'Remove-AzFunctionAppSetting\', \'Restart-AzFunctionApp\', \'Start-AzFunctionApp\', \'Stop-AzFunctionApp\', \'Update-AzFunctionApp\', \'Update-AzFunctionAppPlan\', \'Update-AzFunctionAppSetting\'\"\);'); + - from: source-file-csharp + where: $ + transform: $ = $.replace(/sb.AppendLine\(\$@\"\{Indent\}AliasesToExport = \{aliasesList\}\"\);/, '') + - from: source-file-csharp + where: $ + transform: $ = $.replace(/sb.AppendLine\(\$@\"\{Indent\}FunctionsToExport = \{cmdletsList\}\"\);/, '') +``` + +``` yaml + +# Add Storage and AppInsights cmdlet subset +require: + - $(this-folder)/helpers/Storage/readme.noprofile.md + - $(this-folder)/helpers/AppInsights/readme.noprofile.md + - $(this-folder)/helpers/ManagedIdentity/readme.noprofile.md + +``` diff --git a/tests-upgrade/kubconf/kubernetesconfiguration.json b/tests-upgrade/kubconf/kubernetesconfiguration.json new file mode 100644 index 00000000000..77717c096ce --- /dev/null +++ b/tests-upgrade/kubconf/kubernetesconfiguration.json @@ -0,0 +1,664 @@ +{ + "swagger": "2.0", + "info": { + "version": "2019-11-01-preview", + "title": "SourceControlConfigurationClient", + "description": "Use these APIs to create Source Control Configuration resources through ARM, for Kubernetes Clusters." + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{clusterRp}/{clusterResourceName}/{clusterName}/providers/Microsoft.KubernetesConfiguration/sourceControlConfigurations/{sourceControlConfigurationName}": { + "get": { + "tags": [ + "SourceControlConfiguration" + ], + "description": "Gets details of the Source Control Configuration.", + "operationId": "SourceControlConfigurations_Get", + "x-ms-examples": { + "Get Source Control Configuration": { + "$ref": "./examples/GetSourceControlConfiguration.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ClusterRpParameter" + }, + { + "$ref": "#/parameters/ClusterResourceNameParameter" + }, + { + "$ref": "#/parameters/ClusterNameParameter" + }, + { + "$ref": "#/parameters/SourceControlConfigurationNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/SourceControlConfiguration" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "SourceControlConfiguration" + ], + "description": "Create a new Kubernetes Source Control Configuration.", + "operationId": "SourceControlConfigurations_CreateOrUpdate", + "x-ms-examples": { + "Create Source Control Configuration": { + "$ref": "./examples/CreateSourceControlConfiguration.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ClusterRpParameter" + }, + { + "$ref": "#/parameters/ClusterResourceNameParameter" + }, + { + "$ref": "#/parameters/ClusterNameParameter" + }, + { + "$ref": "#/parameters/SourceControlConfigurationNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "sourceControlConfiguration", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SourceControlConfiguration" + }, + "description": "Properties necessary to Create KubernetesConfiguration." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/SourceControlConfiguration" + } + }, + "201": { + "description": "Created.", + "schema": { + "$ref": "#/definitions/SourceControlConfiguration" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "SourceControlConfiguration" + ], + "description": "This will delete the YAML file used to set up the Source control configuration, thus stopping future sync from the source repo.", + "operationId": "SourceControlConfigurations_Delete", + "x-ms-examples": { + "Delete Source Control Configuration": { + "$ref": "./examples/DeleteSourceControlConfiguration.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ClusterRpParameter" + }, + { + "$ref": "#/parameters/ClusterResourceNameParameter" + }, + { + "$ref": "#/parameters/ClusterNameParameter" + }, + { + "$ref": "#/parameters/SourceControlConfigurationNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has been completed successfully." + }, + "204": { + "description": "No Content. The request has been accepted but the configuration was not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-long-running-operation": true + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{clusterRp}/{clusterResourceName}/{clusterName}/providers/Microsoft.KubernetesConfiguration/sourceControlConfigurations": { + "get": { + "tags": [ + "SourceControlConfiguration" + ], + "description": "List all Source Control Configurations.", + "operationId": "SourceControlConfigurations_List", + "x-ms-examples": { + "List Source Control Configuration": { + "$ref": "./examples/ListSourceControlConfiguration.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ClusterRpParameter" + }, + { + "$ref": "#/parameters/ClusterResourceNameParameter" + }, + { + "$ref": "#/parameters/ClusterNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/SourceControlConfigurationList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.KubernetesConfiguration/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "x-ms-examples": { + "BatchAccountDelete": { + "$ref": "./examples/OperationsList.json" + } + }, + "description": "List all the available operations the KubernetesConfiguration resource provider supports.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK response definition.", + "schema": { + "$ref": "#/definitions/ResourceProviderOperationList" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "Resource": { + "description": "The Resource model definition.", + "type": "object", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + } + }, + "x-ms-azure-resource": true + }, + "ProxyResource": { + "description": "ARM proxy resource.", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "properties": {} + }, + "Result": { + "description": "Sample result definition", + "properties": { + "sampleProperty": { + "type": "string", + "description": "Sample property of type string" + } + } + }, + "ErrorResponse": { + "description": "Error response.", + "properties": { + "error": { + "description": "Error definition.", + "$ref": "#/definitions/ErrorDefinition" + } + } + }, + "ErrorDefinition": { + "description": "Error definition.", + "properties": { + "code": { + "description": "Service specific error code which serves as the substatus for the HTTP error code.", + "type": "string", + "readOnly": true + }, + "message": { + "description": "Description of the error.", + "type": "string", + "readOnly": true + }, + "details": { + "description": "Internal error details.", + "type": "array", + "items": { + "$ref": "#/definitions/ErrorDefinition" + }, + "readOnly": true + } + } + }, + "ComplianceStatus": { + "description": "Compliance Status details", + "type": "object", + "readOnly": true, + "properties": { + "complianceState": { + "description": "The compliance state of the configuration.", + "$ref": "#/definitions/ComplianceState", + "readOnly": true + }, + "lastConfigApplied": { + "description": "Datetime the configuration was last applied.", + "type": "string", + "format": "date-time" + }, + "message": { + "description": "Message from when the configuration was applied.", + "type": "string" + }, + "messageLevel": { + "description": "Level of the message.", + "type": "string", + "enum": [ + "Error", + "Warning", + "Information" + ], + "x-ms-enum": { + "name": "messageLevel", + "modelAsString": true + } + } + } + }, + "ComplianceState": { + "description": "The compliance state of the configuration.", + "type": "string", + "readOnly": true, + "x-ms-enum": { + "name": "complianceState", + "modelAsString": true + }, + "enum": [ + "Pending", + "Compliant", + "Noncompliant", + "Installed", + "Failed" + ] + }, + "ChartVersion": { + "description": "Version of the operator Helm chart.", + "type": "string" + }, + "ChartValues": { + "description": "Values override for the operator Helm chart.", + "type": "string" + }, + "HelmOperatorProperties": { + "description": "Properties for Helm operator.", + "type": "object", + "properties": { + "chartVersion": { + "description": "Version of the operator Helm chart.", + "$ref": "#/definitions/ChartVersion" + }, + "chartValues": { + "description": "Values override for the operator Helm chart.", + "$ref": "#/definitions/ChartValues" + } + } + }, + "SourceControlConfiguration": { + "description": "The SourceControl Configuration object.", + "properties": { + "properties": { + "type": "object", + "x-ms-client-flatten": true, + "description": "Properties to create a Source Control Configuration resource", + "properties": { + "repositoryUrl": { + "type": "string", + "description": "Url of the SourceControl Repository." + }, + "operatorNamespace": { + "description": "The namespace to which this operator is installed to. Maximum of 253 lower case alphanumeric characters, hyphen and period only.", + "type": "string", + "default": "default" + }, + "operatorInstanceName": { + "description": "Instance name of the operator - identifying the specific configuration.", + "type": "string" + }, + "operatorType": { + "description": "Type of the operator", + "type": "string", + "enum": [ + "Flux" + ], + "x-ms-enum": { + "name": "operatorType", + "modelAsString": true + } + }, + "operatorParams": { + "description": "Any Parameters for the Operator instance in string format.", + "type": "string" + }, + "operatorScope": { + "description": "Scope at which the operator will be installed.", + "type": "string", + "enum": [ + "cluster", + "namespace" + ], + "default": "cluster", + "x-ms-enum": { + "name": "operatorScope", + "modelAsString": true + } + }, + "repositoryPublicKey": { + "description": "Public Key associated with this SourceControl configuration (either generated within the cluster or provided by the user).", + "type": "string", + "readOnly": true + }, + "enableHelmOperator": { + "description": "Option to enable Helm Operator for this git configuration.", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "enableHelmOperator", + "modelAsString": true + } + }, + "helmOperatorProperties": { + "description": "Properties for Helm operator.", + "type": "object", + "$ref": "#/definitions/HelmOperatorProperties" + }, + "provisioningState": { + "type": "string", + "description": "The provisioning state of the resource provider.", + "readOnly": true, + "x-ms-enum": { + "modelAsString": true, + "name": "ProvisioningState" + }, + "enum": [ + "Accepted", + "Deleting", + "Running", + "Succeeded", + "Failed" + ] + }, + "complianceStatus": { + "type": "object", + "description": "Compliance Status of the Configuration", + "readOnly": true, + "$ref": "#/definitions/ComplianceStatus" + } + } + } + }, + "allOf": [ + { + "$ref": "#/definitions/ProxyResource" + } + ] + }, + "SourceControlConfigurationList": { + "description": "Result of the request to list Source Control Configurations. It contains a list of SourceControlConfiguration objects and a URL link to get the next set of results.", + "properties": { + "value": { + "type": "array", + "readOnly": true, + "items": { + "$ref": "#/definitions/SourceControlConfiguration" + }, + "description": "List of Source Control Configurations within a Kubernetes cluster." + }, + "nextLink": { + "type": "string", + "readOnly": true, + "description": "URL to get the next set of configuration objects, if any." + } + } + }, + "ResourceProviderOperation": { + "description": "Supported operation of this resource provider.", + "readOnly": true, + "properties": { + "name": { + "description": "Operation name, in format of {provider}/{resource}/{operation}", + "type": "string" + }, + "display": { + "description": "Display metadata associated with the operation.", + "properties": { + "provider": { + "description": "Resource provider: Microsoft KubernetesConfiguration.", + "type": "string" + }, + "resource": { + "description": "Resource on which the operation is performed.", + "type": "string" + }, + "operation": { + "description": "Type of operation: get, read, delete, etc.", + "type": "string" + }, + "description": { + "description": "Description of this operation.", + "type": "string" + } + } + } + } + }, + "ResourceProviderOperationList": { + "description": "Result of the request to list operations.", + "readOnly": true, + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/ResourceProviderOperation" + }, + "description": "List of operations supported by this resource provider." + }, + "nextLink": { + "type": "string", + "readOnly": true, + "description": "URL to the next set of results, if any." + } + } + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The Azure subscription ID. This is a GUID-formatted string (e.g. 00000000-0000-0000-0000-000000000000)" + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group.", + "x-ms-parameter-location": "method" + }, + "ClusterRpParameter": { + "name": "clusterRp", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "Microsoft.ContainerService", + "Microsoft.Kubernetes" + ], + "description": "The Kubernetes cluster RP - either Microsoft.ContainerService (for AKS clusters) or Microsoft.Kubernetes (for OnPrem K8S clusters).", + "x-ms-parameter-location": "method" + }, + "ClusterResourceNameParameter": { + "name": "clusterResourceName", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "managedClusters", + "connectedClusters" + ], + "description": "The Kubernetes cluster resource name - either managedClusters (for AKS clusters) or connectedClusters (for OnPrem K8S clusters).", + "x-ms-parameter-location": "method" + }, + "ClusterNameParameter": { + "name": "clusterName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the kubernetes cluster.", + "x-ms-parameter-location": "method" + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to be used with the HTTP request." + }, + "SourceControlConfigurationNameParameter": { + "name": "sourceControlConfigurationName", + "in": "path", + "description": "Name of the Source Control Configuration.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + } + } +} diff --git a/tests-upgrade/kubconf/readme.md b/tests-upgrade/kubconf/readme.md new file mode 100644 index 00000000000..d38a81ae602 --- /dev/null +++ b/tests-upgrade/kubconf/readme.md @@ -0,0 +1,86 @@ + +# Az.KubernetesConfiguration +This directory contains the PowerShell module for the KubernetesConfiguration service. + +--- +## Status +[![Az.KubernetesConfiguration](https://img.shields.io/powershellgallery/v/Az.KubernetesConfiguration.svg?style=flat-square&label=Az.KubernetesConfiguration "Az.KubernetesConfiguration")](https://www.powershellgallery.com/packages/Az.KubernetesConfiguration/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.KubernetesConfiguration`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g autorest@beta`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - ./kubernetesconfiguration.json + +title: KubernetesConfiguration +module-version: 0.1.0 +subject-prefix: '' + +identity-correction-for-post: true + +directive: + - where: + variant: ^Create$|^CreateViaIdentity$|^CreateViaIdentityExpanded$|^Update$|^UpdateViaIdentity$ + remove: true + - where: + subject: SourceControlConfiguration + set: + subject: KubernetesConfiguration + - where: + parameter-name: ClusterResourceName + set: + parameter-name: ClusterType + - where: + verb: Set + subject: KubernetesConfiguration + set: + verb: Update + - where: + verb: New|Remove + subject: KubernetesConfiguration + hide: true + - where: + verb: Update + subject: KubernetesConfiguration + remove: true +``` diff --git a/tests-upgrade/mysql/.gitattributes b/tests-upgrade/mysql/.gitattributes new file mode 100644 index 00000000000..2125666142e --- /dev/null +++ b/tests-upgrade/mysql/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/tests-upgrade/mysql/.gitignore b/tests-upgrade/mysql/.gitignore new file mode 100644 index 00000000000..649721c69ce --- /dev/null +++ b/tests-upgrade/mysql/.gitignore @@ -0,0 +1,14 @@ +bin +obj +.vs +generated +internal +exports +custom/*.psm1 +test/*-TestResults.xml +/*.ps1 +/*.ps1xml +/*.psm1 +/*.snk +/*.csproj +/*.nuspec \ No newline at end of file diff --git a/tests-upgrade/mysql/common-types/resource-management/v1/privatelinks.json b/tests-upgrade/mysql/common-types/resource-management/v1/privatelinks.json new file mode 100644 index 00000000000..91e640b03fe --- /dev/null +++ b/tests-upgrade/mysql/common-types/resource-management/v1/privatelinks.json @@ -0,0 +1,174 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0", + "title": "Common types" + }, + "paths": {}, + "definitions": { + "PrivateEndpoint": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "The ARM identifier for Private Endpoint" + } + }, + "description": "The Private Endpoint resource." + }, + "PrivateEndpointConnection": { + "properties": { + "properties": { + "$ref": "#/definitions/PrivateEndpointConnectionProperties", + "x-ms-client-flatten": true, + "description": "Resource properties." + } + }, + "allOf": [ + { + "$ref": "./types.json#/definitions/Resource" + } + ], + "description": "The Private Endpoint Connection resource." + }, + "PrivateEndpointConnectionProperties": { + "properties": { + "privateEndpoint": { + "$ref": "#/definitions/PrivateEndpoint", + "description": "The resource of private end point." + }, + "privateLinkServiceConnectionState": { + "$ref": "#/definitions/PrivateLinkServiceConnectionState", + "description": "A collection of information about the state of the connection between service consumer and provider." + }, + "provisioningState": { + "$ref": "#/definitions/PrivateEndpointConnectionProvisioningState", + "description": "The provisioning state of the private endpoint connection resource." + } + }, + "required": [ + "privateLinkServiceConnectionState" + ], + "description": "Properties of the PrivateEndpointConnectProperties." + }, + "PrivateLinkServiceConnectionState": { + "properties": { + "status": { + "$ref": "#/definitions/PrivateEndpointServiceConnectionStatus", + "description": "Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service." + }, + "description": { + "type": "string", + "description": "The reason for approval/rejection of the connection." + }, + "actionsRequired": { + "type": "string", + "description": "A message indicating if changes on the service provider require any updates on the consumer." + } + }, + "description": "A collection of information about the state of the connection between service consumer and provider." + }, + "PrivateEndpointServiceConnectionStatus": { + "type": "string", + "description": "The private endpoint connection status.", + "enum": [ + "Pending", + "Approved", + "Rejected" + ], + "x-ms-enum": { + "name": "PrivateEndpointServiceConnectionStatus", + "modelAsString": true + } + }, + "PrivateEndpointConnectionProvisioningState": { + "type": "string", + "readOnly": true, + "description": "The current provisioning state.", + "enum": [ + "Succeeded", + "Creating", + "Deleting", + "Failed" + ], + "x-ms-enum": { + "name": "PrivateEndpointConnectionProvisioningState", + "modelAsString": true + } + }, + "PrivateLinkResource": { + "properties": { + "properties": { + "$ref": "#/definitions/PrivateLinkResourceProperties", + "description": "Resource properties.", + "x-ms-client-flatten": true + } + }, + "allOf": [ + { + "$ref": "./types.json#/definitions/Resource" + } + ], + "description": "A private link resource" + }, + "PrivateLinkResourceProperties": { + "properties": { + "groupId": { + "description": "The private link resource group id.", + "type": "string", + "readOnly": true + }, + "requiredMembers": { + "description": "The private link resource required member names.", + "type": "array", + "items": { + "type": "string" + }, + "readOnly": true + }, + "requiredZoneNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The private link resource Private link DNS zone name." + } + }, + "description": "Properties of a private link resource." + }, + "PrivateEndpointConnectionListResult": { + "properties": { + "value": { + "type": "array", + "description": "Array of private endpoint connections", + "items": { + "$ref": "#/definitions/PrivateEndpointConnection" + } + } + }, + "description": "List of private endpoint connection associated with the specified storage account" + }, + "PrivateLinkResourceListResult": { + "properties": { + "value": { + "type": "array", + "description": "Array of private link resources", + "items": { + "$ref": "#/definitions/PrivateLinkResource" + } + } + }, + "description": "A list of private link resources" + } + }, + "parameters": { + "PrivateEndpointConnectionName": { + "name": "privateEndpointConnectionName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the private endpoint connection associated with the Azure resource", + "x-ms-parameter-location": "method" + } + } +} diff --git a/tests-upgrade/mysql/common-types/resource-management/v1/types.json b/tests-upgrade/mysql/common-types/resource-management/v1/types.json new file mode 100644 index 00000000000..bf32e064a31 --- /dev/null +++ b/tests-upgrade/mysql/common-types/resource-management/v1/types.json @@ -0,0 +1,467 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0", + "title": "Common types" + }, + "paths": {}, + "definitions": { + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "AzureEntityResource": { + "x-ms-client-name": "AzureEntityResource", + "description": "The resource model definition for a Azure Resource Manager resource with an etag.", + "properties": { + "etag": { + "type": "string", + "readOnly": true, + "description": "Resource Etag." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "TrackedResource": { + "description": "The resource model definition for a ARM tracked top level resource", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "ProxyResource": { + "description": "The resource model definition for a ARM proxy resource. It will have everything other than required location and tags", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "ResourceModelWithAllowedPropertySet": { + "description": "The resource model definition containing the full set of allowed properties for a resource. Except properties bag, there cannot be a top level property outside of this set.", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "x-ms-mutability": [ + "read" + ], + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "x-ms-mutability": [ + "read" + ], + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts.." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + }, + "managedBy": { + "type": "string", + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource." + }, + "kind": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type; e.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\)]+$" + }, + "etag": { + "readOnly": true, + "type": "string", + "description": "The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. " + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "identity": { + "allOf": [ + { + "$ref": "#/definitions/Identity" + } + ] + }, + "sku": { + "allOf": [ + { + "$ref": "#/definitions/Sku" + } + ] + }, + "plan": { + "allOf": [ + { + "$ref": "#/definitions/Plan" + } + ] + } + }, + "x-ms-azure-resource": true + }, + "Sku": { + "description": "The resource model definition representing SKU", + "properties": { + "name": { + "type": "string", + "description": "The name of the SKU. Ex - P3. It is typically a letter+number code" + }, + "tier": { + "type": "string", + "enum": [ + "Free", + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuTier", + "modelAsString": false + }, + "description": "This field is required to be implemented by the Resource Provider if the service has more than one tier, but is not required on a PUT." + }, + "size": { + "type": "string", + "description": "The SKU size. When the name field is the combination of tier and some other value, this would be the standalone code. " + }, + "family": { + "type": "string", + "description": "If the service has different generations of hardware, for the same SKU, then that can be captured here." + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "If the SKU supports scale out/in then the capacity integer should be included. If scale out/in is not possible for the resource this may be omitted." + } + }, + "required": [ + "name" + ] + }, + "Identity": { + "description": "Identity for the resource.", + "properties": { + "principalId": { + "readOnly": true, + "type": "string", + "description": "The principal ID of resource identity." + }, + "tenantId": { + "readOnly": true, + "type": "string", + "description": "The tenant ID of resource." + }, + "type": { + "type": "string", + "description": "The identity type.", + "enum": [ + "SystemAssigned" + ], + "x-ms-enum": { + "name": "ResourceIdentityType", + "modelAsString": false + } + } + } + }, + "Plan": { + "properties": { + "name": { + "type": "string", + "description": "A user defined name of the 3rd Party Artifact that is being procured." + }, + "publisher": { + "type": "string", + "description": "The publisher of the 3rd Party Artifact that is being bought. E.g. NewRelic" + }, + "product": { + "type": "string", + "description": "The 3rd Party artifact that is being procured. E.g. NewRelic. Product maps to the OfferID specified for the artifact at the time of Data Market onboarding. " + }, + "promotionCode": { + "type": "string", + "description": "A publisher provided promotion code as provisioned in Data Market for the said product/artifact." + }, + "version": { + "type": "string", + "description": "The version of the desired product/artifact." + } + }, + "description": "Plan for the resource.", + "required": [ + "name", + "publisher", + "product" + ] + }, + "ErrorResponse": { + "properties": { + "code": { + "readOnly": true, + "type": "string", + "description": "The error code." + }, + "message": { + "readOnly": true, + "type": "string", + "description": "The error message." + }, + "target": { + "readOnly": true, + "type": "string", + "description": "The error target." + }, + "details": { + "readOnly": true, + "type": "array", + "items": { + "$ref": "#/definitions/ErrorResponse" + }, + "description": "The error details." + }, + "additionalInfo": { + "readOnly": true, + "type": "array", + "items": { + "$ref": "#/definitions/ErrorAdditionalInfo" + }, + "description": "The error additional info." + } + }, + "description": "The resource management error response." + }, + "ErrorAdditionalInfo": { + "properties": { + "type": { + "readOnly": true, + "type": "string", + "description": "The additional info type." + }, + "info": { + "readOnly": true, + "type": "object", + "description": "The additional info." + } + }, + "description": "The resource management error additional info." + }, + "locationData": { + "description": "Metadata pertaining to the geographic location of the resource.", + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 256, + "description": "A canonical name for the geographic or physical location." + }, + "city": { + "type": "string", + "description": "The city or locality where the resource is located." + }, + "district": { + "type": "string", + "description": "The district, state, or province where the resource is located." + }, + "countryOrRegion": { + "type": "string", + "description": "The country or region where the resource is located" + } + }, + "required": [ + "name" + ] + }, + "systemData": { + "description": "Metadata pertaining to creation and last modification of the resource.", + "type": "object", + "readOnly": true, + "properties": { + "createdBy": { + "type": "string", + "description": "The identity that created the resource." + }, + "createdByType": { + "type": "string", + "description": "The type of identity that created the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource creation (UTC)." + }, + "lastModifiedBy": { + "type": "string", + "description": "The identity that last modified the resource." + }, + "lastModifiedByType": { + "type": "string", + "description": "The type of identity that last modified the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "lastModifiedAt": { + "type": "string", + "format": "date-time", + "description": "The type of identity that last modified the resource." + } + } + }, + "encryptionProperties": { + "description": "Configuration of key for data encryption", + "type": "object", + "properties": { + "status": { + "description": "Indicates whether or not the encryption is enabled for container registry.", + "enum": [ + "enabled", + "disabled" + ], + "type": "string", + "x-ms-enum": { + "name": "EncryptionStatus", + "modelAsString": true + } + }, + "keyVaultProperties": { + "$ref": "#/definitions/KeyVaultProperties", + "description": "Key vault properties." + } + } + }, + "KeyVaultProperties": { + "type": "object", + "properties": { + "keyIdentifier": { + "description": "Key vault uri to access the encryption key.", + "type": "string" + }, + "identity": { + "description": "The client id of the identity which will be used to access key vault.", + "type": "string" + } + } + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "minLength": 1 + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation.", + "minLength": 1 + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/mysql/common-types/resource-management/v2/types.json b/tests-upgrade/mysql/common-types/resource-management/v2/types.json new file mode 100644 index 00000000000..7ee7093af3e --- /dev/null +++ b/tests-upgrade/mysql/common-types/resource-management/v2/types.json @@ -0,0 +1,473 @@ +{ + "swagger": "2.0", + "info": { + "version": "2.0", + "title": "Common types" + }, + "paths": {}, + "definitions": { + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "AzureEntityResource": { + "x-ms-client-name": "AzureEntityResource", + "description": "The resource model definition for a Azure Resource Manager resource with an etag.", + "properties": { + "etag": { + "type": "string", + "readOnly": true, + "description": "Resource Etag." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "TrackedResource": { + "description": "The resource model definition for a ARM tracked top level resource", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "ProxyResource": { + "description": "The resource model definition for a ARM proxy resource. It will have everything other than required location and tags", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "ResourceModelWithAllowedPropertySet": { + "description": "The resource model definition containing the full set of allowed properties for a resource. Except properties bag, there cannot be a top level property outside of this set.", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "x-ms-mutability": [ + "read" + ], + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "x-ms-mutability": [ + "read" + ], + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts.." + }, + "location": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "The geo-location where the resource lives" + }, + "managedBy": { + "type": "string", + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource." + }, + "kind": { + "type": "string", + "x-ms-mutability": [ + "read", + "create" + ], + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type; e.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\)]+$" + }, + "etag": { + "readOnly": true, + "type": "string", + "description": "The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. " + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ], + "description": "Resource tags." + }, + "identity": { + "allOf": [ + { + "$ref": "#/definitions/Identity" + } + ] + }, + "sku": { + "allOf": [ + { + "$ref": "#/definitions/Sku" + } + ] + }, + "plan": { + "allOf": [ + { + "$ref": "#/definitions/Plan" + } + ] + } + }, + "x-ms-azure-resource": true + }, + "Sku": { + "description": "The resource model definition representing SKU", + "properties": { + "name": { + "type": "string", + "description": "The name of the SKU. Ex - P3. It is typically a letter+number code" + }, + "tier": { + "type": "string", + "enum": [ + "Free", + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuTier", + "modelAsString": false + }, + "description": "This field is required to be implemented by the Resource Provider if the service has more than one tier, but is not required on a PUT." + }, + "size": { + "type": "string", + "description": "The SKU size. When the name field is the combination of tier and some other value, this would be the standalone code. " + }, + "family": { + "type": "string", + "description": "If the service has different generations of hardware, for the same SKU, then that can be captured here." + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "If the SKU supports scale out/in then the capacity integer should be included. If scale out/in is not possible for the resource this may be omitted." + } + }, + "required": [ + "name" + ] + }, + "Identity": { + "description": "Identity for the resource.", + "properties": { + "principalId": { + "readOnly": true, + "type": "string", + "description": "The principal ID of resource identity." + }, + "tenantId": { + "readOnly": true, + "type": "string", + "description": "The tenant ID of resource." + }, + "type": { + "type": "string", + "description": "The identity type.", + "enum": [ + "SystemAssigned" + ], + "x-ms-enum": { + "name": "ResourceIdentityType", + "modelAsString": false + } + } + } + }, + "Plan": { + "properties": { + "name": { + "type": "string", + "description": "A user defined name of the 3rd Party Artifact that is being procured." + }, + "publisher": { + "type": "string", + "description": "The publisher of the 3rd Party Artifact that is being bought. E.g. NewRelic" + }, + "product": { + "type": "string", + "description": "The 3rd Party artifact that is being procured. E.g. NewRelic. Product maps to the OfferID specified for the artifact at the time of Data Market onboarding. " + }, + "promotionCode": { + "type": "string", + "description": "A publisher provided promotion code as provisioned in Data Market for the said product/artifact." + }, + "version": { + "type": "string", + "description": "The version of the desired product/artifact." + } + }, + "description": "Plan for the resource.", + "required": [ + "name", + "publisher", + "product" + ] + }, + "ErrorResponse": { + "properties": { + "error": { + "type": "object", + "description": "The error object.", + "properties": { + "code": { + "readOnly": true, + "type": "string", + "description": "The error code." + }, + "message": { + "readOnly": true, + "type": "string", + "description": "The error message." + }, + "target": { + "readOnly": true, + "type": "string", + "description": "The error target." + }, + "details": { + "readOnly": true, + "type": "array", + "items": { + "$ref": "#/definitions/ErrorResponse" + }, + "description": "The error details." + }, + "additionalInfo": { + "readOnly": true, + "type": "array", + "items": { + "$ref": "#/definitions/ErrorAdditionalInfo" + }, + "description": "The error additional info." + } + } + } + }, + "description": "The resource management error response." + }, + "ErrorAdditionalInfo": { + "properties": { + "type": { + "readOnly": true, + "type": "string", + "description": "The additional info type." + }, + "info": { + "readOnly": true, + "type": "object", + "description": "The additional info." + } + }, + "description": "The resource management error additional info." + }, + "locationData": { + "description": "Metadata pertaining to the geographic location of the resource.", + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 256, + "description": "A canonical name for the geographic or physical location." + }, + "city": { + "type": "string", + "description": "The city or locality where the resource is located." + }, + "district": { + "type": "string", + "description": "The district, state, or province where the resource is located." + }, + "countryOrRegion": { + "type": "string", + "description": "The country or region where the resource is located" + } + }, + "required": [ + "name" + ] + }, + "systemData": { + "description": "Metadata pertaining to creation and last modification of the resource.", + "type": "object", + "readOnly": true, + "properties": { + "createdBy": { + "type": "string", + "description": "The identity that created the resource." + }, + "createdByType": { + "type": "string", + "description": "The type of identity that created the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource creation (UTC)." + }, + "lastModifiedBy": { + "type": "string", + "description": "The identity that last modified the resource." + }, + "lastModifiedByType": { + "type": "string", + "description": "The type of identity that last modified the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "lastModifiedAt": { + "type": "string", + "format": "date-time", + "description": "The type of identity that last modified the resource." + } + } + }, + "encryptionProperties": { + "description": "Configuration of key for data encryption", + "type": "object", + "properties": { + "status": { + "description": "Indicates whether or not the encryption is enabled for container registry.", + "enum": [ + "enabled", + "disabled" + ], + "type": "string", + "x-ms-enum": { + "name": "EncryptionStatus", + "modelAsString": true + } + }, + "keyVaultProperties": { + "$ref": "#/definitions/KeyVaultProperties", + "description": "Key vault properties." + } + } + }, + "KeyVaultProperties": { + "type": "object", + "properties": { + "keyIdentifier": { + "description": "Key vault uri to access the encryption key.", + "type": "string" + }, + "identity": { + "description": "The client id of the identity which will be used to access key vault.", + "type": "string" + } + } + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "minLength": 1 + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "The API version to use for this operation.", + "minLength": 1 + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group. The name is case insensitive.", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + } + } +} diff --git a/tests-upgrade/mysql/common-types/rfcs/rfc7517.json b/tests-upgrade/mysql/common-types/rfcs/rfc7517.json new file mode 100644 index 00000000000..f856d152f36 --- /dev/null +++ b/tests-upgrade/mysql/common-types/rfcs/rfc7517.json @@ -0,0 +1,104 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0", + "title": "Common types" + }, + "paths": {}, + "definitions": { + "JSONWebKey": { + "type": "object", + "required": [ + "use", + "kty", + "kid", + "alg" + ], + "properties": { + "alg": { + "description": "The \"alg\" (algorithm) parameter identifies the algorithm intended for\nuse with the key. The values used should either be registered in the\nIANA \"JSON Web Signature and Encryption Algorithms\" registry\nestablished by [JWA] or be a value that contains a Collision-\nResistant Name.", + "type": "string" + }, + "crv": { + "description": "The \"crv\" (curve) parameter identifies the curve type", + "type": "string" + }, + "d": { + "description": "RSA private exponent or ECC private key", + "type": "string" + }, + "dp": { + "description": "RSA Private Key Parameter", + "type": "string" + }, + "dq": { + "description": "RSA Private Key Parameter", + "type": "string" + }, + "e": { + "description": "RSA public exponent, in Base64", + "type": "string" + }, + "k": { + "description": "Symmetric key", + "type": "string" + }, + "kid": { + "description": "The \"kid\" (key ID) parameter is used to match a specific key. This\nis used, for instance, to choose among a set of keys within a JWK Set\nduring key rollover. The structure of the \"kid\" value is\nunspecified. When \"kid\" values are used within a JWK Set, different\nkeys within the JWK Set SHOULD use distinct \"kid\" values. (One\nexample in which different keys might use the same \"kid\" value is if\nthey have different \"kty\" (key type) values but are considered to be\nequivalent alternatives by the application using them.) The \"kid\"\nvalue is a case-sensitive string.", + "type": "string" + }, + "kty": { + "description": "The \"kty\" (key type) parameter identifies the cryptographic algorithm\nfamily used with the key, such as \"RSA\" or \"EC\". \"kty\" values should\neither be registered in the IANA \"JSON Web Key Types\" registry\nestablished by [JWA] or be a value that contains a Collision-\nResistant Name. The \"kty\" value is a case-sensitive string.", + "type": "string" + }, + "n": { + "description": "RSA modulus, in Base64", + "type": "string" + }, + "p": { + "description": "RSA secret prime", + "type": "string" + }, + "q": { + "description": "RSA secret prime, with p < q", + "type": "string" + }, + "qi": { + "description": "RSA Private Key Parameter", + "type": "string" + }, + "use": { + "description": "Use (\"public key use\") identifies the intended use of\nthe public key. The \"use\" parameter is employed to indicate whether\na public key is used for encrypting data or verifying the signature\non data. Values are commonly \"sig\" (signature) or \"enc\" (encryption).", + "type": "string" + }, + "x": { + "description": "X coordinate for the Elliptic Curve point", + "type": "string" + }, + "x5c": { + "description": "The \"x5c\" (X.509 certificate chain) parameter contains a chain of one\nor more PKIX certificates [RFC5280]. The certificate chain is\nrepresented as a JSON array of certificate value strings. Each\nstring in the array is a base64-encoded (Section 4 of [RFC4648] --\nnot base64url-encoded) DER [ITU.X690.1994] PKIX certificate value.\nThe PKIX certificate containing the key value MUST be the first\ncertificate.", + "type": "array", + "items": { + "type": "string" + } + }, + "y": { + "description": "Y coordinate for the Elliptic Curve point", + "type": "string" + } + } + }, + "JSONWebKeySet": { + "type": "object", + "properties": { + "keys": { + "description": "The value of the \"keys\" parameter is an array of JWK values. By\ndefault, the order of the JWK values within the array does not imply\nan order of preference among them, although applications of JWK Sets\ncan choose to assign a meaning to the order for their purposes, if\ndesired.", + "type": "array", + "items": { + "$ref": "#/definitions/JSONWebKey" + } + } + } + } + } +} diff --git a/tests-upgrade/mysql/custom/readme.md b/tests-upgrade/mysql/custom/readme.md new file mode 100644 index 00000000000..f8336dda153 --- /dev/null +++ b/tests-upgrade/mysql/custom/readme.md @@ -0,0 +1,41 @@ +# Custom +This directory contains custom implementation for non-generated cmdlets for the `Az.MySql` module. Both scripts (`.ps1`) and C# files (`.cs`) can be implemented here. They will be used during the build process in `build-module.ps1`, and create cmdlets into the `..\exports` folder. The only generated file into this folder is the `Az.MySql.custom.psm1`. This file should not be modified. + +## Info +- Modifiable: yes +- Generated: partial +- Committed: yes +- Packaged: yes + +## Details +For `Az.MySql` to use custom cmdlets, it does this two different ways. We **highly recommend** creating script cmdlets, as they are easier to write and allow access to the other exported cmdlets. C# cmdlets *cannot access exported cmdlets*. + +For C# cmdlets, they are compiled with the rest of the generated low-level cmdlets into the `./bin/Az.MySql.private.dll`. The names of the cmdlets (methods) and files must follow the `[cmdletName]_[variantName]` syntax used for generated cmdlets. The `variantName` is used as the `ParameterSetName`, so use something appropriate that doesn't clash with already created variant or parameter set names. You cannot use the `ParameterSetName` property in the `Parameter` attribute on C# cmdlets. Each cmdlet must be separated into variants using the same pattern as seen in the `generated/cmdlets` folder. + +For script cmdlets, these are loaded via the `Az.MySql.custom.psm1`. Then, during the build process, this module is loaded and processed in the same manner as the C# cmdlets. The fundemental difference is the script cmdlets use the `ParameterSetName` attribute and C# cmdlets do not. To create a script cmdlet variant of a generated cmdlet, simply decorate all parameters in the script with the new `ParameterSetName` in the `Parameter` attribute. This will appropriately treat each parameter set as a separate variant when processed to be exported during the build. + +## Purpose +This allows the modules to have cmdlets that were not defined in the REST specification. It also allows combining logic using generated cmdlets. This is a level of customization beyond what can be done using the [readme configuration options](https://github.com/Azure/autorest/blob/master/docs/powershell/options.md) that are currently available. These custom cmdlets are then referenced by the cmdlets created at build-time in the `..\exports` folder. + +## Usage +The easiest way currently to start developing custom cmdlets is to copy an existing cmdlet. For C# cmdlets, copy one from the `generated/cmdlets` folder. For script cmdlets, build the project using `build-module.ps1` and copy one of the scripts from the `..\exports` folder. After that, if you want to add new parameter sets, follow the guidelines in the `Details` section above. For implementing a new cmdlets, at minimum, please keep these parameters: +- Break +- DefaultProfile +- HttpPipelineAppend +- HttpPipelinePrepend +- Proxy +- ProxyCredential +- ProxyUseDefaultCredentials + +These provide functionality to our HTTP pipeline and other useful features. In script, you can forward these parameters using `$PSBoundParameters` to the other cmdlets you're calling within `Az.MySql`. For C#, follow the usage seen in the `ProcessRecordAsync` method. + +### Attributes +For processing the cmdlets, we've created some additional attributes: +- `Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.DescriptionAttribute` + - Used in C# cmdlets to provide a high-level description of the cmdlet. This is propegated to reference documentation via [help comments](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help) in the exported scripts. +- `Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.DoNotExportAttribute` + - Used in C# and script cmdlets to suppress creating an exported cmdlet at build-time. These cmdlets will *not be exposed* by `Az.MySql`. +- `Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.InternalExportAttribute` + - Used in C# cmdlets to route exported cmdlets to the `..\internal`, which are *not exposed* by `Az.MySql`. For more information, see [readme.md](..\internal/readme.md) in the `..\internal` folder. +- `Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.ProfileAttribute` + - Used in C# and script cmdlets to define which Azure profiles the cmdlet supports. This is only supported for Azure (`--azure`) modules. \ No newline at end of file diff --git a/tests-upgrade/mysql/docs/readme.md b/tests-upgrade/mysql/docs/readme.md new file mode 100644 index 00000000000..62fb790569c --- /dev/null +++ b/tests-upgrade/mysql/docs/readme.md @@ -0,0 +1,11 @@ +# Docs +This directory contains the documentation of the cmdlets for the `Az.MySql` module. To run documentation generation, use the `generate-help.ps1` script at the root module folder. Files in this folder will *always be overriden on regeneration*. To update documentation examples, please use the `..\examples` folder. + +## Info +- Modifiable: no +- Generated: all +- Committed: yes +- Packaged: yes + +## Details +The process of documentation generation loads `Az.MySql` and analyzes the exported cmdlets from the module. It recognizes the [help comments](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help) that are generated into the scripts in the `..\exports` folder. Additionally, when writing custom cmdlets in the `..\custom` folder, you can use the help comments syntax, which decorate the exported scripts at build-time. The documentation examples are taken from the `..\examples` folder. \ No newline at end of file diff --git a/tests-upgrade/mysql/examples/readme.md b/tests-upgrade/mysql/examples/readme.md new file mode 100644 index 00000000000..ac871d71fc7 --- /dev/null +++ b/tests-upgrade/mysql/examples/readme.md @@ -0,0 +1,11 @@ +# Examples +This directory contains examples from the exported cmdlets of the module. When `build-module.ps1` is ran, example stub files will be generated here. If your module support Azure Profiles, the example stubs will be in individual profile folders. These example stubs should be updated to show how the cmdlet is used. The examples are imported into the documentation when `generate-help.ps1` is ran. + +## Info +- Modifiable: yes +- Generated: partial +- Committed: yes +- Packaged: no + +## Purpose +This separates the example documentation details from the generated documentation information provided directly from the generated cmdlets. Since the cmdlets don't have examples from the REST spec, this provides a means to add examples easily. The example stubs provide the markdown format that is required. The 3 core elements are: the name of the example, the code information of the example, and the description of the example. That information, if the markdown format is followed, will be available to documentation generation and be part of the documents in the `..\docs` folder. \ No newline at end of file diff --git a/tests-upgrade/mysql/how-to.md b/tests-upgrade/mysql/how-to.md new file mode 100644 index 00000000000..8b7309794ce --- /dev/null +++ b/tests-upgrade/mysql/how-to.md @@ -0,0 +1,58 @@ +# How-To +This document describes how to develop for `Az.MySql`. + +## Building `Az.MySql` +To build, run the `build-module.ps1` at the root of the module directory. This will generate the proxy script cmdlets that are the cmdlets being exported by this module. After the build completes, the proxy script cmdlets will be output to the `exports` folder. To read more about the proxy script cmdlets, look at the [readme.md](exports/readme.md) in the `exports` folder. + +## Creating custom cmdlets +To add cmdlets that were not generated by the REST specification, use the `custom` folder. This folder allows you to add handwritten `.ps1` and `.cs` files. Currently, we support using `.ps1` scripts as new cmdlets or as additional low-level variants (via `ParameterSet`), and `.cs` files as low-level (variants) cmdlets that the exported script cmdlets call. We do not support exporting any `.cs` (dll) cmdlets directly. To read more about custom cmdlets, look at the [readme.md](custom/readme.md) in the `custom` folder. + +## Generating documentation +To generate documentation, the process is now integrated into the `build-module.ps1` script. If you don't want to run this process as part of `build-module.ps1`, you can provide the `-NoDocs` switch. If you want to run documentation generation after the build process, you may still run the `generate-help.ps1` script. Overall, the process will look at the documentation comments in the generated and custom cmdlets and types, and create `.md` files into the `docs` folder. Additionally, this pulls in any examples from the `examples` folder and adds them to the generated help markdown documents. To read more about examples, look at the [readme.md](examples/readme.md) in the `examples` folder. To read more about documentation, look at the [readme.md](docs/readme.md) in the `docs` folder. + +## Testing `Az.MySql` +To test the cmdlets, we use [Pester](https://github.com/pester/Pester). Tests scripts (`.ps1`) should be added to the `test` folder. To execute the Pester tests, run the `test-module.ps1` script. This will run all tests in `playback` mode within the `test` folder. To read more about testing cmdlets, look at the [readme.md](examples/readme.md) in the `examples` folder. + +## Packing `Az.MySql` +To pack `Az.MySql` for distribution, run the `pack-module.ps1` script. This will take the contents of multiple directories and certain root-folder files to create a `.nupkg`. The structure of the `.nupkg` is created so it can be loaded part of a [PSRepository](https://docs.microsoft.com/en-us/powershell/module/powershellget/register-psrepository). Additionally, this package is in a format for distribution to the [PSGallery](https://www.powershellgallery.com/). For signing an Azure module, please contact the [Azure PowerShell](https://github.com/Azure/azure-powershell) team. + +## Module Script Details +There are multiple scripts created for performing different actions for developing `Az.MySql`. +- `build-module.ps1` + - Builds the module DLL (`./bin/Az.MySql.private.dll`), creates the exported cmdlets and documentation, generates custom cmdlet test stubs and exported cmdlet example stubs, and updates `./Az.MySql.psd1` with Azure profile information. + - **Parameters**: [`Switch` parameters] + - `-Run`: After building, creates an isolated PowerShell session and loads `Az.MySql`. + - `-Test`: After building, runs the `Pester` tests defined in the `test` folder. + - `-Docs`: After building, generates the Markdown documents for the modules into the `docs` folder. + - `-Pack`: After building, packages the module into a `.nupkg`. + - `-Code`: After building, opens a VSCode window with the module's directory and runs (see `-Run`) the module. + - `-Release`: Builds the module in `Release` configuration (as opposed to `Debug` configuration). + - `-NoDocs`: Supresses writing the documentation markdown files as part of the cmdlet exporting process. + - `-Debugger`: Used when attaching the debugger in Visual Studio to the PowerShell session, and running the build process without recompiling the DLL. This suppresses running the script as an isolated process. +- `run-module.ps1` + - Creates an isolated PowerShell session and loads `Az.MySql` into the session. + - Same as `-Run` in `build-module.ps1`. + - **Parameters**: [`Switch` parameters] + - `-Code`: Opens a VSCode window with the module's directory. + - Same as `-Code` in `build-module.ps1`. +- `generate-help.ps1` + - Generates the Markdown documents for the modules into the `docs` folder. + - Same as `-Docs` in `build-module.ps1`. +- `test-module.ps1` + - Runs the `Pester` tests defined in the `test` folder. + - Same as `-Test` in `build-module.ps1`. +- `pack-module.ps1` + - Packages the module into a `.nupkg` for distribution. + - Same as `-Pack` in `build-module.ps1`. +- `generate-help.ps1` + - Generates the Markdown documents for the modules into the `docs` folder. + - Same as `-Docs` in `build-module.ps1`. + - This process is now integrated into `build-module.ps1` automatically. To disable, use `-NoDocs` when running `build-module.ps1`. +- `export-surface.ps1` + - Generates Markdown documents for both the cmdlet surface and the model (class) surface of the module. + - These files are placed into the `resources` folder. + - Used for investigating the surface of your module. These are *not* documentation for distribution. +- `check-dependencies.ps1` + - Used in `run-module.ps1` and `test-module.ps1` to verify dependent modules are available to run those tasks. + - It will download local (within the module's directory structure) versions of those modules as needed. + - This script *does not* need to be ran by-hand. \ No newline at end of file diff --git a/tests-upgrade/mysql/license.txt b/tests-upgrade/mysql/license.txt new file mode 100644 index 00000000000..b9f3180fb9a --- /dev/null +++ b/tests-upgrade/mysql/license.txt @@ -0,0 +1,227 @@ +MICROSOFT SOFTWARE LICENSE TERMS + +MICROSOFT AZURE POWERSHELL + +These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. + +BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE. + + +-----------------START OF LICENSE-------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +-------------------END OF LICENSE------------------------------------------ + + +----------------START OF THIRD PARTY NOTICE-------------------------------- + + +The software includes the AutoMapper library ("AutoMapper"). The MIT License set out below is provided for informational purposes only. It is not the license that governs any part of the software. + +Provided for Informational Purposes Only + +AutoMapper + +The MIT License (MIT) +Copyright (c) 2010 Jimmy Bogard + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + + + +*************** + +The software includes Newtonsoft.Json. The MIT License set out below is provided for informational purposes only. It is not the license that governs any part of the software. + +Newtonsoft.Json + +The MIT License (MIT) +Copyright (c) 2007 James Newton-King +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------END OF THIRD PARTY NOTICE---------------------------------------- + diff --git a/tests-upgrade/mysql/mysql.json b/tests-upgrade/mysql/mysql.json new file mode 100644 index 00000000000..78e0d429756 --- /dev/null +++ b/tests-upgrade/mysql/mysql.json @@ -0,0 +1,2576 @@ +{ + "swagger": "2.0", + "info": { + "title": "MySQLManagementClient", + "description": "The Microsoft Azure management API provides create, read, update, and delete functionality for Azure MySQL resources including servers, databases, firewall rules, VNET rules, log files and configurations with new business model.", + "version": "2017-12-01" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}": { + "put": { + "tags": [ + "Servers" + ], + "operationId": "Servers_Create", + "x-ms-examples": { + "Create a new server": { + "$ref": "./examples/ServerCreate.json" + }, + "Create a database as a point in time restore": { + "$ref": "./examples/ServerCreatePointInTimeRestore.json" + }, + "Create a server as a geo restore ": { + "$ref": "./examples/ServerCreateGeoRestoreMode.json" + }, + "Create a replica server": { + "$ref": "./examples/ServerCreateReplicaMode.json" + } + }, + "description": "Creates a new server or updates an existing server. The update action will overwrite the existing server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ServerForCreate" + }, + "description": "The required parameters for creating or updating a server." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Server" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/Server" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true + }, + "patch": { + "tags": [ + "Servers" + ], + "operationId": "Servers_Update", + "x-ms-examples": { + "ServerUpdate": { + "$ref": "./examples/ServerUpdate.json" + } + }, + "description": "Updates an existing server. The request body can contain one to many of the properties present in the normal server definition.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ServerUpdateParameters" + }, + "description": "The required parameters for updating a server." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Server" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true + }, + "delete": { + "tags": [ + "Servers" + ], + "operationId": "Servers_Delete", + "x-ms-examples": { + "ServerDelete": { + "$ref": "./examples/ServerDelete.json" + } + }, + "description": "Deletes a server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "202": { + "description": "Accepted" + }, + "204": { + "description": "NoContent" + } + }, + "x-ms-long-running-operation": true + }, + "get": { + "tags": [ + "Servers" + ], + "operationId": "Servers_Get", + "x-ms-examples": { + "ServerGet": { + "$ref": "./examples/ServerGet.json" + } + }, + "description": "Gets information about a server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Server" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers": { + "get": { + "tags": [ + "Servers" + ], + "operationId": "Servers_ListByResourceGroup", + "x-ms-examples": { + "ServerListByResourceGroup": { + "$ref": "./examples/ServerListByResourceGroup.json" + } + }, + "description": "List all the servers in a given resource group.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ServerListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.DBforMySQL/servers": { + "get": { + "tags": [ + "Servers" + ], + "operationId": "Servers_List", + "x-ms-examples": { + "ServerList": { + "$ref": "./examples/ServerList.json" + } + }, + "description": "List all the servers in a given subscription.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ServerListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/restart": { + "post": { + "tags": [ + "ServerRestart" + ], + "operationId": "Servers_Restart", + "x-ms-examples": { + "ServerRestart": { + "$ref": "./examples/ServerRestart.json" + } + }, + "description": "Restarts a server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "202": { + "description": "Accepted" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-long-running-operation": true + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/replicas": { + "get": { + "tags": [ + "Replicas" + ], + "operationId": "Replicas_ListByServer", + "x-ms-examples": { + "ReplicasListByServer": { + "$ref": "./examples/ReplicasListByServer.json" + } + }, + "description": "List all the replicas for a given server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ServerListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/firewallRules/{firewallRuleName}": { + "put": { + "tags": [ + "FirewallRules" + ], + "operationId": "FirewallRules_CreateOrUpdate", + "x-ms-examples": { + "FirewallRuleCreate": { + "$ref": "./examples/FirewallRuleCreate.json" + } + }, + "description": "Creates a new firewall rule or updates an existing firewall rule.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/FirewallRuleNameParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/FirewallRule" + }, + "description": "The required parameters for creating or updating a firewall rule." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/FirewallRule" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/FirewallRule" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true + }, + "delete": { + "tags": [ + "FirewallRules" + ], + "operationId": "FirewallRules_Delete", + "x-ms-examples": { + "FirewallRuleDelete": { + "$ref": "./examples/FirewallRuleDelete.json" + } + }, + "description": "Deletes a server firewall rule.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/FirewallRuleNameParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "202": { + "description": "Accepted" + }, + "204": { + "description": "NoContent" + } + }, + "x-ms-long-running-operation": true + }, + "get": { + "tags": [ + "FirewallRules" + ], + "operationId": "FirewallRules_Get", + "x-ms-examples": { + "FirewallRuleGet": { + "$ref": "./examples/FirewallRuleGet.json" + } + }, + "description": "Gets information about a server firewall rule.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/FirewallRuleNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/FirewallRule" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/firewallRules": { + "get": { + "tags": [ + "FirewallRules" + ], + "operationId": "FirewallRules_ListByServer", + "x-ms-examples": { + "FirewallRuleList": { + "$ref": "./examples/FirewallRuleListByServer.json" + } + }, + "description": "List all the firewall rules in a given server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/FirewallRuleListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/virtualNetworkRules/{virtualNetworkRuleName}": { + "get": { + "tags": [ + "VirtualNetworkRules" + ], + "description": "Gets a virtual network rule.", + "operationId": "VirtualNetworkRules_Get", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/virtualNetworkRuleNameParameter" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved a specified virtual network rule.", + "schema": { + "$ref": "#/definitions/VirtualNetworkRule" + } + }, + "default": { + "description": "*** Error Responses: ***\n\n * 404 SubscriptionDoesNotHaveServer - The requested server was not found\n\n * 404 ResourceNotFound - The requested resource was not found." + } + }, + "x-ms-examples": { + "Gets a virtual network rule": { + "$ref": "./examples/VirtualNetworkRulesGet.json" + } + } + }, + "put": { + "tags": [ + "VirtualNetworkRules" + ], + "description": "Creates or updates an existing virtual network rule.", + "operationId": "VirtualNetworkRules_CreateOrUpdate", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/virtualNetworkRuleNameParameter" + }, + { + "name": "parameters", + "in": "body", + "description": "The requested virtual Network Rule Resource state.", + "required": true, + "schema": { + "$ref": "#/definitions/VirtualNetworkRule" + } + } + ], + "responses": { + "200": { + "description": "Successfully updated a virtual network rule.", + "schema": { + "$ref": "#/definitions/VirtualNetworkRule" + } + }, + "default": { + "description": "*** Error Responses: ***\n\n * 400 InvalidResourceId - Invalid resource identifier.\n\n * 400 MismatchingSubscriptionWithUrl - The provided subscription did not match the subscription in the Url.\n\n * 400 MismatchingResourceGroupNameWithUrl - The provided resource group name did not match the name in the Url.\n\n * 400 MismatchingServerNameWithUrl - The provided server name did not match the name in the Url.\n\n * 400 NullVirtualNetworkRequest - Virtual Network Request is Null\n\n * 400 NullVirtualNetworkRequestParameters - Virtual Network Request Parameters are Null\n\n * 400 NullVirtualNetworkSubnetId - The Virtual Network Subnet Id is null\n\n * 404 SubscriptionDoesNotHaveServer - The requested server was not found\n\n * 404 VirtualNetworkRuleNotEnabled - Azure SQL Server Virtual Network Rule feature is not enabled\n\n * 404 OperationIdNotFound - The operation with Id does not exist.\n\n * 409 OperationCancelled - The operation has been cancelled by user.\n\n * 409 OperationInterrupted - The operation on the resource could not be completed because it was interrupted by another operation on the same resource.\n\n * 500 OperationTimedOut - The operation timed out and automatically rolled back. Please retry the operation." + }, + "202": { + "description": "Accepted" + }, + "201": { + "description": "Successfully created a virtual network rule.", + "schema": { + "$ref": "#/definitions/VirtualNetworkRule" + } + } + }, + "x-ms-long-running-operation": true, + "x-ms-examples": { + "Create or update a virtual network rule": { + "$ref": "./examples/VirtualNetworkRulesCreateOrUpdate.json" + } + } + }, + "delete": { + "tags": [ + "VirtualNetworkRules" + ], + "description": "Deletes the virtual network rule with the given name.", + "operationId": "VirtualNetworkRules_Delete", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/virtualNetworkRuleNameParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Successfully deleted the virtual network rule." + }, + "default": { + "description": "*** Error Responses: ***\n\n * 400 InvalidResourceId - Invalid resource identifier.\n\n * 400 MismatchingSubscriptionWithUrl - The provided subscription did not match the subscription in the Url.\n\n * 400 MismatchingResourceGroupNameWithUrl - The provided resource group name did not match the name in the Url.\n\n * 400 MismatchingServerNameWithUrl - The provided server name did not match the name in the Url.\n\n * 400 NullVirtualNetworkRequest - Virtual Network Request is Null\n\n * 400 NullVirtualNetworkRequestParameters - Virtual Network Request Parameters are Null\n\n * 404 SubscriptionDoesNotHaveServer - The requested server was not found\n\n * 404 OperationIdNotFound - The operation with Id does not exist.\n\n * 409 OperationCancelled - The operation has been cancelled by user.\n\n * 409 OperationInterrupted - The operation on the resource could not be completed because it was interrupted by another operation on the same resource.\n\n * 500 OperationTimedOut - The operation timed out and automatically rolled back. Please retry the operation." + }, + "202": { + "description": "Accepted" + }, + "204": { + "description": "The specified virtual network rule does not exist." + } + }, + "x-ms-long-running-operation": true, + "x-ms-examples": { + "Delete a virtual network rule": { + "$ref": "./examples/VirtualNetworkRulesDelete.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/virtualNetworkRules": { + "get": { + "tags": [ + "VirtualNetworkRules" + ], + "description": "Gets a list of virtual network rules in a server.", + "operationId": "VirtualNetworkRules_ListByServer", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of virtual network rules.", + "schema": { + "$ref": "#/definitions/VirtualNetworkRuleListResult" + } + }, + "default": { + "description": "*** Error Responses: ***\n\n * 404 SubscriptionDoesNotHaveServer - The requested server was not found\n\n * 404 ResourceNotFound - The requested resource was not found." + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + }, + "x-ms-examples": { + "List virtual network rules": { + "$ref": "./examples/VirtualNetworkRulesList.json" + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/databases/{databaseName}": { + "put": { + "tags": [ + "Databases" + ], + "operationId": "Databases_CreateOrUpdate", + "x-ms-examples": { + "DatabaseCreate": { + "$ref": "./examples/DatabaseCreate.json" + } + }, + "description": "Creates a new database or updates an existing database.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/DatabaseNameParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Database" + }, + "description": "The required parameters for creating or updating a database." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Database" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/Database" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true + }, + "delete": { + "tags": [ + "Databases" + ], + "operationId": "Databases_Delete", + "x-ms-examples": { + "DatabaseDelete": { + "$ref": "./examples/DatabaseDelete.json" + } + }, + "description": "Deletes a database.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/DatabaseNameParameter" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "202": { + "description": "Accepted" + }, + "204": { + "description": "NoContent" + } + }, + "x-ms-long-running-operation": true + }, + "get": { + "tags": [ + "Databases" + ], + "operationId": "Databases_Get", + "x-ms-examples": { + "DatabaseGet": { + "$ref": "./examples/DatabaseGet.json" + } + }, + "description": "Gets information about a database.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/DatabaseNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Database" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/databases": { + "get": { + "tags": [ + "Databases" + ], + "operationId": "Databases_ListByServer", + "x-ms-examples": { + "DatabaseList": { + "$ref": "./examples/DatabaseListByServer.json" + } + }, + "description": "List all the databases in a given server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/DatabaseListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/configurations/{configurationName}": { + "put": { + "tags": [ + "Configurations" + ], + "operationId": "Configurations_CreateOrUpdate", + "x-ms-examples": { + "ConfigurationCreateOrUpdate": { + "$ref": "./examples/ConfigurationCreateOrUpdate.json" + } + }, + "description": "Updates a configuration of a server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/ConfigurationNameParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Configuration" + }, + "description": "The required parameters for updating a server configuration." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Configuration" + } + }, + "202": { + "description": "Accepted" + } + }, + "x-ms-long-running-operation": true + }, + "get": { + "tags": [ + "Configurations" + ], + "operationId": "Configurations_Get", + "x-ms-examples": { + "ConfigurationGet": { + "$ref": "./examples/ConfigurationGet.json" + } + }, + "description": "Gets information about a configuration of server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "$ref": "#/parameters/ConfigurationNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Configuration" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/configurations": { + "get": { + "tags": [ + "Configurations" + ], + "operationId": "Configurations_ListByServer", + "x-ms-examples": { + "ConfigurationList": { + "$ref": "./examples/ConfigurationListByServer.json" + } + }, + "description": "List all the configurations in a given server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ConfigurationListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/logFiles": { + "get": { + "tags": [ + "LogFiles" + ], + "operationId": "LogFiles_ListByServer", + "x-ms-examples": { + "LogFileList": { + "$ref": "./examples/LogFileListByServer.json" + } + }, + "description": "List all the log files in a given server.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/LogFileListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/Administrators/activeDirectory": { + "get": { + "tags": [ + "ServerAdministrators" + ], + "operationId": "ServerAdministrators_Get", + "x-ms-examples": { + "ServerAdministratorGet": { + "$ref": "./examples/ServerAdminGet.json" + } + }, + "description": "Gets information about a AAD server administrator.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ServerAdministratorResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "put": { + "tags": [ + "ServerAdministrators" + ], + "operationId": "ServerAdministrators_CreateOrUpdate", + "x-ms-examples": { + "ServerAdministratorCreate": { + "$ref": "./examples/ServerAdminCreateUpdate.json" + } + }, + "description": "Creates or update active directory administrator on an existing server. The update action will overwrite the existing administrator.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + }, + { + "name": "properties", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ServerAdministratorResource" + }, + "description": "The required parameters for creating or updating an AAD server administrator." + } + ], + "responses": { + "200": { + "description": "Successfully updated the active directory administrator", + "schema": { + "$ref": "#/definitions/ServerAdministratorResource" + } + }, + "202": { + "description": "Operation in progress", + "schema": { + "$ref": "#/definitions/ServerAdministratorResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-long-running-operation": true + }, + "delete": { + "tags": [ + "ServerAdministrators" + ], + "operationId": "ServerAdministrators_Delete", + "x-ms-examples": { + "ServerAdministratorsDelete": { + "$ref": "./examples/ServerAdminDelete.json" + } + }, + "description": "Deletes server active directory administrator.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "Successfully deleted the active directory administrator" + }, + "202": { + "description": "Operation in progress" + }, + "204": { + "description": "The specified Server active directory administrator does not exist" + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-long-running-operation": true + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DBforMySQL/servers/{serverName}/administrators": { + "get": { + "tags": [ + "ServerAdministrators" + ], + "operationId": "ServerAdministrators_List", + "description": "Returns a list of server Administrators.", + "x-ms-examples": { + "get a list of server administrators": { + "$ref": "./examples/ServerAdminList.json" + } + }, + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ServerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/ServerAdministratorResourceListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.DBforMySQL/locations/{locationName}/performanceTiers": { + "get": { + "tags": [ + "LocationBasedPerformanceTier" + ], + "operationId": "LocationBasedPerformanceTier_List", + "x-ms-examples": { + "PerformanceTiersList": { + "$ref": "./examples/PerformanceTiersListByLocation.json" + } + }, + "description": "List all the performance tiers at specified location in a given subscription.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/LocationNameParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/PerformanceTierListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": null + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.DBforMySQL/checkNameAvailability": { + "post": { + "tags": [ + "CheckNameAvailability" + ], + "operationId": "CheckNameAvailability_Execute", + "x-ms-examples": { + "NameAvailability": { + "$ref": "./examples/CheckNameAvailability.json" + } + }, + "description": "Check the availability of name for resource", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/SubscriptionIdParameter" + }, + { + "name": "nameAvailabilityRequest", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/NameAvailabilityRequest" + }, + "description": "The required parameters for checking if resource name is available." + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/NameAvailability" + } + } + } + } + }, + "/providers/Microsoft.DBforMySQL/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "x-ms-examples": { + "OperationList": { + "$ref": "./examples/OperationList.json" + } + }, + "description": "Lists all of the available REST API operations.", + "parameters": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/OperationListResult" + } + } + } + } + } + }, + "definitions": { + "ServerVersion": { + "type": "string", + "description": "The version of a server.", + "enum": [ + "5.6", + "5.7", + "8.0" + ], + "x-ms-enum": { + "name": "ServerVersion", + "modelAsString": false + } + }, + "SslEnforcement": { + "type": "string", + "description": "Enable ssl enforcement or not when connect to server.", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "SslEnforcementEnum", + "modelAsString": false + } + }, + "MinimalTlsVersion": { + "type": "string", + "description": "Enforce a minimal Tls version for the server.", + "enum": [ + "TLS1_0", + "TLS1_1", + "TLS1_2", + "TLSEnforcementDisabled" + ], + "x-ms-enum": { + "name": "MinimalTlsVersionEnum", + "modelAsString": false + } + }, + "InfrastructureEncryption": { + "type": "string", + "description": "Add a second layer of encryption for your data using new encryption algorithm which gives additional data protection. Value is optional but if passed in, must be 'Disabled' or 'Enabled'.", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "InfrastructureEncryption", + "modelAsString": false, + "values": [ + { + "value": "Enabled", + "description": "Default value for single layer of encryption for data at rest." + }, + { + "value": "Disabled", + "description": "Additional (2nd) layer of encryption for data at rest" + } + ] + } + }, + "PublicNetworkAccess": { + "type": "string", + "description": "Whether or not public network access is allowed for this server. Value is optional but if passed in, must be 'Enabled' or 'Disabled'", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "PublicNetworkAccessEnum", + "modelAsString": false + } + }, + "ServerPrivateEndpointConnection": { + "description": "A private endpoint connection under a server", + "type": "object", + "properties": { + "id": { + "description": "Resource Id of the private endpoint connection.", + "type": "string", + "readOnly": true + }, + "properties": { + "$ref": "#/definitions/ServerPrivateEndpointConnectionProperties", + "description": "Private endpoint connection properties", + "readOnly": true + } + } + }, + "ServerPrivateEndpointConnectionProperties": { + "description": "Properties of a private endpoint connection.", + "type": "object", + "properties": { + "privateEndpoint": { + "$ref": "#/definitions/PrivateEndpointProperty", + "description": "Private endpoint which the connection belongs to." + }, + "privateLinkServiceConnectionState": { + "$ref": "#/definitions/ServerPrivateLinkServiceConnectionStateProperty", + "description": "Connection state of the private endpoint connection." + }, + "provisioningState": { + "description": "State of the private endpoint connection.", + "enum": [ + "Approving", + "Ready", + "Dropping", + "Failed", + "Rejecting" + ], + "type": "string", + "readOnly": true, + "x-ms-enum": { + "name": "PrivateEndpointProvisioningState", + "modelAsString": false + } + } + } + }, + "PrivateEndpointProperty": { + "type": "object", + "properties": { + "id": { + "description": "Resource id of the private endpoint.", + "type": "string" + } + }, + "x-ms-azure-resource": true + }, + "ServerPrivateLinkServiceConnectionStateProperty": { + "required": [ + "status", + "description" + ], + "type": "object", + "properties": { + "status": { + "description": "The private link service connection status.", + "enum": [ + "Approved", + "Pending", + "Rejected", + "Disconnected" + ], + "type": "string", + "x-ms-enum": { + "name": "PrivateLinkServiceConnectionStateStatus", + "modelAsString": false + } + }, + "description": { + "description": "The private link service connection description.", + "type": "string" + }, + "actionsRequired": { + "description": "The actions required for private link service connection.", + "enum": [ + "None", + "app" + ], + "type": "string", + "readOnly": true, + "x-ms-enum": { + "name": "PrivateLinkServiceConnectionStateActionsRequire", + "modelAsString": false + } + } + } + }, + "TrackedResource": { + "description": "Resource properties including location and tags for track resources.", + "properties": { + "location": { + "type": "string", + "description": "The location the resource resides in." + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Application-specific metadata in the form of key-value pairs." + } + }, + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "required": [ + "location" + ] + }, + "ServerProperties": { + "properties": { + "administratorLogin": { + "type": "string", + "description": "The administrator's login name of a server. Can only be specified when the server is being created (and is required for creation)." + }, + "version": { + "$ref": "#/definitions/ServerVersion", + "description": "Server version." + }, + "sslEnforcement": { + "$ref": "#/definitions/SslEnforcement", + "description": "Enable ssl enforcement or not when connect to server." + }, + "minimalTlsVersion": { + "$ref": "#/definitions/MinimalTlsVersion", + "description": "Enforce a minimal Tls version for the server." + }, + "byokEnforcement": { + "type": "string", + "description": "Status showing whether the server data encryption is enabled with customer-managed keys.", + "readOnly": true + }, + "infrastructureEncryption": { + "$ref": "#/definitions/InfrastructureEncryption", + "description": "Status showing whether the server enabled infrastructure encryption." + }, + "userVisibleState": { + "type": "string", + "description": "A state of a server that is visible to user.", + "enum": [ + "Ready", + "Dropping", + "Disabled", + "Inaccessible" + ], + "x-ms-enum": { + "name": "ServerState", + "modelAsString": false + } + }, + "fullyQualifiedDomainName": { + "type": "string", + "description": "The fully qualified domain name of a server." + }, + "earliestRestoreDate": { + "type": "string", + "format": "date-time", + "description": "Earliest restore point creation time (ISO8601 format)" + }, + "storageProfile": { + "$ref": "#/definitions/StorageProfile", + "description": "Storage profile of a server." + }, + "replicationRole": { + "type": "string", + "description": "The replication role of the server." + }, + "masterServerId": { + "type": "string", + "description": "The master server id of a replica server." + }, + "replicaCapacity": { + "type": "integer", + "format": "int32", + "minimum": 0, + "description": "The maximum number of replicas that a master server can have." + }, + "publicNetworkAccess": { + "$ref": "#/definitions/PublicNetworkAccess", + "description": "Whether or not public network access is allowed for this server. Value is optional but if passed in, must be 'Enabled' or 'Disabled'" + }, + "privateEndpointConnections": { + "description": "List of private endpoint connections on a server", + "type": "array", + "items": { + "$ref": "#/definitions/ServerPrivateEndpointConnection" + }, + "readOnly": true + } + }, + "description": "The properties of a server." + }, + "StorageProfile": { + "properties": { + "backupRetentionDays": { + "type": "integer", + "description": "Backup retention days for the server." + }, + "geoRedundantBackup": { + "type": "string", + "description": "Enable Geo-redundant or not for server backup.", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "GeoRedundantBackup", + "modelAsString": false + } + }, + "storageMB": { + "type": "integer", + "format": "int32", + "description": "Max storage allowed for a server." + }, + "storageAutogrow": { + "type": "string", + "description": "Enable Storage Auto Grow.", + "enum": [ + "Enabled", + "Disabled" + ], + "x-ms-enum": { + "name": "StorageAutogrow", + "modelAsString": false + } + } + }, + "description": "Storage Profile properties of a server" + }, + "ServerPropertiesForCreate": { + "discriminator": "createMode", + "required": [ + "createMode" + ], + "properties": { + "version": { + "$ref": "#/definitions/ServerVersion", + "description": "Server version." + }, + "sslEnforcement": { + "$ref": "#/definitions/SslEnforcement", + "description": "Enable ssl enforcement or not when connect to server." + }, + "minimalTlsVersion": { + "$ref": "#/definitions/MinimalTlsVersion", + "description": "Enforce a minimal Tls version for the server." + }, + "infrastructureEncryption": { + "$ref": "#/definitions/InfrastructureEncryption", + "description": "Status showing whether the server enabled infrastructure encryption." + }, + "publicNetworkAccess": { + "$ref": "#/definitions/PublicNetworkAccess", + "description": "Whether or not public network access is allowed for this server. Value is optional but if passed in, must be 'Enabled' or 'Disabled'" + }, + "storageProfile": { + "$ref": "#/definitions/StorageProfile", + "description": "Storage profile of a server." + }, + "createMode": { + "type": "string", + "description": "The mode to create a new server.", + "enum": [ + "Default", + "PointInTimeRestore", + "GeoRestore", + "Replica" + ], + "x-ms-enum": { + "name": "CreateMode", + "modelAsString": false + } + } + }, + "description": "The properties used to create a new server." + }, + "ServerPropertiesForDefaultCreate": { + "x-ms-discriminator-value": "Default", + "allOf": [ + { + "$ref": "#/definitions/ServerPropertiesForCreate" + } + ], + "properties": { + "administratorLogin": { + "type": "string", + "description": "The administrator's login name of a server. Can only be specified when the server is being created (and is required for creation)." + }, + "administratorLoginPassword": { + "type": "string", + "format": "password", + "description": "The password of the administrator login." + } + }, + "required": [ + "administratorLogin", + "administratorLoginPassword" + ], + "description": "The properties used to create a new server." + }, + "ServerPropertiesForRestore": { + "x-ms-discriminator-value": "PointInTimeRestore", + "allOf": [ + { + "$ref": "#/definitions/ServerPropertiesForCreate" + } + ], + "properties": { + "sourceServerId": { + "type": "string", + "description": "The source server id to restore from." + }, + "restorePointInTime": { + "type": "string", + "format": "date-time", + "description": "Restore point creation time (ISO8601 format), specifying the time to restore from." + } + }, + "required": [ + "sourceServerId", + "restorePointInTime" + ], + "description": "The properties used to create a new server by restoring from a backup." + }, + "ServerPropertiesForGeoRestore": { + "x-ms-discriminator-value": "GeoRestore", + "allOf": [ + { + "$ref": "#/definitions/ServerPropertiesForCreate" + } + ], + "properties": { + "sourceServerId": { + "type": "string", + "description": "The source server id to restore from." + } + }, + "required": [ + "sourceServerId" + ], + "description": "The properties used to create a new server by restoring to a different region from a geo replicated backup." + }, + "ServerPropertiesForReplica": { + "x-ms-discriminator-value": "Replica", + "allOf": [ + { + "$ref": "#/definitions/ServerPropertiesForCreate" + } + ], + "properties": { + "sourceServerId": { + "type": "string", + "description": "The master server id to create replica from." + } + }, + "required": [ + "sourceServerId" + ], + "description": "The properties to create a new replica." + }, + "Sku": { + "properties": { + "name": { + "type": "string", + "description": "The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8." + }, + "tier": { + "type": "string", + "description": "The tier of the particular SKU, e.g. Basic.", + "enum": [ + "Basic", + "GeneralPurpose", + "MemoryOptimized" + ], + "x-ms-enum": { + "name": "SkuTier", + "modelAsString": false + } + }, + "capacity": { + "type": "integer", + "format": "int32", + "minimum": 0, + "description": "The scale up/out capacity, representing server's compute units." + }, + "size": { + "type": "string", + "description": "The size code, to be interpreted by resource as appropriate." + }, + "family": { + "type": "string", + "description": "The family of hardware." + } + }, + "description": "Billing information related properties of a server." + }, + "ResourceIdentity": { + "description": "Azure Active Directory identity configuration for a resource.", + "type": "object", + "properties": { + "principalId": { + "format": "uuid", + "description": "The Azure Active Directory principal id.", + "type": "string", + "readOnly": true + }, + "type": { + "description": "The identity type. Set this to 'SystemAssigned' in order to automatically create and assign an Azure Active Directory principal for the resource.", + "enum": [ + "SystemAssigned", + "app" + ], + "type": "string", + "x-ms-enum": { + "name": "IdentityType", + "modelAsString": false + } + }, + "tenantId": { + "format": "uuid", + "description": "The Azure Active Directory tenant id.", + "type": "string", + "readOnly": true + } + } + }, + "Server": { + "properties": { + "identity": { + "$ref": "#/definitions/ResourceIdentity", + "description": "The Azure Active Directory identity of the server." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The SKU (pricing tier) of the server." + }, + "properties": { + "$ref": "#/definitions/ServerProperties", + "x-ms-client-flatten": true, + "description": "Properties of the server." + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "Represents a server." + }, + "ServerForCreate": { + "properties": { + "identity": { + "$ref": "#/definitions/ResourceIdentity", + "description": "The Azure Active Directory identity of the server." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The SKU (pricing tier) of the server." + }, + "properties": { + "$ref": "#/definitions/ServerPropertiesForCreate", + "x-ms-client-flatten": false, + "description": "Properties of the server." + }, + "location": { + "type": "string", + "description": "The location the resource resides in." + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Application-specific metadata in the form of key-value pairs." + } + }, + "required": [ + "properties", + "location" + ], + "description": "Represents a server to be created." + }, + "ServerUpdateParameters": { + "properties": { + "identity": { + "$ref": "#/definitions/ResourceIdentity", + "description": "The Azure Active Directory identity of the server." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "The SKU (pricing tier) of the server." + }, + "properties": { + "properties": { + "storageProfile": { + "$ref": "#/definitions/StorageProfile", + "description": "Storage profile of a server." + }, + "administratorLoginPassword": { + "type": "string", + "format": "password", + "description": "The password of the administrator login." + }, + "version": { + "$ref": "#/definitions/ServerVersion", + "description": "The version of a server." + }, + "sslEnforcement": { + "$ref": "#/definitions/SslEnforcement", + "description": "Enable ssl enforcement or not when connect to server." + }, + "minimalTlsVersion": { + "$ref": "#/definitions/MinimalTlsVersion", + "description": "Enforce a minimal Tls version for the server." + }, + "publicNetworkAccess": { + "$ref": "#/definitions/PublicNetworkAccess", + "description": "Whether or not public network access is allowed for this server. Value is optional but if passed in, must be 'Enabled' or 'Disabled'" + }, + "replicationRole": { + "type": "string", + "description": "The replication role of the server." + } + }, + "x-ms-client-flatten": true, + "description": "The properties that can be updated for a server." + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Application-specific metadata in the form of key-value pairs." + } + }, + "description": "Parameters allowed to update for a server." + }, + "ServerListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Server" + }, + "description": "The list of servers" + } + }, + "description": "A list of servers." + }, + "FirewallRuleProperties": { + "properties": { + "startIpAddress": { + "type": "string", + "pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", + "description": "The start IP address of the server firewall rule. Must be IPv4 format." + }, + "endIpAddress": { + "type": "string", + "pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", + "description": "The end IP address of the server firewall rule. Must be IPv4 format." + } + }, + "required": [ + "startIpAddress", + "endIpAddress" + ], + "description": "The properties of a server firewall rule." + }, + "FirewallRule": { + "properties": { + "properties": { + "$ref": "#/definitions/FirewallRuleProperties", + "x-ms-client-flatten": true, + "description": "The properties of a firewall rule." + } + }, + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "required": [ + "properties" + ], + "description": "Represents a server firewall rule." + }, + "FirewallRuleListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/FirewallRule" + }, + "description": "The list of firewall rules in a server." + } + }, + "description": "A list of firewall rules." + }, + "VirtualNetworkRuleProperties": { + "description": "Properties of a virtual network rule.", + "required": [ + "virtualNetworkSubnetId" + ], + "type": "object", + "properties": { + "virtualNetworkSubnetId": { + "description": "The ARM resource id of the virtual network subnet.", + "type": "string" + }, + "ignoreMissingVnetServiceEndpoint": { + "description": "Create firewall rule before the virtual network has vnet service endpoint enabled.", + "type": "boolean" + }, + "state": { + "description": "Virtual Network Rule State", + "enum": [ + "Initializing", + "InProgress", + "Ready", + "Deleting", + "Unknown" + ], + "type": "string", + "readOnly": true, + "x-ms-enum": { + "name": "VirtualNetworkRuleState", + "modelAsString": false + } + } + } + }, + "VirtualNetworkRule": { + "description": "A virtual network rule.", + "type": "object", + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "properties": { + "properties": { + "$ref": "#/definitions/VirtualNetworkRuleProperties", + "description": "Resource properties.", + "x-ms-client-flatten": true + } + } + }, + "VirtualNetworkRuleListResult": { + "description": "A list of virtual network rules.", + "type": "object", + "properties": { + "value": { + "description": "Array of results.", + "type": "array", + "items": { + "$ref": "#/definitions/VirtualNetworkRule" + }, + "readOnly": true + }, + "nextLink": { + "description": "Link to retrieve next page of results.", + "type": "string", + "readOnly": true + } + } + }, + "DatabaseProperties": { + "properties": { + "charset": { + "type": "string", + "description": "The charset of the database." + }, + "collation": { + "type": "string", + "description": "The collation of the database." + } + }, + "description": "The properties of a database." + }, + "Database": { + "properties": { + "properties": { + "$ref": "#/definitions/DatabaseProperties", + "x-ms-client-flatten": true, + "description": "The properties of a database." + } + }, + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "description": "Represents a Database." + }, + "DatabaseListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Database" + }, + "description": "The list of databases housed in a server" + } + }, + "description": "A List of databases." + }, + "ConfigurationProperties": { + "properties": { + "value": { + "type": "string", + "description": "Value of the configuration." + }, + "description": { + "type": "string", + "readOnly": true, + "description": "Description of the configuration." + }, + "defaultValue": { + "type": "string", + "readOnly": true, + "description": "Default value of the configuration." + }, + "dataType": { + "type": "string", + "readOnly": true, + "description": "Data type of the configuration." + }, + "allowedValues": { + "type": "string", + "readOnly": true, + "description": "Allowed values of the configuration." + }, + "source": { + "type": "string", + "description": "Source of the configuration." + } + }, + "description": "The properties of a configuration." + }, + "Configuration": { + "properties": { + "properties": { + "$ref": "#/definitions/ConfigurationProperties", + "x-ms-client-flatten": true, + "description": "The properties of a configuration." + } + }, + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "description": "Represents a Configuration." + }, + "ConfigurationListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Configuration" + }, + "description": "The list of server configurations." + } + }, + "description": "A list of server configurations." + }, + "OperationDisplay": { + "properties": { + "provider": { + "type": "string", + "readOnly": true, + "description": "Operation resource provider name." + }, + "resource": { + "type": "string", + "readOnly": true, + "description": "Resource on which the operation is performed." + }, + "operation": { + "type": "string", + "readOnly": true, + "description": "Localized friendly name for the operation." + }, + "description": { + "type": "string", + "readOnly": true, + "description": "Operation description." + } + }, + "description": "Display metadata associated with the operation." + }, + "Operation": { + "properties": { + "name": { + "type": "string", + "readOnly": true, + "description": "The name of the operation being performed on this particular object." + }, + "display": { + "$ref": "#/definitions/OperationDisplay", + "readOnly": true, + "description": "The localized display information for this particular operation or action." + }, + "origin": { + "type": "string", + "readOnly": true, + "description": "The intended executor of the operation.", + "enum": [ + "NotSpecified", + "user", + "system" + ], + "x-ms-enum": { + "name": "OperationOrigin", + "modelAsString": false + } + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "object" + }, + "readOnly": true, + "x-ms-client-flatten": false, + "description": "Additional descriptions for the operation." + } + }, + "description": "REST API operation definition." + }, + "OperationListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Operation" + }, + "description": "The list of resource provider operations." + } + }, + "description": "A list of resource provider operations." + }, + "LogFileProperties": { + "properties": { + "sizeInKB": { + "type": "integer", + "format": "int64", + "description": "Size of the log file." + }, + "createdTime": { + "type": "string", + "readOnly": true, + "format": "date-time", + "description": "Creation timestamp of the log file." + }, + "lastModifiedTime": { + "type": "string", + "readOnly": true, + "format": "date-time", + "description": "Last modified timestamp of the log file." + }, + "type": { + "type": "string", + "description": "Type of the log file." + }, + "url": { + "type": "string", + "description": "The url to download the log file from." + } + }, + "description": "The properties of a log file." + }, + "LogFile": { + "properties": { + "name": { + "type": "string", + "description": "The name of the log file." + }, + "properties": { + "$ref": "#/definitions/LogFileProperties", + "x-ms-client-flatten": true, + "description": "The properties of the log file." + } + }, + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ], + "description": "Represents a log file." + }, + "LogFileListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/LogFile" + }, + "description": "The list of log files." + } + }, + "description": "A list of log files." + }, + "PerformanceTierServiceLevelObjectives": { + "properties": { + "id": { + "type": "string", + "description": "ID for the service level objective." + }, + "edition": { + "type": "string", + "description": "Edition of the performance tier." + }, + "vCore": { + "type": "integer", + "description": "vCore associated with the service level objective" + }, + "hardwareGeneration": { + "type": "string", + "description": "Hardware generation associated with the service level objective" + }, + "maxBackupRetentionDays": { + "type": "integer", + "description": "Maximum Backup retention in days for the performance tier edition" + }, + "minBackupRetentionDays": { + "type": "integer", + "description": "Minimum Backup retention in days for the performance tier edition" + }, + "maxStorageMB": { + "type": "integer", + "format": "int32", + "description": "Max storage allowed for a server." + }, + "minStorageMB": { + "type": "integer", + "format": "int32", + "description": "Max storage allowed for a server." + } + }, + "description": "Service level objectives for performance tier." + }, + "PerformanceTierProperties": { + "properties": { + "id": { + "type": "string", + "description": "ID of the performance tier." + }, + "serviceLevelObjectives": { + "type": "array", + "items": { + "$ref": "#/definitions/PerformanceTierServiceLevelObjectives" + }, + "description": "Service level objectives associated with the performance tier" + } + }, + "description": "Performance tier properties" + }, + "PerformanceTierListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/PerformanceTierProperties" + }, + "description": "The list of performance tiers" + } + }, + "description": "A list of performance tiers." + }, + "NameAvailabilityRequest": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "Resource name to verify." + }, + "type": { + "type": "string", + "description": "Resource type used for verification." + } + }, + "description": "Request from client to check resource name availability." + }, + "NameAvailability": { + "properties": { + "message": { + "type": "string", + "description": "Error Message." + }, + "nameAvailable": { + "type": "boolean", + "description": "Indicates whether the resource name is available." + }, + "reason": { + "type": "string", + "description": "Reason for name being unavailable." + } + }, + "description": "Represents a resource name availability." + }, + "CloudError": { + "x-ms-external": true, + "properties": { + "error": { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ErrorResponse" + } + }, + "description": "An error response from the Batch service." + }, + "ServerAdministratorProperties": { + "properties": { + "administratorType": { + "type": "string", + "description": "The type of administrator.", + "enum": [ + "ActiveDirectory", + "app" + ], + "x-ms-enum": { + "name": "AdministratorType" + } + }, + "login": { + "type": "string", + "description": "The server administrator login account name." + }, + "sid": { + "type": "string", + "description": "The server administrator Sid (Secure ID).", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "description": "The server Active Directory Administrator tenant id.", + "format": "uuid" + } + }, + "required": [ + "tenantId", + "administratorType", + "login", + "sid" + ], + "description": "The properties of an server Administrator." + }, + "ServerAdministratorResource": { + "properties": { + "properties": { + "$ref": "#/definitions/ServerAdministratorProperties", + "x-ms-client-flatten": true, + "description": "Properties of the server AAD administrator." + } + }, + "description": "Represents a and external administrator to be created.", + "allOf": [ + { + "$ref": "./common-types/resource-management/v1/types.json#/definitions/ProxyResource" + } + ] + }, + "ServerAdministratorResourceListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/ServerAdministratorResource" + }, + "description": "The list of server Active Directory Administrators for the server." + } + }, + "description": "The response to a list Active Directory Administrators request." + } + }, + "parameters": { + "ServerNameParameter": { + "name": "serverName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the server.", + "x-ms-parameter-location": "method" + }, + "FirewallRuleNameParameter": { + "name": "firewallRuleName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the server firewall rule.", + "x-ms-parameter-location": "method" + }, + "virtualNetworkRuleNameParameter": { + "name": "virtualNetworkRuleName", + "in": "path", + "description": "The name of the virtual network rule.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "DatabaseNameParameter": { + "name": "databaseName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the database.", + "x-ms-parameter-location": "method" + }, + "ConfigurationNameParameter": { + "name": "configurationName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the server configuration.", + "x-ms-parameter-location": "method" + }, + "LocationNameParameter": { + "name": "locationName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the location.", + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file diff --git a/tests-upgrade/mysql/readme.md b/tests-upgrade/mysql/readme.md new file mode 100644 index 00000000000..59a155a136f --- /dev/null +++ b/tests-upgrade/mysql/readme.md @@ -0,0 +1,139 @@ + +# Az.MySql +This directory contains the PowerShell module for the MySql service. + +--- +## Status +[![Az.MySql](https://img.shields.io/powershellgallery/v/Az.MySql.svg?style=flat-square&label=Az.MySql "Az.MySql")](https://www.powershellgallery.com/packages/Az.MySql/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.MySql`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g autorest@beta`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - ./mysql.json +module-version: 0.1.0 +title: MySQL +subject-prefix: 'MySQL' + +directive: + - from: mysql.json + where: $.definitions.VirtualNetworkRule + transform: $['required'] = ['properties'] + - where: + verb: Set + subject: Configuration$|FirewallRule$|VirtualNetworkRule$ + set: + verb: Update + - where: + verb: ^New$|^Set$|^Remove$|^Get|^Update$|^Invoke$ + subject: Database$|SecurityAlertPolicy$|Administrator$|LocationBasedPerformanceTier$|LogFile$|ExecuteCheckNameAvailability$ + hide: true + - where: + verb: New$|Update$ + subject: Server$ + hide: true + - where: + verb: New$ + variant: ^Create$ + hide: true + - where: + verb: New$ + variant: ^CreateViaIdentity + hide: true + - where: + verb: New$|Update$ + variant: ^(?!.*?Expanded) + hide: true + - where: + verb: New + subject: Configuration + hide: true + - where: + parameter-name: VirtualNetworkSubnetId + subject: VirtualNetworkRule + set: + parameter-name: SubnetId + - where: + model-name: Server + set: + format-table: + properties: + - Name + - Location + - AdministratorLogin + - Version + - StorageProfileStorageMb + - SkuName + - SkuSize + - SkuTier + - SslEnforcement + - where: + model-name: Configuration + set: + format-table: + properties: + - Name + - Value + - where: + model-name: FirewallRule + set: + format-table: + properties: + - Name + - StartIPAddress + - EndIPAddress + - where: + parameter-name: StorageProfileBackupRetentionDay + subject: Server + set: + parameter-description: Backup retention days for the server. Day count is between 7 and 35. + - from: source-file-csharp + where: $ + transform: $ = $.replace(/OperationOrigin System/, 'OperationOrigin System1'); + - from: source-file-csharp + where: $ + transform: $ = $.replace('internal Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.Api20171201.IServerPropertiesForCreate Property', 'public Microsoft.Azure.PowerShell.Cmdlets.MySql.Models.Api20171201.IServerPropertiesForCreate Property'); + - from: source-file-csharp + where: $ + transform: $ = $.replace('public int StorageProfileBackupRetentionDay', '[System.Management.Automation.ValidateRangeAttribute(7,35)]\n public int StorageProfileBackupRetentionDay'); +``` diff --git a/tests-upgrade/mysql/resources/readme.md b/tests-upgrade/mysql/resources/readme.md new file mode 100644 index 00000000000..937f07f8fec --- /dev/null +++ b/tests-upgrade/mysql/resources/readme.md @@ -0,0 +1,11 @@ +# Resources +This directory can contain any additional resources for module that are not required at runtime. This directory **does not** get packaged with the module. If you have assets for custom implementation, place them into the `..\custom` folder. + +## Info +- Modifiable: yes +- Generated: no +- Committed: yes +- Packaged: no + +## Purpose +Use this folder to put anything you want to keep around as part of the repository for the module, but is not something that is required for the module. For example, development files, packaged builds, or additional information. This is only intended to be used in repositories where the module's output directory is cleaned, but tangential resources for the module want to remain intact. \ No newline at end of file diff --git a/tests-upgrade/mysql/test/loadEnv.ps1 b/tests-upgrade/mysql/test/loadEnv.ps1 new file mode 100644 index 00000000000..c4ebf2e8310 --- /dev/null +++ b/tests-upgrade/mysql/test/loadEnv.ps1 @@ -0,0 +1,28 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- +$envFile = 'env.json' +if ($TestMode -eq 'live') { + $envFile = 'localEnv.json' +} + +if (Test-Path -Path (Join-Path $PSScriptRoot $envFile)) { + $envFilePath = Join-Path $PSScriptRoot $envFile +} else { + $envFilePath = Join-Path $PSScriptRoot '..\$envFile' +} +$env = @{} +if (Test-Path -Path $envFilePath) { + $env = Get-Content (Join-Path $PSScriptRoot $envFile) | ConvertFrom-Json + $PSDefaultParameterValues=@{"*:SubscriptionId"=$env.SubscriptionId; "*:Tenant"=$env.Tenant} +} \ No newline at end of file diff --git a/tests-upgrade/mysql/test/readme.md b/tests-upgrade/mysql/test/readme.md new file mode 100644 index 00000000000..7c752b4c8c4 --- /dev/null +++ b/tests-upgrade/mysql/test/readme.md @@ -0,0 +1,17 @@ +# Test +This directory contains the [Pester](https://www.powershellgallery.com/packages/Pester) tests to run for the module. We use Pester as it is the unofficial standard for PowerShell unit testing. Test stubs for custom cmdlets (created in `..\custom`) will be generated into this folder when `build-module.ps1` is ran. These test stubs will fail automatically, to indicate that tests should be written for custom cmdlets. + +## Info +- Modifiable: yes +- Generated: partial +- Committed: yes +- Packaged: no + +## Details +We allow three testing modes: *live*, *record*, and *playback*. These can be selected using the `-Live`, `-Record`, and `-Playback` switches respectively on the `test-module.ps1` script. This script will run through any `.Tests.ps1` scripts in the `test` folder. If you choose the *record* mode, it will create a `.Recording.json` file of the REST calls between the client and server. Then, when you choose *playback* mode, it will use the `.Recording.json` file to mock the communication between server and client. The *live* mode runs the same as the *record* mode; however, it doesn't create the `.Recording.json` file. + +## Purpose +Custom cmdlets generally encompass additional functionality not described in the REST specification, or combines functionality generated from the REST spec. To validate this functionality continues to operate as intended, creating tests that can be ran and re-ran against custom cmdlets is part of the framework. + +## Usage +To execute tests, run the `test-module.ps1`. To write tests, [this example](https://github.com/pester/Pester/blob/8b9cf4248315e44f1ac6673be149f7e0d7f10466/Examples/Planets/Get-Planet.Tests.ps1#L1) from the Pester repository is very useful for getting started. \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/.gitattributes b/tests-upgrade/mysql/tools/Resources/.gitattributes new file mode 100644 index 00000000000..2125666142e --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/.gitignore b/tests-upgrade/mysql/tools/Resources/.gitignore new file mode 100644 index 00000000000..649721c69ce --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/.gitignore @@ -0,0 +1,14 @@ +bin +obj +.vs +generated +internal +exports +custom/*.psm1 +test/*-TestResults.xml +/*.ps1 +/*.ps1xml +/*.psm1 +/*.snk +/*.csproj +/*.nuspec \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/custom/New-AzDeployment.ps1 b/tests-upgrade/mysql/tools/Resources/custom/New-AzDeployment.ps1 new file mode 100644 index 00000000000..4ece0d887e4 --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/custom/New-AzDeployment.ps1 @@ -0,0 +1,231 @@ +function New-AzDeployment { + [OutputType('Microsoft.Azure.PowerShell.Cmdlets.Resources.Models.Api20180501.IDeploymentExtended')] + [CmdletBinding(DefaultParameterSetName='CreateWithTemplateFileParameterFile', PositionalBinding=$false, SupportsShouldProcess, ConfirmImpact='Medium')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Description('You can provide the template and parameters directly in the request or link to JSON files.')] + param( + [Parameter(HelpMessage='The name of the deployment. If not provided, the name of the template file will be used. If a template file is not used, a random GUID will be used for the name.')] + [Alias('DeploymentName')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Path')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='deploymentName', Required, PossibleTypes=([System.String]), Description='The name of the deployment.')] + [System.String] + # The name of the deployment. If not provided, the name of the template file will be used. If a template file is not used, a random GUID will be used for the name. + ${Name}, + + [Parameter(Mandatory, HelpMessage='The ID of the target subscription.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Path')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='subscriptionId', Required, PossibleTypes=([System.String]), Description='The ID of the target subscription.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.DefaultInfo(Script='(Get-AzContext).Subscription.Id')] + [System.String] + # The ID of the target subscription. + ${SubscriptionId}, + + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterFile', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterJson', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterObject', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterFile', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterJson', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterObject', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterFile', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterJson', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterObject', Mandatory, HelpMessage='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Path')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='resourceGroupName', Required, PossibleTypes=([System.String]), Description='The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist.')] + [System.String] + # The name of the resource group to deploy the resources to. The name is case insensitive. The resource group must already exist. + ${ResourceGroupName}, + + [Parameter(ParameterSetName='CreateWithTemplateFileParameterFile', Mandatory, HelpMessage='Local path to the JSON template file.')] + [Parameter(ParameterSetName='CreateWithTemplateFileParameterJson', Mandatory, HelpMessage='Local path to the JSON template file.')] + [Parameter(ParameterSetName='CreateWithTemplateFileParameterObject', Mandatory, HelpMessage='Local path to the JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterFile', Mandatory, HelpMessage='Local path to the JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterJson', Mandatory, HelpMessage='Local path to the JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterObject', Mandatory, HelpMessage='Local path to the JSON template file.')] + [System.String] + # Local path to the JSON template file. + ${TemplateFile}, + + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterFile', Mandatory, HelpMessage='The string representation of the JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterJson', Mandatory, HelpMessage='The string representation of the JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterObject', Mandatory, HelpMessage='The string representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterFile', Mandatory, HelpMessage='The string representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterJson', Mandatory, HelpMessage='The string representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterObject', Mandatory, HelpMessage='The string representation of the JSON template.')] + [System.String] + # The string representation of the JSON template. + ${TemplateJson}, + + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterFile', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterFile', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterJson', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterJson', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterObject', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterObject', Mandatory, HelpMessage='The hashtable representation of the JSON template.')] + [System.Collections.Hashtable] + # The hashtable representation of the JSON template. + ${TemplateObject}, + + [Parameter(ParameterSetName='CreateWithTemplateFileParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterFile', Mandatory, HelpMessage='Local path to the parameter JSON template file.')] + [System.String] + # Local path to the parameter JSON template file. + ${TemplateParameterFile}, + + [Parameter(ParameterSetName='CreateWithTemplateFileParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterJson', Mandatory, HelpMessage='The string representation of the parameter JSON template.')] + [System.String] + # The string representation of the parameter JSON template. + ${TemplateParameterJson}, + + [Parameter(ParameterSetName='CreateWithTemplateFileParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateFileParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateJsonParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateJsonParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateWithTemplateObjectParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [Parameter(ParameterSetName='CreateRGWithTemplateObjectParameterObject', Mandatory, HelpMessage='The hashtable representation of the parameter JSON template.')] + [System.Collections.Hashtable] + # The hashtable representation of the parameter JSON template. + ${TemplateParameterObject}, + + [Parameter(Mandatory, HelpMessage='The mode that is used to deploy resources. This value can be either Incremental or Complete. In Incremental mode, resources are deployed without deleting existing resources that are not included in the template. In Complete mode, resources are deployed and existing resources in the resource group that are not included in the template are deleted. Be careful when using Complete mode as you may unintentionally delete resources.')] + [ArgumentCompleter([Microsoft.Azure.PowerShell.Cmdlets.Resources.Support.DeploymentMode])] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Body')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='mode', Required, PossibleTypes=([Microsoft.Azure.PowerShell.Cmdlets.Resources.Support.DeploymentMode]), Description='The mode that is used to deploy resources. This value can be either Incremental or Complete. In Incremental mode, resources are deployed without deleting existing resources that are not included in the template. In Complete mode, resources are deployed and existing resources in the resource group that are not included in the template are deleted. Be careful when using Complete mode as you may unintentionally delete resources.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Support.DeploymentMode] + # The mode that is used to deploy resources. This value can be either Incremental or Complete. In Incremental mode, resources are deployed without deleting existing resources that are not included in the template. In Complete mode, resources are deployed and existing resources in the resource group that are not included in the template are deleted. Be careful when using Complete mode as you may unintentionally delete resources. + ${Mode}, + + [Parameter(HelpMessage='Specifies the type of information to log for debugging. The permitted values are none, requestContent, responseContent, or both requestContent and responseContent separated by a comma. The default is none. When setting this value, carefully consider the type of information you are passing in during deployment. By logging information about the request or response, you could potentially expose sensitive data that is retrieved through the deployment operations.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Body')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='detailLevel', PossibleTypes=([System.String]), Description='Specifies the type of information to log for debugging. The permitted values are none, requestContent, responseContent, or both requestContent and responseContent separated by a comma. The default is none. When setting this value, carefully consider the type of information you are passing in during deployment. By logging information about the request or response, you could potentially expose sensitive data that is retrieved through the deployment operations.')] + [System.String] + # Specifies the type of information to log for debugging. The permitted values are none, requestContent, responseContent, or both requestContent and responseContent separated by a comma. The default is none. When setting this value, carefully consider the type of information you are passing in during deployment. By logging information about the request or response, you could potentially expose sensitive data that is retrieved through the deployment operations. + ${DeploymentDebugLogLevel}, + + [Parameter(HelpMessage='The location to store the deployment data.')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Body')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Runtime.Info(SerializedName='location', PossibleTypes=([System.String]), Description='The location to store the deployment data.')] + [System.String] + # The location to store the deployment data. + ${Location}, + + [Parameter(HelpMessage='The credentials, account, tenant, and subscription used for communication with Azure.')] + [Alias('AzureRMContext', 'AzureCredential')] + [ValidateNotNull()] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Azure')] + [System.Management.Automation.PSObject] + # The credentials, account, tenant, and subscription used for communication with Azure. + ${DefaultProfile}, + + [Parameter(HelpMessage='Run the command as a job')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + # Run the command as a job + ${AsJob}, + + [Parameter(HelpMessage='Run the command asynchronously')] + [Microsoft.Azure.PowerShell.Cmdlets.Resources.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + # Run the command asynchronously + ${NoWait} + + ) + + process { + if ($PSBoundParameters.ContainsKey("TemplateFile")) + { + if (!(Test-Path -Path $TemplateFile)) + { + throw "Unable to find template file '$TemplateFile'." + } + + if (!$PSBoundParameters.ContainsKey("Name")) + { + $DeploymentName = (Get-Item -Path $TemplateFile).BaseName + $null = $PSBoundParameters.Add("Name", $DeploymentName) + } + + $TemplateJson = [System.IO.File]::ReadAllText($TemplateFile) + $null = $PSBoundParameters.Add("Template", $TemplateJson) + $null = $PSBoundParameters.Remove("TemplateFile") + } + elseif ($PSBoundParameters.ContainsKey("TemplateJson")) + { + $null = $PSBoundParameters.Add("Template", $TemplateJson) + $null = $PSBoundParameters.Remove("TemplateJson") + } + elseif ($PSBoundParameters.ContainsKey("TemplateObject")) + { + $TemplateJson = ConvertTo-Json -InputObject $TemplateObject + $null = $PSBoundParameters.Add("Template", $TemplateJson) + $null = $PSBoundParameters.Remove("TemplateObject") + } + + if ($PSBoundParameters.ContainsKey("TemplateParameterFile")) + { + if (!(Test-Path -Path $TemplateParameterFile)) + { + throw "Unable to find template parameter file '$TemplateParameterFile'." + } + + $ParameterJson = [System.IO.File]::ReadAllText($TemplateParameterFile) + $ParameterObject = ConvertFrom-Json -InputObject $ParameterJson + $ParameterHashtable = @{} + $ParameterObject.PSObject.Properties | ForEach-Object { $ParameterHashtable[$_.Name] = $_.Value } + $ParameterHashtable.Remove("`$schema") + $ParameterHashtable.Remove("contentVersion") + $NestedValues = $ParameterHashtable.parameters + if ($null -ne $NestedValues) + { + $ParameterHashtable.Remove("parameters") + $NestedValues.PSObject.Properties | ForEach-Object { $ParameterHashtable[$_.Name] = $_.Value } + } + + $ParameterJson = ConvertTo-Json -InputObject $ParameterHashtable + $null = $PSBoundParameters.Add("DeploymentPropertyParameter", $ParameterJson) + $null = $PSBoundParameters.Remove("TemplateParameterFile") + } + elseif ($PSBoundParameters.ContainsKey("TemplateParameterJson")) + { + $null = $PSBoundParameters.Add("DeploymentPropertyParameter", $TemplateParameterJson) + $null = $PSBoundParameters.Remove("TemplateParameterJson") + } + elseif ($PSBoundParameters.ContainsKey("TemplateParameterObject")) + { + $TemplateParameterObject.Remove("`$schema") + $TemplateParameterObject.Remove("contentVersion") + $NestedValues = $TemplateParameterObject.parameters + if ($null -ne $NestedValues) + { + $TemplateParameterObject.Remove("parameters") + $NestedValues.PSObject.Properties | ForEach-Object { $TemplateParameterObject[$_.Name] = $_.Value } + } + + $TemplateParameterJson = ConvertTo-Json -InputObject $TemplateParameterObject + $null = $PSBoundParameters.Add("DeploymentPropertyParameter", $TemplateParameterJson) + $null = $PSBoundParameters.Remove("TemplateParameterObject") + } + + if (!$PSBoundParameters.ContainsKey("Name")) + { + $DeploymentName = (New-Guid).Guid + $null = $PSBoundParameters.Add("Name", $DeploymentName) + } + + if ($PSBoundParameters.ContainsKey("ResourceGroupName")) + { + Az.Resources.TestSupport.private\New-AzDeployment_CreateExpanded @PSBoundParameters + } + else + { + Az.Resources.TestSupport.private\New-AzDeployment_CreateExpanded @PSBoundParameters + } + } +} \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/docs/readme.md b/tests-upgrade/mysql/tools/Resources/docs/readme.md new file mode 100644 index 00000000000..95fb0e21daf --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/docs/readme.md @@ -0,0 +1,11 @@ +# Docs +This directory contains the documentation of the cmdlets for the `Az.Resources` module. To run documentation generation, use the `generate-help.ps1` script at the root module folder. Files in this folder will *always be overriden on regeneration*. To update documentation examples, please use the `..\examples` folder. + +## Info +- Modifiable: no +- Generated: all +- Committed: yes +- Packaged: yes + +## Details +The process of documentation generation loads `Az.Resources` and analyzes the exported cmdlets from the module. It recognizes the [help comments](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help) that are generated into the scripts in the `..\exports` folder. Additionally, when writing custom cmdlets in the `..\custom` folder, you can use the help comments syntax, which decorate the exported scripts at build-time. The documentation examples are taken from the `..\examples` folder. \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/examples/readme.md b/tests-upgrade/mysql/tools/Resources/examples/readme.md new file mode 100644 index 00000000000..ac871d71fc7 --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/examples/readme.md @@ -0,0 +1,11 @@ +# Examples +This directory contains examples from the exported cmdlets of the module. When `build-module.ps1` is ran, example stub files will be generated here. If your module support Azure Profiles, the example stubs will be in individual profile folders. These example stubs should be updated to show how the cmdlet is used. The examples are imported into the documentation when `generate-help.ps1` is ran. + +## Info +- Modifiable: yes +- Generated: partial +- Committed: yes +- Packaged: no + +## Purpose +This separates the example documentation details from the generated documentation information provided directly from the generated cmdlets. Since the cmdlets don't have examples from the REST spec, this provides a means to add examples easily. The example stubs provide the markdown format that is required. The 3 core elements are: the name of the example, the code information of the example, and the description of the example. That information, if the markdown format is followed, will be available to documentation generation and be part of the documents in the `..\docs` folder. \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/how-to.md b/tests-upgrade/mysql/tools/Resources/how-to.md new file mode 100644 index 00000000000..c4daf2b254c --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/how-to.md @@ -0,0 +1,58 @@ +# How-To +This document describes how to develop for `Az.Resources`. + +## Building `Az.Resources` +To build, run the `build-module.ps1` at the root of the module directory. This will generate the proxy script cmdlets that are the cmdlets being exported by this module. After the build completes, the proxy script cmdlets will be output to the `exports` folder. To read more about the proxy script cmdlets, look at the [readme.md](exports/readme.md) in the `exports` folder. + +## Creating custom cmdlets +To add cmdlets that were not generated by the REST specification, use the `custom` folder. This folder allows you to add handwritten `.ps1` and `.cs` files. Currently, we support using `.ps1` scripts as new cmdlets or as additional low-level variants (via `ParameterSet`), and `.cs` files as low-level (variants) cmdlets that the exported script cmdlets call. We do not support exporting any `.cs` (dll) cmdlets directly. To read more about custom cmdlets, look at the [readme.md](custom/readme.md) in the `custom` folder. + +## Generating documentation +To generate documentation, the process is now integrated into the `build-module.ps1` script. If you don't want to run this process as part of `build-module.ps1`, you can provide the `-NoDocs` switch. If you want to run documentation generation after the build process, you may still run the `generate-help.ps1` script. Overall, the process will look at the documentation comments in the generated and custom cmdlets and types, and create `.md` files into the `docs` folder. Additionally, this pulls in any examples from the `examples` folder and adds them to the generated help markdown documents. To read more about examples, look at the [readme.md](examples/readme.md) in the `examples` folder. To read more about documentation, look at the [readme.md](docs/readme.md) in the `docs` folder. + +## Testing `Az.Resources` +To test the cmdlets, we use [Pester](https://github.com/pester/Pester). Tests scripts (`.ps1`) should be added to the `test` folder. To execute the Pester tests, run the `test-module.ps1` script. This will run all tests in `playback` mode within the `test` folder. To read more about testing cmdlets, look at the [readme.md](examples/readme.md) in the `examples` folder. + +## Packing `Az.Resources` +To pack `Az.Resources` for distribution, run the `pack-module.ps1` script. This will take the contents of multiple directories and certain root-folder files to create a `.nupkg`. The structure of the `.nupkg` is created so it can be loaded part of a [PSRepository](https://docs.microsoft.com/en-us/powershell/module/powershellget/register-psrepository). Additionally, this package is in a format for distribution to the [PSGallery](https://www.powershellgallery.com/). For signing an Azure module, please contact the [Azure PowerShell](https://github.com/Azure/azure-powershell) team. + +## Module Script Details +There are multiple scripts created for performing different actions for developing `Az.Resources`. +- `build-module.ps1` + - Builds the module DLL (`./bin/Az.Resources.private.dll`), creates the exported cmdlets and documentation, generates custom cmdlet test stubs and exported cmdlet example stubs, and updates `./Az.Resources.psd1` with Azure profile information. + - **Parameters**: [`Switch` parameters] + - `-Run`: After building, creates an isolated PowerShell session and loads `Az.Resources`. + - `-Test`: After building, runs the `Pester` tests defined in the `test` folder. + - `-Docs`: After building, generates the Markdown documents for the modules into the `docs` folder. + - `-Pack`: After building, packages the module into a `.nupkg`. + - `-Code`: After building, opens a VSCode window with the module's directory and runs (see `-Run`) the module. + - `-Release`: Builds the module in `Release` configuration (as opposed to `Debug` configuration). + - `-NoDocs`: Supresses writing the documentation markdown files as part of the cmdlet exporting process. + - `-Debugger`: Used when attaching the debugger in Visual Studio to the PowerShell session, and running the build process without recompiling the DLL. This suppresses running the script as an isolated process. +- `run-module.ps1` + - Creates an isolated PowerShell session and loads `Az.Resources` into the session. + - Same as `-Run` in `build-module.ps1`. + - **Parameters**: [`Switch` parameters] + - `-Code`: Opens a VSCode window with the module's directory. + - Same as `-Code` in `build-module.ps1`. +- `generate-help.ps1` + - Generates the Markdown documents for the modules into the `docs` folder. + - Same as `-Docs` in `build-module.ps1`. +- `test-module.ps1` + - Runs the `Pester` tests defined in the `test` folder. + - Same as `-Test` in `build-module.ps1`. +- `pack-module.ps1` + - Packages the module into a `.nupkg` for distribution. + - Same as `-Pack` in `build-module.ps1`. +- `generate-help.ps1` + - Generates the Markdown documents for the modules into the `docs` folder. + - Same as `-Docs` in `build-module.ps1`. + - This process is now integrated into `build-module.ps1` automatically. To disable, use `-NoDocs` when running `build-module.ps1`. +- `export-surface.ps1` + - Generates Markdown documents for both the cmdlet surface and the model (class) surface of the module. + - These files are placed into the `resources` folder. + - Used for investigating the surface of your module. These are *not* documentation for distribution. +- `check-dependencies.ps1` + - Used in `run-module.ps1` and `test-module.ps1` to verify dependent modules are available to run those tasks. + - It will download local (within the module's directory structure) versions of those modules as needed. + - This script *does not* need to be ran by-hand. \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/license.txt b/tests-upgrade/mysql/tools/Resources/license.txt new file mode 100644 index 00000000000..3d3f8f90d5d --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/license.txt @@ -0,0 +1,203 @@ +MICROSOFT SOFTWARE LICENSE TERMS + +MICROSOFT AZURE POWERSHELL + +These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. + +BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE. + + +-----------------START OF LICENSE-------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +-------------------END OF LICENSE------------------------------------------ + + +----------------START OF THIRD PARTY NOTICE-------------------------------- + +The software includes Newtonsoft.Json. The MIT License set out below is provided for informational purposes only. It is not the license that governs any part of the software. + +Newtonsoft.Json + +The MIT License (MIT) +Copyright (c) 2007 James Newton-King +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------END OF THIRD PARTY NOTICE---------------------------------------- + diff --git a/tests-upgrade/mysql/tools/Resources/readme.md b/tests-upgrade/mysql/tools/Resources/readme.md new file mode 100644 index 00000000000..aa61ef906c4 --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/readme.md @@ -0,0 +1,440 @@ + +# Az.Resources.TestSupport +This directory contains the PowerShell module for the Resources service. + +--- +## Status +[![Az.Resources.TestSupport](https://img.shields.io/powershellgallery/v/Az.Resources.TestSupport.svg?style=flat-square&label=Az.Resources.TestSupport "Az.Resources.TestSupport")](https://www.powershellgallery.com/packages/Az.Resources.TestSupport/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.Resources.TestSupport`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g @autorest/autorest`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +> Values +``` yaml +azure: true +powershell: true +branch: master +repo: https://github.com/Azure/azure-rest-api-specs/blob/master +metadata: + authors: Microsoft Corporation + owners: Microsoft Corporation + copyright: Microsoft Corporation. All rights reserved. + companyName: Microsoft Corporation + requireLicenseAcceptance: true + licenseUri: https://aka.ms/azps-license + projectUri: https://github.com/Azure/azure-powershell +``` + +> Names +``` yaml +prefix: Az +``` + +> Folders +``` yaml +clear-output-folder: true +``` + +``` yaml +input-file: + - https://github.com/Azure/azure-rest-api-specs/blob/master/specification/resources/resource-manager/Microsoft.Resources/stable/2018-05-01/resources.json +module-name: Az.Resources.TestSupport +namespace: Microsoft.Azure.PowerShell.Cmdlets.Resources + +subject-prefix: '' +module-version: 0.0.1 +title: Resources + +directive: + - where: + subject: Operation + hide: true + - where: + parameter-name: SubscriptionId + set: + default: + script: '(Get-AzContext).Subscription.Id' + - from: swagger-document + where: $..parameters[?(@.name=='$filter')] + transform: $['x-ms-skip-url-encoding'] = true + - from: swagger-document + where: $..[?( /Resources_(CreateOrUpdate|Update|Delete|Get|GetById|CheckExistence|CheckExistenceById)/g.exec(@.operationId))] + transform: "$.parameters = $.parameters.map( each => { each.name = each.name === 'api-version' ? 'explicit-api-version' : each.name; return each; } );" + - from: source-file-csharp + where: $ + transform: $ = $.replace(/explicit-api-version/g, 'api-version'); + - where: + parameter-name: ExplicitApiVersion + set: + parameter-name: ApiVersion + - from: source-file-csharp + where: $ + transform: > + $ = $.replace(/result.OdataNextLink/g,'nextLink' ); + return $.replace( /(^\s*)(if\s*\(\s*nextLink\s*!=\s*null\s*\))/gm, '$1var nextLink = Module.Instance.FixNextLink(responseMessage, result.OdataNextLink);\n$1$2' ); + - from: swagger-document + where: + - $..DeploymentProperties.properties.template + - $..DeploymentProperties.properties.parameters + - $..ResourceGroupExportResult.properties.template + - $..PolicyDefinitionProperties.properties.policyRule + transform: $.additionalProperties = true; + - where: + verb: Set + subject: Resource + remove: true + - where: + verb: Set + subject: Deployment + remove: true + - where: + subject: Resource + parameter-name: GroupName + set: + parameter-name: ResourceGroupName + clear-alias: true + - where: + subject: Resource + parameter-name: Id + set: + parameter-name: ResourceId + clear-alias: true + - where: + subject: Resource + parameter-name: Type + set: + parameter-name: ResourceType + clear-alias: true + - where: + subject: Appliance* + remove: true + - where: + verb: Test + subject: CheckNameAvailability + set: + subject: NameAvailability + - where: + verb: Export + subject: ResourceGroupTemplate + set: + subject: ResourceGroup + alias: Export-AzResourceGroupTemplate + - where: + parameter-name: Filter + set: + alias: ODataQuery + - where: + verb: Test + subject: ResourceGroupExistence + set: + subject: ResourceGroup + alias: Test-AzResourceGroupExistence + - where: + verb: Export + subject: DeploymentTemplate + set: + alias: [Save-AzDeploymentTemplate, Save-AzResourceGroupDeploymentTemplate] + - where: + subject: Deployment + set: + alias: ${verb}-AzResourceGroupDeployment + - where: + verb: Get + subject: DeploymentOperation + set: + alias: Get-AzResourceGroupDeploymentOperation + - where: + verb: New + subject: Deployment + variant: Create.*Expanded.* + parameter-name: Parameter + set: + parameter-name: DeploymentPropertyParameter + - where: + verb: New + subject: Deployment + hide: true + - where: + verb: Test + subject: Deployment + variant: Validate.*Expanded.* + parameter-name: Parameter + set: + parameter-name: DeploymentPropertyParameter + - where: + verb: New + subject: Deployment + parameter-name: DebugSettingDetailLevel + set: + parameter-name: DeploymentDebugLogLevel + - where: + subject: Provider + set: + subject: ResourceProvider + - where: + subject: ProviderFeature|ResourceProvider|ResourceLock + parameter-name: ResourceProviderNamespace + set: + alias: ProviderNamespace + - where: + verb: Update + subject: ResourceGroup + parameter-name: Name + clear-alias: true + - where: + parameter-name: UpnOrObjectId + set: + alias: ['UserPrincipalName', 'Upn', 'ObjectId'] + - where: + subject: Deployment + variant: (.*)Expanded(.*) + parameter-name: Parameter + set: + parameter-name: DeploymentParameter + # Format output + - where: + model-name: GenericResource + set: + format-table: + properties: + - Name + - ResourceGroupName + - Type + - Location + labels: + Type: ResourceType + - where: + model-name: ResourceGroup + set: + format-table: + properties: + - Name + - Location + - ProvisioningState + - where: + model-name: DeploymentExtended + set: + format-table: + properties: + - Name + - ProvisioningState + - Timestamp + - Mode + - where: + model-name: PolicyAssignment + set: + format-table: + properties: + - Name + - DisplayName + - Id + - where: + model-name: PolicyDefinition + set: + format-table: + properties: + - Name + - DisplayName + - Id + - where: + model-name: PolicySetDefinition + set: + format-table: + properties: + - Name + - DisplayName + - Id + - where: + model-name: Provider + set: + format-table: + properties: + - Namespace + - RegistrationState + - where: + model-name: ProviderResourceType + set: + format-table: + properties: + - ResourceType + - Location + - ApiVersion + - where: + model-name: FeatureResult + set: + format-table: + properties: + - Name + - State + - where: + model-name: TagDetails + set: + format-table: + properties: + - TagName + - CountValue + - where: + model-name: Application + set: + format-table: + properties: + - DisplayName + - ObjectId + - AppId + - Homepage + - AvailableToOtherTenant + - where: + model-name: KeyCredential + set: + format-table: + properties: + - StartDate + - EndDate + - KeyId + - Type + - where: + model-name: PasswordCredential + set: + format-table: + properties: + - StartDate + - EndDate + - KeyId + - where: + model-name: User + set: + format-table: + properties: + - PrincipalName + - DisplayName + - ObjectId + - Type + - where: + model-name: AdGroup + set: + format-table: + properties: + - DisplayName + - Mail + - ObjectId + - SecurityEnabled + - where: + model-name: ServicePrincipal + set: + format-table: + properties: + - DisplayName + - ObjectId + - AppDisplayName + - AppId + - where: + model-name: Location + set: + format-table: + properties: + - Name + - DisplayName + - where: + model-name: ManagementLockObject + set: + format-table: + properties: + - Name + - Level + - ResourceId + - where: + model-name: RoleAssignment + set: + format-table: + properties: + - DisplayName + - ObjectId + - ObjectType + - RoleDefinitionName + - Scope + - where: + model-name: RoleDefinition + set: + format-table: + properties: + - RoleName + - Name + - Action +# To remove cmdlets not used in the test frame + - where: + subject: Operation + remove: true + - where: + subject: Deployment + variant: (.*)1|Cancel(.*)|Validate(.*)|Export(.*)|List(.*)|Delete(.*)|Check(.*)|Calculate(.*) + remove: true + - where: + subject: ResourceProvider + variant: Register(.*)|Unregister(.*)|Get(.*) + remove: true + - where: + subject: ResourceGroup + variant: List(.*)|Update(.*)|Export(.*)|Move(.*) + remove: true + - where: + subject: Resource + remove: true + - where: + subject: Tag|TagValue + remove: true + - where: + subject: DeploymentOperation + remove: true + - where: + subject: DeploymentTemplate + remove: true + - where: + subject: Calculate(.*) + remove: true + - where: + subject: ResourceExistence + remove: true + - where: + subject: ResourceMoveResource + remove: true + - where: + subject: DeploymentExistence + remove: true +``` diff --git a/tests-upgrade/mysql/tools/Resources/resources/CmdletSurface-latest-2019-04-30.md b/tests-upgrade/mysql/tools/Resources/resources/CmdletSurface-latest-2019-04-30.md new file mode 100644 index 00000000000..278ea694e0f --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/resources/CmdletSurface-latest-2019-04-30.md @@ -0,0 +1,598 @@ +### AzADApplication [Get, New, Remove, Update] `IApplication, Boolean` + - TenantId `String` + - ObjectId `String` + - IncludeDeleted `SwitchParameter` + - InputObject `IResourcesIdentity` + - HardDelete `SwitchParameter` + - Filter `String` + - IdentifierUri `String` + - DisplayNameStartWith `String` + - DisplayName `String` + - ApplicationId `String` + - AllowGuestsSignIn `SwitchParameter` + - AllowPassthroughUser `SwitchParameter` + - AppLogoUrl `String` + - AppPermission `String[]` + - AppRole `IAppRole[]` + - AvailableToOtherTenants `SwitchParameter` + - ErrorUrl `String` + - GroupMembershipClaim `GroupMembershipClaimTypes` + - Homepage `String` + - InformationalUrlMarketing `String` + - InformationalUrlPrivacy `String` + - InformationalUrlSupport `String` + - InformationalUrlTermsOfService `String` + - IsDeviceOnlyAuthSupported `SwitchParameter` + - KeyCredentials `IKeyCredential[]` + - KnownClientApplication `String[]` + - LogoutUrl `String` + - Oauth2AllowImplicitFlow `SwitchParameter` + - Oauth2AllowUrlPathMatching `SwitchParameter` + - Oauth2Permission `IOAuth2Permission[]` + - Oauth2RequirePostResponse `SwitchParameter` + - OptionalClaimAccessToken `IOptionalClaim[]` + - OptionalClaimIdToken `IOptionalClaim[]` + - OptionalClaimSamlToken `IOptionalClaim[]` + - OrgRestriction `String[]` + - PasswordCredentials `IPasswordCredential[]` + - PreAuthorizedApplication `IPreAuthorizedApplication[]` + - PublicClient `SwitchParameter` + - PublisherDomain `String` + - ReplyUrl `String[]` + - RequiredResourceAccess `IRequiredResourceAccess[]` + - SamlMetadataUrl `String` + - SignInAudience `String` + - WwwHomepage `String` + - Parameter `IApplicationCreateParameters` + - PassThru `SwitchParameter` + - AvailableToOtherTenant `SwitchParameter` + +### AzADApplicationOwner [Add, Get, Remove] `Boolean, IDirectoryObject` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + - OwnerObjectId `String` + - AdditionalProperties `Hashtable` + - Url `String` + - Parameter `IAddOwnerParameters` + +### AzADDeletedApplication [Restore] `IApplication` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + +### AzADGroup [Get, New, Remove] `IAdGroup, Boolean` + - TenantId `String` + - ObjectId `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - DisplayNameStartsWith `String` + - DisplayName `String` + - AdditionalProperties `Hashtable` + - MailNickname `String` + - Parameter `IGroupCreateParameters` + - PassThru `SwitchParameter` + +### AzADGroupMember [Add, Get, Remove, Test] `Boolean, IDirectoryObject, SwitchParameter` + - GroupObjectId `String` + - TenantId `String` + - MemberObjectId `String[]` + - MemberUserPrincipalName `String[]` + - GroupObject `IAdGroup` + - GroupDisplayName `String` + - InputObject `IResourcesIdentity` + - ObjectId `String` + - ShowOwner `SwitchParameter` + - PassThru `SwitchParameter` + - AdditionalProperties `Hashtable` + - Url `String` + - Parameter `IGroupAddMemberParameters` + - DisplayName `String` + - GroupId `String` + - MemberId `String` + +### AzADGroupMemberGroup [Get] `String` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + - AdditionalProperties `Hashtable` + - SecurityEnabledOnly `SwitchParameter` + - Parameter `IGroupGetMemberGroupsParameters` + +### AzADGroupOwner [Add, Remove] `Boolean` + - ObjectId `String` + - TenantId `String` + - GroupObjectId `String` + - MemberObjectId `String[]` + - InputObject `IResourcesIdentity` + - OwnerObjectId `String` + - PassThru `SwitchParameter` + - AdditionalProperties `Hashtable` + - Url `String` + - Parameter `IAddOwnerParameters` + +### AzADObject [Get] `IDirectoryObject` + - TenantId `String` + - InputObject `IResourcesIdentity` + - AdditionalProperties `Hashtable` + - IncludeDirectoryObjectReference `SwitchParameter` + - ObjectId `String[]` + - Type `String[]` + - Parameter `IGetObjectsParameters` + +### AzADServicePrincipal [Get, New, Remove, Update] `IServicePrincipal, Boolean` + - TenantId `String` + - ObjectId `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - ApplicationObject `IApplication` + - ServicePrincipalName `String` + - DisplayNameBeginsWith `String` + - DisplayName `String` + - ApplicationId `String` + - AccountEnabled `SwitchParameter` + - AppId `String` + - AppRoleAssignmentRequired `SwitchParameter` + - KeyCredentials `IKeyCredential[]` + - PasswordCredentials `IPasswordCredential[]` + - ServicePrincipalType `String` + - Tag `String[]` + - Parameter `IServicePrincipalCreateParameters` + - PassThru `SwitchParameter` + +### AzADServicePrincipalOwner [Get] `IDirectoryObject` + - ObjectId `String` + - TenantId `String` + +### AzADUser [Get, New, Remove, Update] `IUser, Boolean` + - TenantId `String` + - UpnOrObjectId `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - DisplayName `String` + - StartsWith `String` + - Mail `String` + - MailNickname `String` + - Parameter `IUserCreateParameters` + - AccountEnabled `SwitchParameter` + - GivenName `String` + - ImmutableId `String` + - PasswordProfile `IPasswordProfile` + - Surname `String` + - UsageLocation `String` + - UserPrincipalName `String` + - UserType `UserType` + - PassThru `SwitchParameter` + - EnableAccount `SwitchParameter` + +### AzADUserMemberGroup [Get] `String` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + - AdditionalProperties `Hashtable` + - SecurityEnabledOnly `SwitchParameter` + - Parameter `IUserGetMemberGroupsParameters` + +### AzApplicationKeyCredentials [Get, Update] `IKeyCredential, Boolean` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + - Parameter `IKeyCredentialsUpdateParameters` + - Value `IKeyCredential[]` + +### AzApplicationPasswordCredentials [Get, Update] `IPasswordCredential, Boolean` + - ObjectId `String` + - TenantId `String` + - InputObject `IResourcesIdentity` + - Parameter `IPasswordCredentialsUpdateParameters` + - Value `IPasswordCredential[]` + +### AzAuthorizationOperation [Get] `IOperation` + +### AzClassicAdministrator [Get] `IClassicAdministrator` + - SubscriptionId `String[]` + +### AzDenyAssignment [Get] `IDenyAssignment` + - Id `String` + - Scope `String` + - InputObject `IResourcesIdentity` + - ParentResourcePath `String` + - ResourceGroupName `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + - SubscriptionId `String[]` + - Filter `String` + +### AzDeployment [Get, New, Remove, Set, Stop, Test] `IDeploymentExtended, Boolean, IDeploymentValidateResult` + - SubscriptionId `String[]` + - Name `String` + - ResourceGroupName `String` + - Id `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - Top `Int32` + - Parameter `IDeployment` + - DebugSettingDetailLevel `String` + - Location `String` + - Mode `DeploymentMode` + - OnErrorDeploymentName `String` + - OnErrorDeploymentType `OnErrorDeploymentType` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Template `IDeploymentPropertiesTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + - PassThru `SwitchParameter` + +### AzDeploymentExistence [Test] `Boolean` + - DeploymentName `String` + - SubscriptionId `String` + - ResourceGroupName `String` + - InputObject `IResourcesIdentity` + +### AzDeploymentOperation [Get] `IDeploymentOperation` + - DeploymentName `String` + - SubscriptionId `String[]` + - ResourceGroupName `String` + - OperationId `String` + - DeploymentObject `IDeploymentExtended` + - InputObject `IResourcesIdentity` + - Top `Int32` + +### AzDeploymentTemplate [Export] `IDeploymentExportResultTemplate` + - DeploymentName `String` + - SubscriptionId `String` + - ResourceGroupName `String` + - InputObject `IResourcesIdentity` + +### AzDomain [Get] `IDomain` + - TenantId `String` + - Name `String` + - InputObject `IResourcesIdentity` + - Filter `String` + +### AzElevateGlobalAdministratorAccess [Invoke] `Boolean` + +### AzEntity [Get] `IEntityInfo` + - Filter `String` + - GroupName `String` + - Search `String` + - Select `String` + - Skip `Int32` + - Skiptoken `String` + - Top `Int32` + - View `String` + - CacheControl `String` + +### AzManagedApplication [Get, New, Remove, Set, Update] `IApplication, Boolean` + - Id `String` + - Name `String` + - ResourceGroupName `String` + - SubscriptionId `String[]` + - InputObject `IResourcesIdentity` + - Parameter `IApplication` + - ApplicationDefinitionId `String` + - IdentityType `ResourceIdentityType` + - Kind `String` + - Location `String` + - ManagedBy `String` + - ManagedResourceGroupId `String` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - SkuCapacity `Int32` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `Hashtable` + +### AzManagedApplicationDefinition [Get, New, Remove, Set] `IApplicationDefinition, Boolean` + - Id `String` + - Name `String` + - ResourceGroupName `String` + - SubscriptionId `String[]` + - InputObject `IResourcesIdentity` + - Parameter `IApplicationDefinition` + - Artifact `IApplicationArtifact[]` + - Authorization `IApplicationProviderAuthorization[]` + - CreateUiDefinition `IApplicationDefinitionPropertiesCreateUiDefinition` + - Description `String` + - DisplayName `String` + - IdentityType `ResourceIdentityType` + - IsEnabled `String` + - Location `String` + - LockLevel `ApplicationLockLevel` + - MainTemplate `IApplicationDefinitionPropertiesMainTemplate` + - ManagedBy `String` + - PackageFileUri `String` + - SkuCapacity `Int32` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `Hashtable` + +### AzManagementGroup [Get, New, Remove, Set, Update] `IManagementGroup, IManagementGroupInfo, Boolean` + - GroupId `String` + - InputObject `IResourcesIdentity` + - Skiptoken `String` + - Expand `String` + - Filter `String` + - Recurse `SwitchParameter` + - CacheControl `String` + - DisplayName `String` + - Name `String` + - ParentId `String` + - CreateManagementGroupRequest `ICreateManagementGroupRequest` + - PatchGroupRequest `IPatchManagementGroupRequest` + +### AzManagementGroupDescendant [Get] `IDescendantInfo` + - GroupId `String` + - InputObject `IResourcesIdentity` + - Skiptoken `String` + - Top `Int32` + +### AzManagementGroupSubscription [New, Remove] `Boolean` + - GroupId `String` + - SubscriptionId `String` + - InputObject `IResourcesIdentity` + - CacheControl `String` + +### AzManagementLock [Get, New, Remove, Set] `IManagementLockObject, Boolean` + - SubscriptionId `String[]` + - LockName `String` + - ResourceGroupName `String` + - ParentResourcePath `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + - Scope `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - Level `LockLevel` + - Note `String` + - Owner `IManagementLockOwner[]` + - Parameter `IManagementLockObject` + +### AzNameAvailability [Test] `ICheckNameAvailabilityResult` + - Name `String` + - Type `Type` + - CheckNameAvailabilityRequest `ICheckNameAvailabilityRequest` + +### AzOAuth2PermissionGrant [Get, New, Remove] `IOAuth2PermissionGrant, Boolean` + - TenantId `String` + - InputObject `IResourcesIdentity` + - Filter `String` + - ClientId `String` + - ConsentType `ConsentType` + - ExpiryTime `String` + - ObjectId `String` + - OdataType `String` + - PrincipalId `String` + - ResourceId `String` + - Scope `String` + - StartTime `String` + - Body `IOAuth2PermissionGrant` + +### AzPermission [Get] `IPermission` + - ResourceGroupName `String` + - SubscriptionId `String[]` + - ParentResourcePath `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + +### AzPolicyAssignment [Get, New, Remove] `IPolicyAssignment` + - Id `String` + - Name `String` + - Scope `String` + - InputObject `IResourcesIdentity` + - ParentResourcePath `String` + - ResourceGroupName `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + - SubscriptionId `String[]` + - PolicyDefinitionId `String` + - IncludeDescendent `SwitchParameter` + - Filter `String` + - Parameter `IPolicyAssignment` + - Description `String` + - DisplayName `String` + - IdentityType `ResourceIdentityType` + - Location `String` + - Metadata `IPolicyAssignmentPropertiesMetadata` + - NotScope `String[]` + - SkuName `String` + - SkuTier `String` + - PropertiesScope `String` + +### AzPolicyDefinition [Get, New, Remove, Set] `IPolicyDefinition, Boolean` + - SubscriptionId `String[]` + - Name `String` + - ManagementGroupName `String` + - Id `String` + - InputObject `IResourcesIdentity` + - BuiltIn `SwitchParameter` + - Parameter `IPolicyDefinition` + - Description `String` + - DisplayName `String` + - Metadata `IPolicyDefinitionPropertiesMetadata` + - Mode `PolicyMode` + - PolicyRule `IPolicyDefinitionPropertiesPolicyRule` + - PolicyType `PolicyType` + - PassThru `SwitchParameter` + +### AzPolicySetDefinition [Get, New, Remove, Set] `IPolicySetDefinition, Boolean` + - SubscriptionId `String[]` + - Name `String` + - ManagementGroupName `String` + - Id `String` + - InputObject `IResourcesIdentity` + - BuiltIn `SwitchParameter` + - Parameter `IPolicySetDefinition` + - Description `String` + - DisplayName `String` + - Metadata `IPolicySetDefinitionPropertiesMetadata` + - PolicyDefinition `IPolicyDefinitionReference[]` + - PolicyType `PolicyType` + - PassThru `SwitchParameter` + +### AzProviderFeature [Get, Register] `IFeatureResult` + - SubscriptionId `String[]` + - Name `String` + - ResourceProviderNamespace `String` + - InputObject `IResourcesIdentity` + +### AzProviderOperationsMetadata [Get] `IProviderOperationsMetadata` + - ResourceProviderNamespace `String` + - InputObject `IResourcesIdentity` + - Expand `String` + +### AzResource [Get, Move, New, Remove, Set, Test, Update] `IGenericResource, Boolean` + - ResourceId `String` + - Name `String` + - ParentResourcePath `String` + - ProviderNamespace `String` + - ResourceGroupName `String` + - ResourceType `String` + - SubscriptionId `String[]` + - InputObject `IResourcesIdentity` + - SourceResourceGroupName `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - Expand `String` + - Top `Int32` + - TagName `String` + - TagValue `String` + - Tag `Hashtable` + - Filter `String` + - PassThru `SwitchParameter` + - Resource `String[]` + - TargetResourceGroup `String` + - TargetSubscriptionId `String` + - TargetResourceGroupName `String` + - Parameter `IResourcesMoveInfo` + - IdentityType `ResourceIdentityType` + - IdentityUserAssignedIdentity `Hashtable` + - Kind `String` + - Location `String` + - ManagedBy `String` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - Property `IGenericResourceProperties` + - SkuCapacity `Int32` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + +### AzResourceGroup [Export, Get, New, Remove, Set, Test, Update] `IResourceGroupExportResult, IResourceGroup, Boolean` + - ResourceGroupName `String` + - SubscriptionId `String` + - InputObject `IResourcesIdentity` + - Name `String` + - Id `String` + - Filter `String` + - Top `Int32` + - TagName `String` + - TagValue `String` + - Tag `Hashtable` + - Option `String` + - Resource `String[]` + - Parameter `IExportTemplateRequest` + - Location `String` + - ManagedBy `String` + +### AzResourceLink [Get, New, Remove, Set] `IResourceLink, Boolean` + - ResourceId `String` + - InputObject `IResourcesIdentity` + - SubscriptionId `String[]` + - Scope `String` + - FilterById `String` + - FilterByScope `Filter` + - Note `String` + - TargetId `String` + - Parameter `IResourceLink` + +### AzResourceMove [Test] `Boolean` + - SourceResourceGroupName `String` + - SubscriptionId `String` + - InputObject `IResourcesIdentity` + - PassThru `SwitchParameter` + - Resource `String[]` + - TargetResourceGroup `String` + - TargetSubscriptionId `String` + - TargetResourceGroupName `String` + - Parameter `IResourcesMoveInfo` + +### AzResourceProvider [Get, Register, Unregister] `IProvider` + - SubscriptionId `String[]` + - ResourceProviderNamespace `String` + - InputObject `IResourcesIdentity` + - Expand `String` + - Top `Int32` + +### AzResourceProviderOperationDetail [Get] `IResourceProviderOperationDefinition` + - ResourceProviderNamespace `String` + +### AzRoleAssignment [Get, New, Remove] `IRoleAssignment` + - Id `String` + - Name `String` + - Scope `String` + - RoleId `String` + - InputObject `IResourcesIdentity` + - ParentResourceId `String` + - ResourceGroupName `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + - SubscriptionId `String[]` + - ExpandPrincipalGroups `String` + - ServicePrincipalName `String` + - SignInName `String` + - Filter `String` + - CanDelegate `SwitchParameter` + - PrincipalId `String` + - RoleDefinitionId `String` + - Parameter `IRoleAssignmentCreateParameters` + - PrincipalType `PrincipalType` + +### AzRoleDefinition [Get, New, Remove, Set] `IRoleDefinition` + - Id `String` + - Scope `String` + - InputObject `IResourcesIdentity` + - Name `String` + - Custom `SwitchParameter` + - Filter `String` + - AssignableScope `String[]` + - Description `String` + - Permission `IPermission[]` + - RoleName `String` + - RoleType `String` + - RoleDefinition `IRoleDefinition` + +### AzSubscriptionLocation [Get] `ILocation` + - SubscriptionId `String[]` + +### AzTag [Get, New, Remove] `ITagDetails, Boolean` + - SubscriptionId `String[]` + - Name `String` + - Value `String` + - InputObject `IResourcesIdentity` + - PassThru `SwitchParameter` + +### AzTenantBackfill [Start] `ITenantBackfillStatusResult` + +### AzTenantBackfillStatus [Invoke] `ITenantBackfillStatusResult` + diff --git a/tests-upgrade/mysql/tools/Resources/resources/ModelSurface.md b/tests-upgrade/mysql/tools/Resources/resources/ModelSurface.md new file mode 100644 index 00000000000..378e3ec418a --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/resources/ModelSurface.md @@ -0,0 +1,1645 @@ +### AddOwnerParameters \ [Api16] + - Url `String` + +### AdGroup \ [Api16] + - DeletionTimestamp `DateTime?` **{MinValue, MaxValue}** + - DisplayName `String` + - Mail `String` + - MailEnabled `Boolean?` + - MailNickname `String` + - ObjectId `String` + - ObjectType `String` + - SecurityEnabled `Boolean?` + +### AliasPathType [Api20180501] + - ApiVersion `String[]` + - Path `String` + +### AliasType [Api20180501] + - Name `String` + - Path `IAliasPathType[]` + +### Appliance [Api20160901Preview] + - DefinitionId `String` + - Id `String` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - Kind `String` + - Location `String` + - ManagedBy `String` + - ManagedResourceGroupId `String` + - Name `String` + - Output `IAppliancePropertiesOutputs` + - Parameter `IAppliancePropertiesParameters` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - ProvisioningState `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + - UiDefinitionUri `String` + +### ApplianceArtifact [Api20160901Preview] + - Name `String` + - Type `ApplianceArtifactType?` **{Custom, Template}** + - Uri `String` + +### ApplianceDefinition [Api20160901Preview] + - Artifact `IApplianceArtifact[]` + - Authorization `IApplianceProviderAuthorization[]` + - Description `String` + - DisplayName `String` + - Id `String` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - Location `String` + - LockLevel `ApplianceLockLevel` **{CanNotDelete, None, ReadOnly}** + - ManagedBy `String` + - Name `String` + - PackageFileUri `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + +### ApplianceDefinitionListResult [Api20160901Preview] + - NextLink `String` + - Value `IApplianceDefinition[]` + +### ApplianceDefinitionProperties [Api20160901Preview] + - Artifact `IApplianceArtifact[]` + - Authorization `IApplianceProviderAuthorization[]` + - Description `String` + - DisplayName `String` + - LockLevel `ApplianceLockLevel` **{CanNotDelete, None, ReadOnly}** + - PackageFileUri `String` + +### ApplianceListResult [Api20160901Preview] + - NextLink `String` + - Value `IAppliance[]` + +### AppliancePatchable [Api20160901Preview] + - ApplianceDefinitionId `String` + - Id `String` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - Kind `String` + - Location `String` + - ManagedBy `String` + - ManagedResourceGroupId `String` + - Name `String` + - Output `IAppliancePropertiesPatchableOutputs` + - Parameter `IAppliancePropertiesPatchableParameters` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - ProvisioningState `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + - UiDefinitionUri `String` + +### ApplianceProperties [Api20160901Preview] + - ApplianceDefinitionId `String` + - ManagedResourceGroupId `String` + - Output `IAppliancePropertiesOutputs` + - Parameter `IAppliancePropertiesParameters` + - ProvisioningState `String` + - UiDefinitionUri `String` + +### AppliancePropertiesPatchable [Api20160901Preview] + - ApplianceDefinitionId `String` + - ManagedResourceGroupId `String` + - Output `IAppliancePropertiesPatchableOutputs` + - Parameter `IAppliancePropertiesPatchableParameters` + - ProvisioningState `String` + - UiDefinitionUri `String` + +### ApplianceProviderAuthorization [Api20160901Preview] + - PrincipalId `String` + - RoleDefinitionId `String` + +### Application \ [Api16, Api20170901, Api20180601] + - AllowGuestsSignIn `Boolean?` + - AllowPassthroughUser `Boolean?` + - AppId `String` + - AppLogoUrl `String` + - AppPermission `String[]` + - AppRole `IAppRole[]` + - AvailableToOtherTenant `Boolean?` + - DefinitionId `String` + - DeletionTimestamp `DateTime?` **{MinValue, MaxValue}** + - DisplayName `String` + - ErrorUrl `String` + - GroupMembershipClaim `GroupMembershipClaimTypes?` **{All, None, SecurityGroup}** + - Homepage `String` + - Id `String` + - IdentifierUri `String[]` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - InformationalUrlMarketing `String` + - InformationalUrlPrivacy `String` + - InformationalUrlSupport `String` + - InformationalUrlTermsOfService `String` + - IsDeviceOnlyAuthSupported `Boolean?` + - KeyCredentials `IKeyCredential[]` + - Kind `String` + - KnownClientApplication `String[]` + - Location `String` + - LogoutUrl `String` + - ManagedBy `String` + - ManagedResourceGroupId `String` + - Name `String` + - Oauth2AllowImplicitFlow `Boolean?` + - Oauth2AllowUrlPathMatching `Boolean?` + - Oauth2Permission `IOAuth2Permission[]` + - Oauth2RequirePostResponse `Boolean?` + - ObjectId `String` + - ObjectType `String` + - OptionalClaimAccessToken `IOptionalClaim[]` + - OptionalClaimIdToken `IOptionalClaim[]` + - OptionalClaimSamlToken `IOptionalClaim[]` + - OrgRestriction `String[]` + - Output `IApplicationPropertiesOutputs` + - Parameter `IApplicationPropertiesParameters` + - PasswordCredentials `IPasswordCredential[]` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - PreAuthorizedApplication `IPreAuthorizedApplication[]` + - ProvisioningState `String` + - PublicClient `Boolean?` + - PublisherDomain `String` + - ReplyUrl `String[]` + - RequiredResourceAccess `IRequiredResourceAccess[]` + - SamlMetadataUrl `String` + - SignInAudience `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + - UiDefinitionUri `String` + - WwwHomepage `String` + +### ApplicationArtifact [Api20170901] + - Name `String` + - Type `ApplicationArtifactType?` **{Custom, Template}** + - Uri `String` + +### ApplicationBase [Api16] + - AllowGuestsSignIn `Boolean?` + - AllowPassthroughUser `Boolean?` + - AppLogoUrl `String` + - AppPermission `String[]` + - AppRole `IAppRole[]` + - AvailableToOtherTenant `Boolean?` + - ErrorUrl `String` + - GroupMembershipClaim `GroupMembershipClaimTypes?` **{All, None, SecurityGroup}** + - Homepage `String` + - InformationalUrlMarketing `String` + - InformationalUrlPrivacy `String` + - InformationalUrlSupport `String` + - InformationalUrlTermsOfService `String` + - IsDeviceOnlyAuthSupported `Boolean?` + - KeyCredentials `IKeyCredential[]` + - KnownClientApplication `String[]` + - LogoutUrl `String` + - Oauth2AllowImplicitFlow `Boolean?` + - Oauth2AllowUrlPathMatching `Boolean?` + - Oauth2Permission `IOAuth2Permission[]` + - Oauth2RequirePostResponse `Boolean?` + - OptionalClaimAccessToken `IOptionalClaim[]` + - OptionalClaimIdToken `IOptionalClaim[]` + - OptionalClaimSamlToken `IOptionalClaim[]` + - OrgRestriction `String[]` + - PasswordCredentials `IPasswordCredential[]` + - PreAuthorizedApplication `IPreAuthorizedApplication[]` + - PublicClient `Boolean?` + - PublisherDomain `String` + - ReplyUrl `String[]` + - RequiredResourceAccess `IRequiredResourceAccess[]` + - SamlMetadataUrl `String` + - SignInAudience `String` + - WwwHomepage `String` + +### ApplicationCreateParameters [Api16] + - AllowGuestsSignIn `Boolean?` + - AllowPassthroughUser `Boolean?` + - AppLogoUrl `String` + - AppPermission `String[]` + - AppRole `IAppRole[]` + - AvailableToOtherTenant `Boolean?` + - DisplayName `String` + - ErrorUrl `String` + - GroupMembershipClaim `GroupMembershipClaimTypes?` **{All, None, SecurityGroup}** + - Homepage `String` + - IdentifierUri `String[]` + - InformationalUrl `IInformationalUrl` + - InformationalUrlMarketing `String` + - InformationalUrlPrivacy `String` + - InformationalUrlSupport `String` + - InformationalUrlTermsOfService `String` + - IsDeviceOnlyAuthSupported `Boolean?` + - KeyCredentials `IKeyCredential[]` + - KnownClientApplication `String[]` + - LogoutUrl `String` + - Oauth2AllowImplicitFlow `Boolean?` + - Oauth2AllowUrlPathMatching `Boolean?` + - Oauth2Permission `IOAuth2Permission[]` + - Oauth2RequirePostResponse `Boolean?` + - OptionalClaim `IOptionalClaims` + - OptionalClaimAccessToken `IOptionalClaim[]` + - OptionalClaimIdToken `IOptionalClaim[]` + - OptionalClaimSamlToken `IOptionalClaim[]` + - OrgRestriction `String[]` + - PasswordCredentials `IPasswordCredential[]` + - PreAuthorizedApplication `IPreAuthorizedApplication[]` + - PublicClient `Boolean?` + - PublisherDomain `String` + - ReplyUrl `String[]` + - RequiredResourceAccess `IRequiredResourceAccess[]` + - SamlMetadataUrl `String` + - SignInAudience `String` + - WwwHomepage `String` + +### ApplicationDefinition [Api20170901] + - Artifact `IApplicationArtifact[]` + - Authorization `IApplicationProviderAuthorization[]` + - CreateUiDefinition `IApplicationDefinitionPropertiesCreateUiDefinition` + - Description `String` + - DisplayName `String` + - Id `String` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - IsEnabled `String` + - Location `String` + - LockLevel `ApplicationLockLevel` **{CanNotDelete, None, ReadOnly}** + - MainTemplate `IApplicationDefinitionPropertiesMainTemplate` + - ManagedBy `String` + - Name `String` + - PackageFileUri `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + +### ApplicationDefinitionListResult [Api20180601] + - NextLink `String` + - Value `IApplicationDefinition[]` + +### ApplicationDefinitionProperties [Api20170901] + - Artifact `IApplicationArtifact[]` + - Authorization `IApplicationProviderAuthorization[]` + - CreateUiDefinition `IApplicationDefinitionPropertiesCreateUiDefinition` + - Description `String` + - DisplayName `String` + - IsEnabled `String` + - LockLevel `ApplicationLockLevel` **{CanNotDelete, None, ReadOnly}** + - MainTemplate `IApplicationDefinitionPropertiesMainTemplate` + - PackageFileUri `String` + +### ApplicationListResult [Api16, Api20180601] + - NextLink `String` + - OdataNextLink `String` + - Value `IApplication[]` + +### ApplicationPatchable [Api20170901, Api20180601] + - ApplicationDefinitionId `String` + - Id `String` + - Identity `IIdentity` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - Kind `String` + - Location `String` + - ManagedBy `String` + - ManagedResourceGroupId `String` + - Name `String` + - Output `IApplicationPropertiesPatchableOutputs` + - Parameter `IApplicationPropertiesPatchableParameters` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - ProvisioningState `String` + - Sku `ISku` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + - UiDefinitionUri `String` + +### ApplicationProperties [Api20170901, Api20180601] + - ApplicationDefinitionId `String` + - ManagedResourceGroupId `String` + - Output `IApplicationPropertiesOutputs` + - Parameter `IApplicationPropertiesParameters` + - ProvisioningState `String` + - UiDefinitionUri `String` + +### ApplicationPropertiesPatchable [Api20170901, Api20180601] + - ApplicationDefinitionId `String` + - ManagedResourceGroupId `String` + - Output `IApplicationPropertiesPatchableOutputs` + - Parameter `IApplicationPropertiesPatchableParameters` + - ProvisioningState `String` + - UiDefinitionUri `String` + +### ApplicationProviderAuthorization [Api20170901] + - PrincipalId `String` + - RoleDefinitionId `String` + +### ApplicationUpdateParameters [Api16] + - AllowGuestsSignIn `Boolean?` + - AllowPassthroughUser `Boolean?` + - AppLogoUrl `String` + - AppPermission `String[]` + - AppRole `IAppRole[]` + - AvailableToOtherTenant `Boolean?` + - DisplayName `String` + - ErrorUrl `String` + - GroupMembershipClaim `GroupMembershipClaimTypes?` **{All, None, SecurityGroup}** + - Homepage `String` + - IdentifierUri `String[]` + - InformationalUrl `IInformationalUrl` + - InformationalUrlMarketing `String` + - InformationalUrlPrivacy `String` + - InformationalUrlSupport `String` + - InformationalUrlTermsOfService `String` + - IsDeviceOnlyAuthSupported `Boolean?` + - KeyCredentials `IKeyCredential[]` + - KnownClientApplication `String[]` + - LogoutUrl `String` + - Oauth2AllowImplicitFlow `Boolean?` + - Oauth2AllowUrlPathMatching `Boolean?` + - Oauth2Permission `IOAuth2Permission[]` + - Oauth2RequirePostResponse `Boolean?` + - OptionalClaim `IOptionalClaims` + - OptionalClaimAccessToken `IOptionalClaim[]` + - OptionalClaimIdToken `IOptionalClaim[]` + - OptionalClaimSamlToken `IOptionalClaim[]` + - OrgRestriction `String[]` + - PasswordCredentials `IPasswordCredential[]` + - PreAuthorizedApplication `IPreAuthorizedApplication[]` + - PublicClient `Boolean?` + - PublisherDomain `String` + - ReplyUrl `String[]` + - RequiredResourceAccess `IRequiredResourceAccess[]` + - SamlMetadataUrl `String` + - SignInAudience `String` + - WwwHomepage `String` + +### AppRole [Api16] + - AllowedMemberType `String[]` + - Description `String` + - DisplayName `String` + - Id `String` + - IsEnabled `Boolean?` + - Value `String` + +### BasicDependency [Api20180501] + - Id `String` + - ResourceName `String` + - ResourceType `String` + +### CheckGroupMembershipParameters \ [Api16] + - GroupId `String` + - MemberId `String` + +### CheckGroupMembershipResult \ [Api16] + - Value `Boolean?` + +### CheckNameAvailabilityRequest [Api20180301Preview] + - Name `String` + - Type `Type?` **{ProvidersMicrosoftManagementGroups}** + +### CheckNameAvailabilityResult [Api20180301Preview] + - Message `String` + - NameAvailable `Boolean?` + - Reason `Reason?` **{AlreadyExists, Invalid}** + +### ClassicAdministrator [Api20150701] + - EmailAddress `String` + - Id `String` + - Name `String` + - Role `String` + - Type `String` + +### ClassicAdministratorListResult [Api20150701] + - NextLink `String` + - Value `IClassicAdministrator[]` + +### ClassicAdministratorProperties [Api20150701] + - EmailAddress `String` + - Role `String` + +### ComponentsSchemasIdentityPropertiesUserassignedidentitiesAdditionalproperties [Api20180501] + - ClientId `String` + - PrincipalId `String` + +### CreateManagementGroupChildInfo [Api20180301Preview] + - Child `ICreateManagementGroupChildInfo[]` + - DisplayName `String` + - Id `String` + - Name `String` + - Role `String[]` + - Type `String` + +### CreateManagementGroupDetails [Api20180301Preview] + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - UpdatedBy `String` + - UpdatedTime `DateTime?` **{MinValue, MaxValue}** + - Version `Single?` + +### CreateManagementGroupProperties [Api20180301Preview] + - Child `ICreateManagementGroupChildInfo[]` + - DetailUpdatedBy `String` + - DetailUpdatedTime `DateTime?` **{MinValue, MaxValue}** + - DetailVersion `Single?` + - DisplayName `String` + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - Role `String[]` + - TenantId `String` + +### CreateManagementGroupRequest [Api20180301Preview] + - Child `ICreateManagementGroupChildInfo[]` + - DetailUpdatedBy `String` + - DetailUpdatedTime `DateTime?` **{MinValue, MaxValue}** + - DetailVersion `Single?` + - DisplayName `String` + - Id `String` + - Name `String` + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - Role `String[]` + - TenantId `String` + - Type `String` + +### CreateParentGroupInfo [Api20180301Preview] + - DisplayName `String` + - Id `String` + - Name `String` + +### DebugSetting [Api20180501] + - DetailLevel `String` + +### DenyAssignment [Api20180701Preview] + - DenyAssignmentName `String` + - Description `String` + - DoNotApplyToChildScope `Boolean?` + - ExcludePrincipal `IPrincipal[]` + - Id `String` + - IsSystemProtected `Boolean?` + - Name `String` + - Permission `IDenyAssignmentPermission[]` + - Principal `IPrincipal[]` + - Scope `String` + - Type `String` + +### DenyAssignmentListResult [Api20180701Preview] + - NextLink `String` + - Value `IDenyAssignment[]` + +### DenyAssignmentPermission [Api20180701Preview] + - Action `String[]` + - DataAction `String[]` + - NotAction `String[]` + - NotDataAction `String[]` + +### DenyAssignmentProperties [Api20180701Preview] + - DenyAssignmentName `String` + - Description `String` + - DoNotApplyToChildScope `Boolean?` + - ExcludePrincipal `IPrincipal[]` + - IsSystemProtected `Boolean?` + - Permission `IDenyAssignmentPermission[]` + - Principal `IPrincipal[]` + - Scope `String` + +### Dependency [Api20180501] + - DependsOn `IBasicDependency[]` + - Id `String` + - ResourceName `String` + - ResourceType `String` + +### Deployment [Api20180501] + - DebugSettingDetailLevel `String` + - Location `String` + - Mode `DeploymentMode` **{Complete, Incremental}** + - OnErrorDeploymentName `String` + - OnErrorDeploymentType `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + - Parameter `IDeploymentPropertiesParameters` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Template `IDeploymentPropertiesTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + +### DeploymentExportResult [Api20180501] + - Template `IDeploymentExportResultTemplate` + +### DeploymentExtended [Api20180501] + - CorrelationId `String` + - DebugSettingDetailLevel `String` + - Dependency `IDependency[]` + - Id `String` + - Location `String` + - Mode `DeploymentMode?` **{Complete, Incremental}** + - Name `String` + - OnErrorDeploymentName `String` + - OnErrorDeploymentProvisioningState `String` + - OnErrorDeploymentType `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + - Output `IDeploymentPropertiesExtendedOutputs` + - Parameter `IDeploymentPropertiesExtendedParameters` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Provider `IProvider[]` + - ProvisioningState `String` + - Template `IDeploymentPropertiesExtendedTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + - Timestamp `DateTime?` **{MinValue, MaxValue}** + - Type `String` + +### DeploymentListResult [Api20180501] + - NextLink `String` + - Value `IDeploymentExtended[]` + +### DeploymentOperation [Api20180501] + - Id `String` + - OperationId `String` + - ProvisioningState `String` + - RequestContent `IHttpMessageContent` + - ResponseContent `IHttpMessageContent` + - ServiceRequestId `String` + - StatusCode `String` + - StatusMessage `IDeploymentOperationPropertiesStatusMessage` + - TargetResourceId `String` + - TargetResourceName `String` + - TargetResourceType `String` + - Timestamp `DateTime?` **{MinValue, MaxValue}** + +### DeploymentOperationProperties [Api20180501] + - ProvisioningState `String` + - RequestContent `IHttpMessageContent` + - ResponseContent `IHttpMessageContent` + - ServiceRequestId `String` + - StatusCode `String` + - StatusMessage `IDeploymentOperationPropertiesStatusMessage` + - TargetResourceId `String` + - TargetResourceName `String` + - TargetResourceType `String` + - Timestamp `DateTime?` **{MinValue, MaxValue}** + +### DeploymentOperationsListResult [Api20180501] + - NextLink `String` + - Value `IDeploymentOperation[]` + +### DeploymentProperties [Api20180501] + - DebugSettingDetailLevel `String` + - Mode `DeploymentMode` **{Complete, Incremental}** + - OnErrorDeploymentName `String` + - OnErrorDeploymentType `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + - Parameter `IDeploymentPropertiesParameters` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Template `IDeploymentPropertiesTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + +### DeploymentPropertiesExtended [Api20180501] + - CorrelationId `String` + - DebugSettingDetailLevel `String` + - Dependency `IDependency[]` + - Mode `DeploymentMode?` **{Complete, Incremental}** + - OnErrorDeploymentName `String` + - OnErrorDeploymentProvisioningState `String` + - OnErrorDeploymentType `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + - Output `IDeploymentPropertiesExtendedOutputs` + - Parameter `IDeploymentPropertiesExtendedParameters` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Provider `IProvider[]` + - ProvisioningState `String` + - Template `IDeploymentPropertiesExtendedTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + - Timestamp `DateTime?` **{MinValue, MaxValue}** + +### DeploymentValidateResult [Api20180501] + - CorrelationId `String` + - DebugSettingDetailLevel `String` + - Dependency `IDependency[]` + - ErrorCode `String` + - ErrorDetail `IResourceManagementErrorWithDetails[]` + - ErrorMessage `String` + - ErrorTarget `String` + - Mode `DeploymentMode?` **{Complete, Incremental}** + - OnErrorDeploymentName `String` + - OnErrorDeploymentProvisioningState `String` + - OnErrorDeploymentType `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + - Output `IDeploymentPropertiesExtendedOutputs` + - Parameter `IDeploymentPropertiesExtendedParameters` + - ParameterLinkContentVersion `String` + - ParameterLinkUri `String` + - Provider `IProvider[]` + - ProvisioningState `String` + - Template `IDeploymentPropertiesExtendedTemplate` + - TemplateLinkContentVersion `String` + - TemplateLinkUri `String` + - Timestamp `DateTime?` **{MinValue, MaxValue}** + +### DescendantInfo [Api20180301Preview] + - DisplayName `String` + - Id `String` + - Name `String` + - ParentId `String` + - Type `String` + +### DescendantInfoProperties [Api20180301Preview] + - DisplayName `String` + - ParentId `String` + +### DescendantListResult [Api20180301Preview] + - NextLink `String` + - Value `IDescendantInfo[]` + +### DescendantParentGroupInfo [Api20180301Preview] + - Id `String` + +### DirectoryObject \ [Api16] + - DeletionTimestamp `DateTime?` **{MinValue, MaxValue}** + - ObjectId `String` + - ObjectType `String` + +### DirectoryObjectListResult [Api16] + - OdataNextLink `String` + - Value `IDirectoryObject[]` + +### Domain \ [Api16] + - AuthenticationType `String` + - IsDefault `Boolean?` + - IsVerified `Boolean?` + - Name `String` + +### DomainListResult [Api16] + - Value `IDomain[]` + +### EntityInfo [Api20180301Preview] + - DisplayName `String` + - Id `String` + - InheritedPermission `String` + - Name `String` + - NumberOfChild `Int32?` + - NumberOfChildGroup `Int32?` + - NumberOfDescendant `Int32?` + - ParentDisplayNameChain `String[]` + - ParentId `String` + - ParentNameChain `String[]` + - Permission `String` + - TenantId `String` + - Type `String` + +### EntityInfoProperties [Api20180301Preview] + - DisplayName `String` + - InheritedPermission `String` + - NumberOfChild `Int32?` + - NumberOfChildGroup `Int32?` + - NumberOfDescendant `Int32?` + - ParentDisplayNameChain `String[]` + - ParentId `String` + - ParentNameChain `String[]` + - Permission `String` + - TenantId `String` + +### EntityListResult [Api20180301Preview] + - Count `Int32?` + - NextLink `String` + - Value `IEntityInfo[]` + +### EntityParentGroupInfo [Api20180301Preview] + - Id `String` + +### ErrorDetails [Api20180301Preview] + - Code `String` + - Detail `String` + - Message `String` + +### ErrorMessage [Api16] + - Message `String` + +### ErrorResponse [Api20160901Preview, Api20180301Preview] + - ErrorCode `String` + - ErrorDetail `String` + - ErrorMessage `String` + - HttpStatus `String` + +### ExportTemplateRequest [Api20180501] + - Option `String` + - Resource `String[]` + +### FeatureOperationsListResult [Api20151201] + - NextLink `String` + - Value `IFeatureResult[]` + +### FeatureProperties [Api20151201] + - State `String` + +### FeatureResult [Api20151201] + - Id `String` + - Name `String` + - State `String` + - Type `String` + +### GenericResource [Api20160901Preview, Api20180501] + - Id `String` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - IdentityUserAssignedIdentity `IIdentityUserAssignedIdentities ` + - Kind `String` + - Location `String` + - ManagedBy `String` + - Name `String` + - PlanName `String` + - PlanProduct `String` + - PlanPromotionCode `String` + - PlanPublisher `String` + - PlanVersion `String` + - Property `IGenericResourceProperties` + - SkuCapacity `Int32?` + - SkuFamily `String` + - SkuModel `String` + - SkuName `String` + - SkuSize `String` + - SkuTier `String` + - Tag `IResourceTags ` + - Type `String` + +### GetObjectsParameters \ [Api16] + - IncludeDirectoryObjectReference `Boolean?` + - ObjectId `String[]` + - Type `String[]` + +### GraphError [Api16] + - ErrorMessageValueMessage `String` + - OdataErrorCode `String` + +### GroupAddMemberParameters \ [Api16] + - Url `String` + +### GroupCreateParameters \ [Api16] + - DisplayName `String` + - MailEnabled `Boolean` + - MailNickname `String` + - SecurityEnabled `Boolean` + +### GroupGetMemberGroupsParameters \ [Api16] + - SecurityEnabledOnly `Boolean` + +### GroupGetMemberGroupsResult [Api16] + - Value `String[]` + +### GroupListResult [Api16] + - OdataNextLink `String` + - Value `IAdGroup[]` + +### HttpMessage [Api20180501] + - Content `IHttpMessageContent` + +### Identity [Api20160901Preview, Api20180501] + - PrincipalId `String` + - TenantId `String` + - Type `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - UserAssignedIdentity `IIdentityUserAssignedIdentities ` + +### Identity1 [Api20180501] + - PrincipalId `String` + - TenantId `String` + - Type `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + +### InformationalUrl [Api16] + - Marketing `String` + - Privacy `String` + - Support `String` + - TermsOfService `String` + +### KeyCredential \ [Api16] + - CustomKeyIdentifier `String` + - EndDate `DateTime?` **{MinValue, MaxValue}** + - KeyId `String` + - StartDate `DateTime?` **{MinValue, MaxValue}** + - Type `String` + - Usage `String` + - Value `String` + +### KeyCredentialListResult [Api16] + - Value `IKeyCredential[]` + +### KeyCredentialsUpdateParameters [Api16] + - Value `IKeyCredential[]` + +### Location [Api20160601] + - DisplayName `String` + - Id `String` + - Latitude `String` + - Longitude `String` + - Name `String` + - SubscriptionId `String` + +### LocationListResult [Api20160601] + - Value `ILocation[]` + +### ManagementGroup [Api20180301Preview] + - Child `IManagementGroupChildInfo[]` + - DetailUpdatedBy `String` + - DetailUpdatedTime `DateTime?` **{MinValue, MaxValue}** + - DetailVersion `Single?` + - DisplayName `String` + - Id `String` + - Name `String` + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - Role `String[]` + - TenantId `String` + - Type `String` + +### ManagementGroupChildInfo [Api20180301Preview] + - Child `IManagementGroupChildInfo[]` + - DisplayName `String` + - Id `String` + - Name `String` + - Role `String[]` + - Type `String` + +### ManagementGroupDetails [Api20180301Preview] + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - UpdatedBy `String` + - UpdatedTime `DateTime?` **{MinValue, MaxValue}** + - Version `Single?` + +### ManagementGroupInfo [Api20180301Preview] + - DisplayName `String` + - Id `String` + - Name `String` + - TenantId `String` + - Type `String` + +### ManagementGroupInfoProperties [Api20180301Preview] + - DisplayName `String` + - TenantId `String` + +### ManagementGroupListResult [Api20180301Preview] + - NextLink `String` + - Value `IManagementGroupInfo[]` + +### ManagementGroupProperties [Api20180301Preview] + - Child `IManagementGroupChildInfo[]` + - DetailUpdatedBy `String` + - DetailUpdatedTime `DateTime?` **{MinValue, MaxValue}** + - DetailVersion `Single?` + - DisplayName `String` + - ParentDisplayName `String` + - ParentId `String` + - ParentName `String` + - Role `String[]` + - TenantId `String` + +### ManagementLockListResult [Api20160901] + - NextLink `String` + - Value `IManagementLockObject[]` + +### ManagementLockObject [Api20160901] + - Id `String` + - Level `LockLevel` **{CanNotDelete, NotSpecified, ReadOnly}** + - Name `String` + - Note `String` + - Owner `IManagementLockOwner[]` + - Type `String` + +### ManagementLockOwner [Api20160901] + - ApplicationId `String` + +### ManagementLockProperties [Api20160901] + - Level `LockLevel` **{CanNotDelete, NotSpecified, ReadOnly}** + - Note `String` + - Owner `IManagementLockOwner[]` + +### OAuth2Permission [Api16] + - AdminConsentDescription `String` + - AdminConsentDisplayName `String` + - Id `String` + - IsEnabled `Boolean?` + - Type `String` + - UserConsentDescription `String` + - UserConsentDisplayName `String` + - Value `String` + +### OAuth2PermissionGrant [Api16] + - ClientId `String` + - ConsentType `ConsentType?` **{AllPrincipals, Principal}** + - ExpiryTime `String` + - ObjectId `String` + - OdataType `String` + - PrincipalId `String` + - ResourceId `String` + - Scope `String` + - StartTime `String` + +### OAuth2PermissionGrantListResult [Api16] + - OdataNextLink `String` + - Value `IOAuth2PermissionGrant[]` + +### OdataError [Api16] + - Code `String` + - ErrorMessageValueMessage `String` + +### OnErrorDeployment [Api20180501] + - DeploymentName `String` + - Type `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + +### OnErrorDeploymentExtended [Api20180501] + - DeploymentName `String` + - ProvisioningState `String` + - Type `OnErrorDeploymentType?` **{LastSuccessful, SpecificDeployment}** + +### Operation [Api20151201, Api20180301Preview] + - DisplayDescription `String` + - DisplayOperation `String` + - DisplayProvider `String` + - DisplayResource `String` + - Name `String` + +### OperationDisplay [Api20151201] + - Operation `String` + - Provider `String` + - Resource `String` + +### OperationDisplayProperties [Api20180301Preview] + - Description `String` + - Operation `String` + - Provider `String` + - Resource `String` + +### OperationListResult [Api20151201, Api20180301Preview] + - NextLink `String` + - Value `IOperation[]` + +### OperationResults [Api20180301Preview] + - Id `String` + - Name `String` + - ProvisioningState `String` + - Type `String` + +### OperationResultsProperties [Api20180301Preview] + - ProvisioningState `String` + +### OptionalClaim [Api16] + - AdditionalProperty `IOptionalClaimAdditionalProperties` + - Essential `Boolean?` + - Name `String` + - Source `String` + +### OptionalClaims [Api16] + - AccessToken `IOptionalClaim[]` + - IdToken `IOptionalClaim[]` + - SamlToken `IOptionalClaim[]` + +### ParametersLink [Api20180501] + - ContentVersion `String` + - Uri `String` + +### ParentGroupInfo [Api20180301Preview] + - DisplayName `String` + - Id `String` + - Name `String` + +### PasswordCredential \ [Api16] + - CustomKeyIdentifier `Byte[]` + - EndDate `DateTime?` **{MinValue, MaxValue}** + - KeyId `String` + - StartDate `DateTime?` **{MinValue, MaxValue}** + - Value `String` + +### PasswordCredentialListResult [Api16] + - Value `IPasswordCredential[]` + +### PasswordCredentialsUpdateParameters [Api16] + - Value `IPasswordCredential[]` + +### PasswordProfile \ [Api16] + - ForceChangePasswordNextLogin `Boolean?` + - Password `String` + +### PatchManagementGroupRequest [Api20180301Preview] + - DisplayName `String` + - ParentId `String` + +### Permission [Api20150701, Api201801Preview] + - Action `String[]` + - DataAction `String[]` + - NotAction `String[]` + - NotDataAction `String[]` + +### PermissionGetResult [Api20150701, Api201801Preview] + - NextLink `String` + - Value `IPermission[]` + +### Plan [Api20160901Preview, Api20180501] + - Name `String` + - Product `String` + - PromotionCode `String` + - Publisher `String` + - Version `String` + +### PlanPatchable [Api20160901Preview] + - Name `String` + - Product `String` + - PromotionCode `String` + - Publisher `String` + - Version `String` + +### PolicyAssignment [Api20151101, Api20161201, Api20180501] + - Description `String` + - DisplayName `String` + - Id `String` + - IdentityPrincipalId `String` + - IdentityTenantId `String` + - IdentityType `ResourceIdentityType?` **{None, SystemAssigned, SystemAssignedUserAssigned, UserAssigned}** + - Location `String` + - Metadata `IPolicyAssignmentPropertiesMetadata` + - Name `String` + - NotScope `String[]` + - Parameter `IPolicyAssignmentPropertiesParameters` + - PolicyDefinitionId `String` + - Scope `String` + - SkuName `String` + - SkuTier `String` + - Type `String` + +### PolicyAssignmentListResult [Api20151101, Api20161201, Api20180501] + - NextLink `String` + - Value `IPolicyAssignment[]` + +### PolicyAssignmentProperties [Api20151101, Api20161201, Api20180501] + - Description `String` + - DisplayName `String` + - Metadata `IPolicyAssignmentPropertiesMetadata` + - NotScope `String[]` + - Parameter `IPolicyAssignmentPropertiesParameters` + - PolicyDefinitionId `String` + - Scope `String` + +### PolicyDefinition [Api20161201, Api20180501] + - Description `String` + - DisplayName `String` + - Id `String` + - Metadata `IPolicyDefinitionPropertiesMetadata` + - Mode `PolicyMode?` **{All, Indexed, NotSpecified}** + - Name `String` + - Parameter `IPolicyDefinitionPropertiesParameters` + - PolicyRule `IPolicyDefinitionPropertiesPolicyRule` + - PolicyType `PolicyType?` **{BuiltIn, Custom, NotSpecified}** + - Property `IPolicyDefinitionProperties` + - Type `String` + +### PolicyDefinitionListResult [Api20161201, Api20180501] + - NextLink `String` + - Value `IPolicyDefinition[]` + +### PolicyDefinitionProperties [Api20161201] + - Description `String` + - DisplayName `String` + - Metadata `IPolicyDefinitionPropertiesMetadata` + - Mode `PolicyMode?` **{All, Indexed, NotSpecified}** + - Parameter `IPolicyDefinitionPropertiesParameters` + - PolicyRule `IPolicyDefinitionPropertiesPolicyRule` + - PolicyType `PolicyType?` **{BuiltIn, Custom, NotSpecified}** + +### PolicyDefinitionReference [Api20180501] + - Parameter `IPolicyDefinitionReferenceParameters` + - PolicyDefinitionId `String` + +### PolicySetDefinition [Api20180501] + - Description `String` + - DisplayName `String` + - Id `String` + - Metadata `IPolicySetDefinitionPropertiesMetadata` + - Name `String` + - Parameter `IPolicySetDefinitionPropertiesParameters` + - PolicyDefinition `IPolicyDefinitionReference[]` + - PolicyType `PolicyType?` **{BuiltIn, Custom, NotSpecified}** + - Type `String` + +### PolicySetDefinitionListResult [Api20180501] + - NextLink `String` + - Value `IPolicySetDefinition[]` + +### PolicySetDefinitionProperties [Api20180501] + - Description `String` + - DisplayName `String` + - Metadata `IPolicySetDefinitionPropertiesMetadata` + - Parameter `IPolicySetDefinitionPropertiesParameters` + - PolicyDefinition `IPolicyDefinitionReference[]` + - PolicyType `PolicyType?` **{BuiltIn, Custom, NotSpecified}** + +### PolicySku [Api20180501] + - Name `String` + - Tier `String` + +### PreAuthorizedApplication [Api16] + - AppId `String` + - Extension `IPreAuthorizedApplicationExtension[]` + - Permission `IPreAuthorizedApplicationPermission[]` + +### PreAuthorizedApplicationExtension [Api16] + - Condition `String[]` + +### PreAuthorizedApplicationPermission [Api16] + - AccessGrant `String[]` + - DirectAccessGrant `Boolean?` + +### Principal [Api20180701Preview] + - Id `String` + - Type `String` + +### Provider [Api20180501] + - Id `String` + - Namespace `String` + - RegistrationState `String` + - ResourceType `IProviderResourceType[]` + +### ProviderListResult [Api20180501] + - NextLink `String` + - Value `IProvider[]` + +### ProviderOperation [Api20150701, Api201801Preview] + - Description `String` + - DisplayName `String` + - IsDataAction `Boolean?` + - Name `String` + - Origin `String` + - Property `IProviderOperationProperties` + +### ProviderOperationsMetadata [Api20150701, Api201801Preview] + - DisplayName `String` + - Id `String` + - Name `String` + - Operation `IProviderOperation[]` + - ResourceType `IResourceType[]` + - Type `String` + +### ProviderOperationsMetadataListResult [Api20150701, Api201801Preview] + - NextLink `String` + - Value `IProviderOperationsMetadata[]` + +### ProviderResourceType [Api20180501] + - Alias `IAliasType[]` + - ApiVersion `String[]` + - Location `String[]` + - Property `IProviderResourceTypeProperties ` + - ResourceType `String` + +### RequiredResourceAccess \ [Api16] + - ResourceAccess `IResourceAccess[]` + - ResourceAppId `String` + +### Resource [Api20160901Preview] + - Id `String` + - Location `String` + - Name `String` + - Tag `IResourceTags ` + - Type `String` + +### ResourceAccess \ [Api16] + - Id `String` + - Type `String` + +### ResourceGroup [Api20180501] + - Id `String` + - Location `String` + - ManagedBy `String` + - Name `String` + - ProvisioningState `String` + - Tag `IResourceGroupTags ` + - Type `String` + +### ResourceGroupExportResult [Api20180501] + - ErrorCode `String` + - ErrorDetail `IResourceManagementErrorWithDetails[]` + - ErrorMessage `String` + - ErrorTarget `String` + - Template `IResourceGroupExportResultTemplate` + +### ResourceGroupListResult [Api20180501] + - NextLink `String` + - Value `IResourceGroup[]` + +### ResourceGroupPatchable [Api20180501] + - ManagedBy `String` + - Name `String` + - ProvisioningState `String` + - Tag `IResourceGroupPatchableTags ` + +### ResourceGroupProperties [Api20180501] + - ProvisioningState `String` + +### ResourceLink [Api20160901] + - Id `String` + - Name `String` + - Note `String` + - SourceId `String` + - TargetId `String` + - Type `IResourceLinkType` + +### ResourceLinkProperties [Api20160901] + - Note `String` + - SourceId `String` + - TargetId `String` + +### ResourceLinkResult [Api20160901] + - NextLink `String` + - Value `IResourceLink[]` + +### ResourceListResult [Api20180501] + - NextLink `String` + - Value `IGenericResource[]` + +### ResourceManagementErrorWithDetails [Api20180501] + - Code `String` + - Detail `IResourceManagementErrorWithDetails[]` + - Message `String` + - Target `String` + +### ResourceProviderOperationDefinition [Api20151101] + - DisplayDescription `String` + - DisplayOperation `String` + - DisplayProvider `String` + - DisplayPublisher `String` + - DisplayResource `String` + - Name `String` + +### ResourceProviderOperationDetailListResult [Api20151101] + - NextLink `String` + - Value `IResourceProviderOperationDefinition[]` + +### ResourceProviderOperationDisplayProperties [Api20151101] + - Description `String` + - Operation `String` + - Provider `String` + - Publisher `String` + - Resource `String` + +### ResourcesIdentity [Models] + - ApplianceDefinitionId `String` + - ApplianceDefinitionName `String` + - ApplianceId `String` + - ApplianceName `String` + - ApplicationDefinitionId `String` + - ApplicationDefinitionName `String` + - ApplicationId `String` + - ApplicationId1 `String` + - ApplicationName `String` + - ApplicationObjectId `String` + - DenyAssignmentId `String` + - DeploymentName `String` + - DomainName `String` + - FeatureName `String` + - GroupId `String` + - GroupObjectId `String` + - Id `String` + - LinkId `String` + - LockName `String` + - ManagementGroupId `String` + - MemberObjectId `String` + - ObjectId `String` + - OperationId `String` + - OwnerObjectId `String` + - ParentResourcePath `String` + - PolicyAssignmentId `String` + - PolicyAssignmentName `String` + - PolicyDefinitionName `String` + - PolicySetDefinitionName `String` + - ResourceGroupName `String` + - ResourceId `String` + - ResourceName `String` + - ResourceProviderNamespace `String` + - ResourceType `String` + - RoleAssignmentId `String` + - RoleAssignmentName `String` + - RoleDefinitionId `String` + - RoleId `String` + - Scope `String` + - SourceResourceGroupName `String` + - SubscriptionId `String` + - TagName `String` + - TagValue `String` + - TenantId `String` + - UpnOrObjectId `String` + +### ResourcesMoveInfo [Api20180501] + - Resource `String[]` + - TargetResourceGroup `String` + +### ResourceType [Api20150701, Api201801Preview] + - DisplayName `String` + - Name `String` + - Operation `IProviderOperation[]` + +### RoleAssignment [Api20150701, Api20171001Preview, Api20180901Preview] + - CanDelegate `Boolean?` + - Id `String` + - Name `String` + - PrincipalId `String` + - PrincipalType `PrincipalType?` **{Application, DirectoryObjectOrGroup, DirectoryRoleTemplate, Everyone, ForeignGroup, Group, Msi, ServicePrincipal, Unknown, User}** + - RoleDefinitionId `String` + - Scope `String` + - Type `String` + +### RoleAssignmentCreateParameters [Api20150701, Api20171001Preview, Api20180901Preview] + - CanDelegate `Boolean?` + - PrincipalId `String` + - PrincipalType `PrincipalType?` **{Application, DirectoryObjectOrGroup, DirectoryRoleTemplate, Everyone, ForeignGroup, Group, Msi, ServicePrincipal, Unknown, User}** + - RoleDefinitionId `String` + +### RoleAssignmentListResult [Api20150701, Api20180901Preview] + - NextLink `String` + - Value `IRoleAssignment[]` + +### RoleAssignmentProperties [Api20150701, Api20171001Preview, Api20180901Preview] + - CanDelegate `Boolean?` + - PrincipalId `String` + - PrincipalType `PrincipalType?` **{Application, DirectoryObjectOrGroup, DirectoryRoleTemplate, Everyone, ForeignGroup, Group, Msi, ServicePrincipal, Unknown, User}** + - RoleDefinitionId `String` + +### RoleAssignmentPropertiesWithScope [Api20150701, Api20171001Preview, Api20180901Preview] + - CanDelegate `Boolean?` + - PrincipalId `String` + - PrincipalType `PrincipalType?` **{Application, DirectoryObjectOrGroup, DirectoryRoleTemplate, Everyone, ForeignGroup, Group, Msi, ServicePrincipal, Unknown, User}** + - RoleDefinitionId `String` + - Scope `String` + +### RoleDefinition [Api20150701, Api201801Preview] + - AssignableScope `String[]` + - Description `String` + - Id `String` + - Name `String` + - Permission `IPermission[]` + - RoleName `String` + - RoleType `String` + - Type `String` + +### RoleDefinitionListResult [Api20150701, Api201801Preview] + - NextLink `String` + - Value `IRoleDefinition[]` + +### RoleDefinitionProperties [Api20150701, Api201801Preview] + - AssignableScope `String[]` + - Description `String` + - Permission `IPermission[]` + - RoleName `String` + - RoleType `String` + +### ServicePrincipal \ [Api16] + - AccountEnabled `Boolean?` + - AlternativeName `String[]` + - AppDisplayName `String` + - AppId `String` + - AppOwnerTenantId `String` + - AppRole `IAppRole[]` + - AppRoleAssignmentRequired `Boolean?` + - DeletionTimestamp `DateTime?` **{MinValue, MaxValue}** + - DisplayName `String` + - ErrorUrl `String` + - Homepage `String` + - KeyCredentials `IKeyCredential[]` + - LogoutUrl `String` + - Name `String[]` + - Oauth2Permission `IOAuth2Permission[]` + - ObjectId `String` + - ObjectType `String` + - PasswordCredentials `IPasswordCredential[]` + - PreferredTokenSigningKeyThumbprint `String` + - PublisherName `String` + - ReplyUrl `String[]` + - SamlMetadataUrl `String` + - Tag `String[]` + - Type `String` + +### ServicePrincipalBase [Api16] + - AccountEnabled `Boolean?` + - AppRoleAssignmentRequired `Boolean?` + - KeyCredentials `IKeyCredential[]` + - PasswordCredentials `IPasswordCredential[]` + - ServicePrincipalType `String` + - Tag `String[]` + +### ServicePrincipalCreateParameters [Api16] + - AccountEnabled `Boolean?` + - AppId `String` + - AppRoleAssignmentRequired `Boolean?` + - KeyCredentials `IKeyCredential[]` + - PasswordCredentials `IPasswordCredential[]` + - ServicePrincipalType `String` + - Tag `String[]` + +### ServicePrincipalListResult [Api16] + - OdataNextLink `String` + - Value `IServicePrincipal[]` + +### ServicePrincipalObjectResult [Api16] + - OdataMetadata `String` + - Value `String` + +### ServicePrincipalUpdateParameters [Api16] + - AccountEnabled `Boolean?` + - AppRoleAssignmentRequired `Boolean?` + - KeyCredentials `IKeyCredential[]` + - PasswordCredentials `IPasswordCredential[]` + - ServicePrincipalType `String` + - Tag `String[]` + +### SignInName \ [Api16] + - Type `String` + - Value `String` + +### Sku [Api20160901Preview, Api20180501] + - Capacity `Int32?` + - Family `String` + - Model `String` + - Name `String` + - Size `String` + - Tier `String` + +### Subscription [Api20160601] + - AuthorizationSource `String` + - DisplayName `String` + - Id `String` + - PolicyLocationPlacementId `String` + - PolicyQuotaId `String` + - PolicySpendingLimit `SpendingLimit?` **{CurrentPeriodOff, Off, On}** + - State `SubscriptionState?` **{Deleted, Disabled, Enabled, PastDue, Warned}** + - SubscriptionId `String` + +### SubscriptionPolicies [Api20160601] + - LocationPlacementId `String` + - QuotaId `String` + - SpendingLimit `SpendingLimit?` **{CurrentPeriodOff, Off, On}** + +### TagCount [Api20180501] + - Type `String` + - Value `Int32?` + +### TagDetails [Api20180501] + - CountType `String` + - CountValue `Int32?` + - Id `String` + - TagName `String` + - Value `ITagValue[]` + +### TagsListResult [Api20180501] + - NextLink `String` + - Value `ITagDetails[]` + +### TagValue [Api20180501] + - CountType `String` + - CountValue `Int32?` + - Id `String` + - TagValue1 `String` + +### TargetResource [Api20180501] + - Id `String` + - ResourceName `String` + - ResourceType `String` + +### TemplateLink [Api20180501] + - ContentVersion `String` + - Uri `String` + +### TenantBackfillStatusResult [Api20180301Preview] + - Status `Status?` **{Cancelled, Completed, Failed, NotStarted, NotStartedButGroupsExist, Started}** + - TenantId `String` + +### TenantIdDescription [Api20160601] + - Id `String` + - TenantId `String` + +### TenantListResult [Api20160601] + - NextLink `String` + - Value `ITenantIdDescription[]` + +### User \ [Api16] + - AccountEnabled `Boolean?` + - DeletionTimestamp `DateTime?` **{MinValue, MaxValue}** + - DisplayName `String` + - GivenName `String` + - ImmutableId `String` + - Mail `String` + - MailNickname `String` + - ObjectId `String` + - ObjectType `String` + - PrincipalName `String` + - SignInName `ISignInName[]` + - Surname `String` + - Type `UserType?` **{Guest, Member}** + - UsageLocation `String` + +### UserBase \ [Api16] + - GivenName `String` + - ImmutableId `String` + - Surname `String` + - UsageLocation `String` + - UserType `UserType?` **{Guest, Member}** + +### UserCreateParameters \ [Api16] + - AccountEnabled `Boolean` + - DisplayName `String` + - GivenName `String` + - ImmutableId `String` + - Mail `String` + - MailNickname `String` + - PasswordProfile `IPasswordProfile ` + - Surname `String` + - UsageLocation `String` + - UserPrincipalName `String` + - UserType `UserType?` **{Guest, Member}** + +### UserGetMemberGroupsParameters \ [Api16] + - SecurityEnabledOnly `Boolean` + +### UserGetMemberGroupsResult [Api16] + - Value `String[]` + +### UserListResult [Api16] + - OdataNextLink `String` + - Value `IUser[]` + +### UserUpdateParameters \ [Api16] + - AccountEnabled `Boolean?` + - DisplayName `String` + - GivenName `String` + - ImmutableId `String` + - MailNickname `String` + - PasswordProfile `IPasswordProfile ` + - Surname `String` + - UsageLocation `String` + - UserPrincipalName `String` + - UserType `UserType?` **{Guest, Member}** + diff --git a/tests-upgrade/mysql/tools/Resources/resources/readme.md b/tests-upgrade/mysql/tools/Resources/resources/readme.md new file mode 100644 index 00000000000..937f07f8fec --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/resources/readme.md @@ -0,0 +1,11 @@ +# Resources +This directory can contain any additional resources for module that are not required at runtime. This directory **does not** get packaged with the module. If you have assets for custom implementation, place them into the `..\custom` folder. + +## Info +- Modifiable: yes +- Generated: no +- Committed: yes +- Packaged: no + +## Purpose +Use this folder to put anything you want to keep around as part of the repository for the module, but is not something that is required for the module. For example, development files, packaged builds, or additional information. This is only intended to be used in repositories where the module's output directory is cleaned, but tangential resources for the module want to remain intact. \ No newline at end of file diff --git a/tests-upgrade/mysql/tools/Resources/test/readme.md b/tests-upgrade/mysql/tools/Resources/test/readme.md new file mode 100644 index 00000000000..7c752b4c8c4 --- /dev/null +++ b/tests-upgrade/mysql/tools/Resources/test/readme.md @@ -0,0 +1,17 @@ +# Test +This directory contains the [Pester](https://www.powershellgallery.com/packages/Pester) tests to run for the module. We use Pester as it is the unofficial standard for PowerShell unit testing. Test stubs for custom cmdlets (created in `..\custom`) will be generated into this folder when `build-module.ps1` is ran. These test stubs will fail automatically, to indicate that tests should be written for custom cmdlets. + +## Info +- Modifiable: yes +- Generated: partial +- Committed: yes +- Packaged: no + +## Details +We allow three testing modes: *live*, *record*, and *playback*. These can be selected using the `-Live`, `-Record`, and `-Playback` switches respectively on the `test-module.ps1` script. This script will run through any `.Tests.ps1` scripts in the `test` folder. If you choose the *record* mode, it will create a `.Recording.json` file of the REST calls between the client and server. Then, when you choose *playback* mode, it will use the `.Recording.json` file to mock the communication between server and client. The *live* mode runs the same as the *record* mode; however, it doesn't create the `.Recording.json` file. + +## Purpose +Custom cmdlets generally encompass additional functionality not described in the REST specification, or combines functionality generated from the REST spec. To validate this functionality continues to operate as intended, creating tests that can be ran and re-ran against custom cmdlets is part of the framework. + +## Usage +To execute tests, run the `test-module.ps1`. To write tests, [this example](https://github.com/pester/Pester/blob/8b9cf4248315e44f1ac6673be149f7e0d7f10466/Examples/Planets/Get-Planet.Tests.ps1#L1) from the Pester repository is very useful for getting started. \ No newline at end of file diff --git a/tests-upgrade/tsi/readme.md b/tests-upgrade/tsi/readme.md new file mode 100644 index 00000000000..254dcdea73a --- /dev/null +++ b/tests-upgrade/tsi/readme.md @@ -0,0 +1,130 @@ + +# Az.TimeSeriesInsights +This directory contains the PowerShell module for the TimeSeriesInsights service. + +--- +## Status +[![Az.TimeSeriesInsights](https://img.shields.io/powershellgallery/v/Az.TimeSeriesInsights.svg?style=flat-square&label=Az.TimeSeriesInsights "Az.TimeSeriesInsights")](https://www.powershellgallery.com/packages/Az.TimeSeriesInsights/) + +## Info +- Modifiable: yes +- Generated: all +- Committed: yes +- Packaged: yes + +--- +## Detail +This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. + +## Module Requirements +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater + +## Authentication +AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. + +## Development +For information on how to develop for `Az.TimeSeriesInsights`, see [how-to.md](how-to.md). + + +--- +## Generation Requirements +Use of the beta version of `autorest.powershell` generator requires the following: +- [NodeJS LTS](https://nodejs.org) (10.15.x LTS preferred) + - **Note**: It *will not work* with Node < 10.x. Using 11.x builds may cause issues as they may introduce instability or breaking changes. +> If you want an easy way to install and update Node, [NVS - Node Version Switcher](../nodejs/installing-via-nvs.md) or [NVM - Node Version Manager](../nodejs/installing-via-nvm.md) is recommended. +- [AutoRest](https://aka.ms/autorest) v3 beta
`npm install -g autorest@autorest`
  +- PowerShell 6.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g pwsh`
  +- .NET Core SDK 2.0 or greater + - If you don't have it installed, you can use the cross-platform npm package
`npm install -g dotnet-sdk-2.2`
  + +## Run Generation +In this directory, run AutoRest: +> `autorest-beta` + +--- +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +branch: powershell +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - ./timeseriesinsights.json + +module-version: 0.0.1 +title: TimeSeriesInsights +subject-prefix: $(service-name) + +directive: + # Fix errors in swagger + - from: swagger-document + where: $ + transform: return $.replace(/Microsoft.IotHub/g, "Microsoft.IoTHub") + - from: swagger-document + where: $ + transform: return $.replace(/\/eventSources\//g, "/eventsources/") + - from: swagger-document + where: $ + transform: return $.replace(/\/accessPolicies\//g, "/accesspolicies/") + # Remove the unneeded parameter set + - where: + variant: ^CreateViaIdentity$|^CreateViaIdentityExpanded$|^Update$|^UpdateViaIdentity$ + remove: true + - where: + subject: ReferenceDataSet|AccessPolicy + variant: ^Create$ + remove: true + - where: + subject: EventSource|Environment + variant: ^Create$|^CreateExpanded$ + hide: true + # Remove the set-* cmdlet + - where: + verb: Set + remove: true + # Hide the operation cmdlet + - where: + subject: Operation + hide: true + # correct some names + - where: + parameter-name: SkuCapacity + set: + parameter-name: Capacity + - where: + parameter-name: SkuName + set: + parameter-name: Sku + # Suppress the table format + - where: + model-name: StandardEnvironmentResource + set: + suppress-format: true + - where: + model-name: LongTermEnvironmentResource + set: + suppress-format: true + - where: + model-name: EventHubEventSourceResource + set: + suppress-format: true + - where: + model-name: IoTHubEventSourceResource + set: + suppress-format: true + # Correct some generated code + - from: source-file-csharp + where: $ + transform: $ = $.replace('internal Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IStandardEnvironmentCreationProperties Property', 'public Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IStandardEnvironmentCreationProperties Property'); + - from: source-file-csharp + where: $ + transform: $ = $.replace('internal Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.ILongTermEnvironmentCreationProperties Property', 'public Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.ILongTermEnvironmentCreationProperties Property'); + - from: source-file-csharp + where: $ + transform: $ = $.replace('internal Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IEventHubEventSourceCreationProperties Property', 'public Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IEventHubEventSourceCreationProperties Property'); + - from: source-file-csharp + where: $ + transform: $ = $.replace('internal Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IIoTHubEventSourceCreationProperties Property', 'public Microsoft.Azure.PowerShell.Cmdlets.TimeSeriesInsights.Models.Api20180815Preview.IIoTHubEventSourceCreationProperties Property'); +``` diff --git a/tests-upgrade/tsi/timeseriesinsights.json b/tests-upgrade/tsi/timeseriesinsights.json new file mode 100644 index 00000000000..240dd0cb741 --- /dev/null +++ b/tests-upgrade/tsi/timeseriesinsights.json @@ -0,0 +1,2061 @@ +{ + "swagger": "2.0", + "info": { + "title": "TimeSeriesInsightsClient", + "description": "Time Series Insights client", + "version": "2017-02-28-preview" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/providers/Microsoft.TimeSeriesInsights/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "description": "Lists all of the available Time Series Insights related operations.", + "x-ms-examples": { + "List available operations for the Time Series Insights resource provider": { + "$ref": "./examples/Operation_List.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Successfully listed the available operations.", + "schema": { + "$ref": "#/definitions/OperationListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}": { + "put": { + "tags": [ + "Environments" + ], + "operationId": "Environments_CreateOrUpdate", + "x-ms-examples": { + "EnvironmentsCreate": { + "$ref": "./examples/EnvironmentsCreate.json" + } + }, + "x-ms-long-running-operation": true, + "description": "Create or update an environment in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "name": "environmentName", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "description": "Name of the environment" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EnvironmentCreateOrUpdateParameters" + }, + "description": "Parameters for creating an environment resource." + } + ], + "responses": { + "200": { + "description": "The existing environment definition was successfully updated.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "201": { + "description": "The environment create request was accepted. Environment provisioning is an asynchronous operation. You can periodically get your environment definition and monitor progress via the provisioningState property.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "404": { + "description": "The subscription or resource group could not be found." + }, + "default": { + "description": "HTTP 400 (Bad Request): The given environment request body is invalid; See the error code and message in the response for details.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "get": { + "tags": [ + "Environments" + ], + "operationId": "Environments_Get", + "x-ms-examples": { + "EnvironmentsGet": { + "$ref": "./examples/EnvironmentsGet.json" + } + }, + "description": "Gets the environment with the specified name in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The environment definition was successfully retrieved and is in the response. If you are polling for the completion of a provisioning or scale operation, you can check its status via the provisioningState property.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "patch": { + "tags": [ + "Environments" + ], + "operationId": "Environments_Update", + "x-ms-examples": { + "EnvironmentsUpdate": { + "$ref": "./examples/EnvironmentsPatchSkuCapacity.json" + } + }, + "x-ms-long-running-operation": true, + "description": "Updates the environment with the specified name in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "name": "environmentUpdateParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EnvironmentUpdateParameters" + }, + "description": "Request object that contains the updated information for the environment." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The environment definition was successfully updated and is in the response. If the environment was updated synchronously, the response will include a provisioningState value of \"Succeeded\". If the environment was updated asynchronously, the response will include a provisioningState value of \"Updating\". You can periodically get your environment definition and monitor progress of the update via the provisioningState property.", + "schema": { + "$ref": "#/definitions/EnvironmentResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "delete": { + "tags": [ + "Environments" + ], + "operationId": "Environments_Delete", + "x-ms-examples": { + "EnvironmentsDelete": { + "$ref": "./examples/EnvironmentsDelete.json" + } + }, + "description": "Deletes the environment with the specified name in the specified subscription and resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The environment was successfully deleted." + }, + "204": { + "description": "The environment was successfully deleted." + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments": { + "get": { + "tags": [ + "Environments" + ], + "operationId": "Environments_ListByResourceGroup", + "x-ms-examples": { + "EnvironmentsByResourceGroup": { + "$ref": "./examples/EnvironmentsListByResourceGroup.json" + } + }, + "description": "Lists all the available environments associated with the subscription and within the specified resource group.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Environments returned successfully.", + "schema": { + "$ref": "#/definitions/EnvironmentListResponse" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, or resource group could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.TimeSeriesInsights/environments": { + "get": { + "tags": [ + "Environments" + ], + "operationId": "Environments_ListBySubscription", + "x-ms-examples": { + "EnvironmentsBySubscription": { + "$ref": "./examples/EnvironmentsListBySubscription.json" + } + }, + "description": "Lists all the available environments within a subscription, irrespective of the resource groups.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Environments returned successfully.", + "schema": { + "$ref": "#/definitions/EnvironmentListResponse" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/eventSources/{eventSourceName}": { + "put": { + "tags": [ + "EventSources" + ], + "operationId": "EventSources_CreateOrUpdate", + "description": "Create or update an event source under the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "name": "eventSourceName", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "description": "Name of the event source." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EventSourceCreateOrUpdateParameters" + }, + "description": "Parameters for creating an event source resource." + } + ], + "responses": { + "200": { + "description": "The existing event source definition was successfully updated.", + "schema": { + "$ref": "#/definitions/EventSourceResource" + } + }, + "201": { + "description": "The event source was successfully created.", + "schema": { + "$ref": "#/definitions/EventSourceResource" + } + }, + "default": { + "description": "HTTP 400 (Bad Request): The given event source request body is invalid; See the error code and message in the response for details.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "get": { + "tags": [ + "EventSources" + ], + "operationId": "EventSources_Get", + "description": "Gets the event source with the specified name in the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/EventSourceNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The event source definition was successfully retrieved and is in the response.", + "schema": { + "$ref": "#/definitions/EventSourceResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or event source could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "patch": { + "tags": [ + "EventSources" + ], + "operationId": "EventSources_Update", + "description": "Updates the event source with the specified name in the specified subscription, resource group, and environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/EventSourceNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "eventSourceUpdateParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EventSourceUpdateParameters" + }, + "description": "Request object that contains the updated information for the event source." + } + ], + "responses": { + "200": { + "description": "The event source definition was successfully updated and is in the response.", + "schema": { + "$ref": "#/definitions/EventSourceResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or event source could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "delete": { + "tags": [ + "EventSources" + ], + "operationId": "EventSources_Delete", + "description": "Deletes the event source with the specified name in the specified subscription, resource group, and environment", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/EventSourceNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The event source was successfully deleted." + }, + "204": { + "description": "The event source was successfully deleted." + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or event source could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/eventSources": { + "get": { + "tags": [ + "EventSources" + ], + "operationId": "EventSources_ListByEnvironment", + "description": "Lists all the available event sources associated with the subscription and within the specified resource group and environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Environments returned successfully.", + "schema": { + "$ref": "#/definitions/EventSourceListResponse" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/referenceDataSets/{referenceDataSetName}": { + "put": { + "tags": [ + "ReferenceDataSets" + ], + "operationId": "ReferenceDataSets_CreateOrUpdate", + "x-ms-examples": { + "ReferenceDataSetsCreate": { + "$ref": "./examples/ReferenceDataSetsCreate.json" + } + }, + "description": "Create or update a reference data set in the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "name": "referenceDataSetName", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[A-Za-z0-9]", + "minLength": 3, + "maxLength": 63, + "description": "Name of the reference data set." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ReferenceDataSetCreateOrUpdateParameters" + }, + "description": "Parameters for creating a reference data set." + } + ], + "responses": { + "200": { + "description": "The existing reference data set definition was successfully updated.", + "schema": { + "$ref": "#/definitions/ReferenceDataSetResource" + } + }, + "201": { + "description": "The reference data set was successfully created.", + "schema": { + "$ref": "#/definitions/ReferenceDataSetResource" + } + }, + "default": { + "description": "HTTP 400 (Bad Request): The given reference data set request body is invalid; See the error code and message in the response for details.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "get": { + "tags": [ + "ReferenceDataSets" + ], + "operationId": "ReferenceDataSets_Get", + "x-ms-examples": { + "ReferenceDataSetsGet": { + "$ref": "./examples/ReferenceDataSetsGet.json" + } + }, + "description": "Gets the reference data set with the specified name in the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ReferenceDataSetNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The reference data set definition was successfully retrieved and is in the response.", + "schema": { + "$ref": "#/definitions/ReferenceDataSetResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or reference data set could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "patch": { + "tags": [ + "ReferenceDataSets" + ], + "operationId": "ReferenceDataSets_Update", + "x-ms-examples": { + "ReferenceDataSetsUpdate": { + "$ref": "./examples/ReferenceDataSetsPatchTags.json" + } + }, + "description": "Updates the reference data set with the specified name in the specified subscription, resource group, and environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ReferenceDataSetNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "referenceDataSetUpdateParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ReferenceDataSetUpdateParameters" + }, + "description": "Request object that contains the updated information for the reference data set." + } + ], + "responses": { + "200": { + "description": "The reference data set definition was successfully updated and is in the response.", + "schema": { + "$ref": "#/definitions/ReferenceDataSetResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or reference data set could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "delete": { + "tags": [ + "ReferenceDataSets" + ], + "operationId": "ReferenceDataSets_Delete", + "x-ms-examples": { + "ReferenceDataSetsDelete": { + "$ref": "./examples/ReferenceDataSetsDelete.json" + } + }, + "description": "Deletes the reference data set with the specified name in the specified subscription, resource group, and environment", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ReferenceDataSetNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The reference data set was successfully deleted." + }, + "204": { + "description": "The reference data set was successfully deleted." + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or reference data set could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/referenceDataSets": { + "get": { + "tags": [ + "ReferenceDataSets" + ], + "operationId": "ReferenceDataSets_ListByEnvironment", + "x-ms-examples": { + "ReferenceDataSetsListByEnvironment": { + "$ref": "./examples/ReferenceDataSetsListByEnvironment.json" + } + }, + "description": "Lists all the available reference data sets associated with the subscription and within the specified resource group and environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Reference data sets returned successfully.", + "schema": { + "$ref": "#/definitions/ReferenceDataSetListResponse" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/accessPolicies/{accessPolicyName}": { + "put": { + "tags": [ + "AccessPolicies" + ], + "operationId": "AccessPolicies_CreateOrUpdate", + "x-ms-examples": { + "AccessPoliciesCreate": { + "$ref": "./examples/AccessPoliciesCreate.json" + } + }, + "description": "Create or update an access policy in the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "name": "accessPolicyName", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[-\\w\\._\\(\\)]+$", + "minLength": 1, + "maxLength": 90, + "description": "Name of the access policy." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/AccessPolicyCreateOrUpdateParameters" + }, + "description": "Parameters for creating an access policy." + } + ], + "responses": { + "200": { + "description": "The existing access policy definition was successfully updated.", + "schema": { + "$ref": "#/definitions/AccessPolicyResource" + } + }, + "201": { + "description": "The access policy was successfully created.", + "schema": { + "$ref": "#/definitions/AccessPolicyResource" + } + }, + "default": { + "description": "HTTP 400 (Bad Request): The given access policy request body is invalid; See the error code and message in the response for details.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "get": { + "tags": [ + "AccessPolicies" + ], + "operationId": "AccessPolicies_Get", + "x-ms-examples": { + "AccessPoliciesGet": { + "$ref": "./examples/AccessPoliciesGet.json" + } + }, + "description": "Gets the access policy with the specified name in the specified environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/AccessPolicyNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The access policy definition was successfully retrieved and is in the response.", + "schema": { + "$ref": "#/definitions/AccessPolicyResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or access policy could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "patch": { + "tags": [ + "AccessPolicies" + ], + "operationId": "AccessPolicies_Update", + "x-ms-examples": { + "AccessPoliciesUpdate": { + "$ref": "./examples/AccessPoliciesPatchRoles.json" + } + }, + "description": "Updates the access policy with the specified name in the specified subscription, resource group, and environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/AccessPolicyNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "accessPolicyUpdateParameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/AccessPolicyUpdateParameters" + }, + "description": "Request object that contains the updated information for the access policy." + } + ], + "responses": { + "200": { + "description": "The access policy definition was successfully updated and is in the response.", + "schema": { + "$ref": "#/definitions/AccessPolicyResource" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or access policy could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + }, + "delete": { + "tags": [ + "AccessPolicies" + ], + "operationId": "AccessPolicies_Delete", + "x-ms-examples": { + "AccessPoliciesDelete": { + "$ref": "./examples/AccessPoliciesDelete.json" + } + }, + "description": "Deletes the access policy with the specified name in the specified subscription, resource group, and environment", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/AccessPolicyNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The access policy was successfully deleted." + }, + "204": { + "description": "The access policy was successfully deleted." + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, environment, or access policy could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.TimeSeriesInsights/environments/{environmentName}/accessPolicies": { + "get": { + "tags": [ + "AccessPolicies" + ], + "operationId": "AccessPolicies_ListByEnvironment", + "x-ms-examples": { + "AccessPoliciesByEnvironment": { + "$ref": "./examples/AccessPoliciesListByEnvironment.json" + } + }, + "description": "Lists all the available access policies associated with the environment.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "#/parameters/EnvironmentNameParameter" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "access policies returned successfully.", + "schema": { + "$ref": "#/definitions/AccessPolicyListResponse" + } + }, + "default": { + "description": "HTTP 404 (Not Found): The subscription, resource group, or environment could not be found.", + "schema": { + "$ref": "#/definitions/CloudError" + } + } + } + } + } + }, + "definitions": { + "OperationListResult": { + "description": "Result of the request to list Time Series Insights operations. It contains a list of operations and a URL link to get the next set of results.", + "properties": { + "value": { + "description": "List of Time Series Insights operations supported by the Microsoft.TimeSeriesInsights resource provider.", + "type": "array", + "readOnly": true, + "items": { + "$ref": "#/definitions/Operation" + } + }, + "nextLink": { + "description": "URL to get the next set of operation list results if there are any.", + "type": "string", + "readOnly": true + } + } + }, + "Operation": { + "description": "A Time Series Insights REST API operation", + "type": "object", + "properties": { + "name": { + "description": "The name of the operation being performed on this particular object.", + "type": "string", + "readOnly": true + }, + "display": { + "description": "Contains the localized display information for this particular operation / action.", + "readOnly": true, + "properties": { + "provider": { + "description": "The localized friendly form of the resource provider name.", + "type": "string", + "readOnly": true + }, + "resource": { + "description": "The localized friendly form of the resource type related to this action/operation.", + "type": "string", + "readOnly": true + }, + "operation": { + "description": "The localized friendly name for the operation.", + "type": "string", + "readOnly": true + }, + "description": { + "description": "The localized friendly description for the operation.", + "type": "string", + "readOnly": true + } + } + } + } + }, + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + } + }, + "description": "Time Series Insights resource", + "x-ms-azure-resource": true + }, + "TrackedResource": { + "properties": { + "location": { + "type": "string", + "description": "Resource location" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "required": [ + "location" + ], + "description": "Time Series Insights resource that is tracked by Azure Resource Manager." + }, + "ResourceProperties": { + "properties": { + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "Provisioning state of the resource.", + "enum": [ + "Accepted", + "Creating", + "Updating", + "Succeeded", + "Failed", + "Deleting" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": false + } + }, + "creationTime": { + "readOnly": true, + "type": "string", + "format": "date-time", + "description": "The time the resource was created." + } + }, + "description": "Properties that are common to all tracked resources." + }, + "Sku": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of this SKU.", + "enum": [ + "S1", + "S2" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + } + }, + "capacity": { + "format": "int32", + "type": "integer", + "description": "The capacity of the sku. This value can be changed to support scale out of environments after they have been created.", + "minimum": 1, + "maximum": 10 + } + }, + "required": [ + "name", + "capacity" + ], + "description": "The sku determines the capacity of the environment, the SLA (in queries-per-minute and total capacity), and the billing rate." + }, + "CreateOrUpdateTrackedResourceProperties": { + "properties": { + "location": { + "type": "string", + "description": "The location of the resource." + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs of additional properties for the resource." + } + }, + "required": [ + "location" + ], + "description": "Properties required to create any resource tracked by Azure Resource Manager." + }, + "EnvironmentCreateOrUpdateParameters": { + "properties": { + "sku": { + "$ref": "#/definitions/Sku" + }, + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EnvironmentCreationProperties" + } + }, + "required": [ + "sku", + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ], + "description": "Parameters supplied to the CreateOrUpdate Environment operation." + }, + "EnvironmentUpdateParameters": { + "type": "object", + "properties": { + "sku": { + "$ref": "#/definitions/Sku", + "description": "The sku of the environment." + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs of additional properties for the environment." + }, + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EnvironmentMutableProperties", + "description": "Properties of the environment." + } + }, + "description": "Parameters supplied to the Update Environment operation." + }, + "EnvironmentListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/EnvironmentResource" + }, + "description": "Result of the List Environments operation." + } + }, + "description": "The response of the List Environments operation." + }, + "EnvironmentResource": { + "properties": { + "sku": { + "$ref": "#/definitions/Sku" + }, + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EnvironmentResourceProperties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "An environment is a set of time-series data available for query, and is the top level Azure Time Series Insights resource." + }, + "EnvironmentCreationProperties": { + "properties": { + "dataRetentionTime": { + "type": "string", + "format": "duration", + "description": "ISO8601 timespan specifying the minimum number of days the environment's events will be available for query." + }, + "storageLimitExceededBehavior": { + "type": "string", + "description": "The behavior the Time Series Insights service should take when the environment's capacity has been exceeded. If \"PauseIngress\" is specified, new events will not be read from the event source. If \"PurgeOldData\" is specified, new events will continue to be read and old events will be deleted from the environment. The default behavior is PurgeOldData.", + "enum": [ + "PurgeOldData", + "PauseIngress" + ], + "x-ms-enum": { + "name": "StorageLimitExceededBehavior", + "modelAsString": false + } + } + }, + "required": [ + "dataRetentionTime" + ], + "description": "Properties used to create an environment." + }, + "EnvironmentResourceProperties": { + "properties": { + "dataAccessId": { + "readOnly": true, + "type": "string", + "format": "uuid", + "description": "An id used to access the environment data, e.g. to query the environment's events or upload reference data for the environment." + }, + "dataAccessFqdn": { + "readOnly": true, + "type": "string", + "description": "The fully qualified domain name used to access the environment data, e.g. to query the environment's events or upload reference data for the environment." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EnvironmentCreationProperties" + }, + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "required": [ + "dataRetentionTime" + ], + "description": "Properties of the environment." + }, + "EnvironmentMutableProperties": { + "description": "An object that represents a set of mutable environment resource properties.", + "type": "object", + "properties": { + "dataRetentionTime": { + "type": "string", + "format": "duration", + "description": "ISO8601 timespan specifying the minimum number of days the environment's events will be available for query." + } + } + }, + "EventSourceCreateOrUpdateParameters": { + "discriminator": "kind", + "properties": { + "kind": { + "type": "string", + "description": "The kind of the event source.", + "enum": [ + "Microsoft.EventHub", + "Microsoft.IoTHub" + ], + "x-ms-enum": { + "name": "Kind", + "modelAsString": false + } + } + }, + "required": [ + "kind" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation." + }, + "EventHubEventSourceCreateOrUpdateParameters": { + "x-ms-discriminator-value": "Microsoft.EventHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation for an EventHub event source." + }, + "IoTHubEventSourceCreateOrUpdateParameters": { + "x-ms-discriminator-value": "Microsoft.IoTHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceCreateOrUpdateParameters" + } + ], + "description": "Parameters supplied to the Create or Update Event Source operation for an IoTHub event source." + }, + "EventSourceUpdateParameters": { + "type": "object", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs of additional properties for the event source." + } + }, + "description": "Parameters supplied to the Update Event Source operation." + }, + "EventHubEventSourceUpdateParameters": { + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceMutableProperties", + "description": "Properties of the EventHub event source." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Event Source operation to update an EventHub event source." + }, + "IoTHubEventSourceUpdateParameters": { + "type": "object", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceMutableProperties", + "description": "Properties of the IoTHub event source." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceUpdateParameters" + } + ], + "description": "Parameters supplied to the Update Event Source operation to update an IoTHub event source." + }, + "EventSourceListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/EventSourceResource" + }, + "description": "Result of the List EventSources operation." + } + }, + "description": "The response of the List EventSources operation." + }, + "EventSourceResource": { + "type": "object", + "discriminator": "kind", + "properties": { + "kind": { + "type": "string", + "description": "The kind of the event source.", + "enum": [ + "Microsoft.EventHub", + "Microsoft.IoTHub" + ] + } + }, + "required": [ + "kind" + ], + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "An environment receives data from one or more event sources. Each event source has associated connection info that allows the Time Series Insights ingress pipeline to connect to and pull data from the event source" + }, + "EventHubEventSourceResource": { + "x-ms-discriminator-value": "Microsoft.EventHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/EventHubEventSourceResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceResource" + } + ], + "description": "An event source that receives its data from an Azure EventHub." + }, + "IoTHubEventSourceResource": { + "x-ms-discriminator-value": "Microsoft.IotHub", + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/IoTHubEventSourceResourceProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/EventSourceResource" + } + ], + "description": "An event source that receives its data from an Azure IoTHub." + }, + "EventSourceCommonProperties": { + "properties": { + "timestampPropertyName": { + "type": "string", + "description": "The event property that will be used as the event source's timestamp. If a value isn't specified for timestampPropertyName, or if null or empty-string is specified, the event creation time will be used." + } + }, + "allOf": [ + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "description": "Properties of the event source." + }, + "AzureEventSourceProperties": { + "properties": { + "eventSourceResourceId": { + "type": "string", + "description": "The resource id of the event source in Azure Resource Manager." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceCommonProperties" + } + ], + "required": [ + "eventSourceResourceId" + ], + "description": "Properties of an event source that reads events from an event broker in Azure." + }, + "EventHubEventSourceCommonProperties": { + "properties": { + "serviceBusNamespace": { + "type": "string", + "description": "The name of the service bus that contains the event hub." + }, + "eventHubName": { + "type": "string", + "description": "The name of the event hub." + }, + "consumerGroupName": { + "type": "string", + "description": "The name of the event hub's consumer group that holds the partitions from which events will be read." + }, + "keyName": { + "type": "string", + "description": "The name of the SAS key that grants the Time Series Insights service access to the event hub. The shared access policies for this key must grant 'Listen' permissions to the event hub." + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureEventSourceProperties" + } + ], + "required": [ + "serviceBusNamespace", + "eventHubName", + "consumerGroupName", + "keyName" + ], + "description": "Properties of the EventHub event source." + }, + "EventHubEventSourceCreationProperties": { + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the event hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventHubEventSourceCommonProperties" + } + ], + "required": [ + "sharedAccessKey" + ], + "description": "Properties of the EventHub event source that are required on create or update requests." + }, + "EventHubEventSourceResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/EventHubEventSourceCommonProperties" + } + ], + "description": "Properties of the EventHub event source resource." + }, + "IoTHubEventSourceCommonProperties": { + "properties": { + "iotHubName": { + "type": "string", + "description": "The name of the iot hub." + }, + "consumerGroupName": { + "type": "string", + "description": "The name of the iot hub's consumer group that holds the partitions from which events will be read." + }, + "keyName": { + "type": "string", + "description": "The name of the Shared Access Policy key that grants the Time Series Insights service access to the iot hub. This shared access policy key must grant 'service connect' permissions to the iot hub." + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureEventSourceProperties" + } + ], + "required": [ + "iotHubName", + "consumerGroupName", + "keyName" + ], + "description": "Properties of the IoTHub event source." + }, + "IoTHubEventSourceCreationProperties": { + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the Shared Access Policy key that grants the Time Series Insights service read access to the iot hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/IoTHubEventSourceCommonProperties" + } + ], + "required": [ + "sharedAccessKey" + ], + "description": "Properties of the IoTHub event source that are required on create or update requests." + }, + "IoTHubEventSourceResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/IoTHubEventSourceCommonProperties" + } + ], + "description": "Properties of the IoTHub event source resource." + }, + "LocalTimestamp": { + "description": "An object that represents the local timestamp property. It contains the format of local timestamp that needs to be used and the corresponding timezone offset information. If a value isn't specified for localTimestamp, or if null, then the local timestamp will not be ingressed with the events.", + "type": "object", + "properties": { + "format": { + "description": "An enum that represents the format of the local timestamp property that needs to be set.", + "type": "string", + "enum": [ + "Embedded", + "Iana", + "TimeSpan" + ], + "x-ms-enum": { + "name": "LocalTimestampFormat", + "modelAsString": false + } + }, + "timeZoneOffset": { + "description": "An object that represents the offset information for the local timestamp format specified. Should not be specified for LocalTimestampFormat - Embedded.", + "type": "object", + "properties": { + "propertyName": { + "type": "string", + "description": "The event property that will be contain the offset information to calculate the local timestamp. When the LocalTimestampFormat is Iana, the property name will contain the name of the column which contains IANA Timezone Name (eg: Americas/Los Angeles). When LocalTimestampFormat is Timespan, it contains the name of property which contains values representing the offset (eg: P1D or 1.00:00:00)" + } + } + } + } + }, + "EventSourceMutableProperties": { + "description": "An object that represents a set of mutable event source resource properties.", + "type": "object", + "properties": { + "timestampPropertyName": { + "type": "string", + "description": "The event property that will be used as the event source's timestamp. If a value isn't specified for timestampPropertyName, or if null or empty-string is specified, the event creation time will be used." + }, + "localTimestamp": { + "$ref": "#/definitions/LocalTimestamp" + } + } + }, + "EventHubEventSourceMutableProperties": { + "description": "An object that represents a set of mutable EventHub event source resource properties.", + "type": "object", + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the event hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceMutableProperties" + } + ] + }, + "IoTHubEventSourceMutableProperties": { + "description": "An object that represents a set of mutable IoTHub event source resource properties.", + "type": "object", + "properties": { + "sharedAccessKey": { + "type": "string", + "description": "The value of the shared access key that grants the Time Series Insights service read access to the iot hub. This property is not shown in event source responses." + } + }, + "allOf": [ + { + "$ref": "#/definitions/EventSourceMutableProperties" + } + ] + }, + "ReferenceDataSetCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/ReferenceDataSetCreationProperties" + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/CreateOrUpdateTrackedResourceProperties" + } + ] + }, + "ReferenceDataSetUpdateParameters": { + "type": "object", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs of additional properties for the reference data set." + } + }, + "description": "Parameters supplied to the Update Reference Data Set operation." + }, + "ReferenceDataSetListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/ReferenceDataSetResource" + }, + "description": "Result of the List Reference Data Sets operation." + } + }, + "description": "The response of the List Reference Data Sets operation." + }, + "ReferenceDataSetResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/ReferenceDataSetResourceProperties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "description": "A reference data set provides metadata about the events in an environment. Metadata in the reference data set will be joined with events as they are read from event sources. The metadata that makes up the reference data set is uploaded or modified through the Time Series Insights data plane APIs." + }, + "ReferenceDataSetCreationProperties": { + "properties": { + "keyProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/ReferenceDataSetKeyProperty" + }, + "description": "The list of key properties for the reference data set." + } + }, + "required": [ + "keyProperties" + ], + "description": "Properties used to create a reference data set." + }, + "ReferenceDataSetResourceProperties": { + "allOf": [ + { + "$ref": "#/definitions/ReferenceDataSetCreationProperties" + }, + { + "$ref": "#/definitions/ResourceProperties" + } + ], + "required": [ + "keyProperties" + ], + "description": "Properties of the reference data set." + }, + "ReferenceDataSetKeyProperty": { + "properties": { + "name": { + "type": "string", + "description": "The name of the key property." + }, + "type": { + "type": "string", + "description": "The type of the key property.", + "enum": [ + "String", + "Double", + "Bool", + "DateTime" + ], + "x-ms-enum": { + "name": "ReferenceDataKeyPropertyType", + "modelAsString": false + } + } + }, + "description": "A key property for the reference data set. A reference data set can have multiple key properties." + }, + "AccessPolicyCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyResourceProperties" + } + }, + "required": [ + "properties" + ] + }, + "AccessPolicyUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyMutableProperties" + } + }, + "required": [ + "properties" + ] + }, + "AccessPolicyListResponse": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/AccessPolicyResource" + }, + "description": "Result of the List access policies operation." + } + }, + "description": "The response of the List access policies operation." + }, + "AccessPolicyResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/AccessPolicyResourceProperties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "An access policy is used to grant users and applications access to the environment. Roles are assigned to service principals in Azure Active Directory. These roles define the actions the principal can perform through the Time Series Insights data plane APIs." + }, + "AccessPolicyResourceProperties": { + "properties": { + "principalObjectId": { + "type": "string", + "description": "The objectId of the principal in Azure Active Directory." + }, + "description": { + "type": "string", + "description": "An description of the access policy." + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "description": "A role defining the data plane operations that a principal can perform on a Time Series Insights client.", + "enum": [ + "Reader", + "Contributor" + ], + "x-ms-enum": { + "name": "AccessPolicyRole", + "modelAsString": false + } + }, + "description": "The list of roles the principal is assigned on the environment." + } + } + }, + "AccessPolicyMutableProperties": { + "description": "An object that represents a set of mutable access policy resource properties.", + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "An description of the access policy." + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "description": "A role defining the data plane operations that a principal can perform on a Time Series Insights client.", + "enum": [ + "Reader", + "Contributor" + ], + "x-ms-enum": { + "name": "AccessPolicyRole", + "modelAsString": false + } + }, + "description": "The list of roles the principal is assigned on the environment." + } + } + }, + "CloudError": { + "type": "object", + "properties": { + "error": { + "$ref": "#/definitions/CloudErrorBody" + } + }, + "description": "Contains information about an API error.", + "x-ms-external": true + }, + "CloudErrorBody": { + "type": "object", + "description": "Describes a particular API error with an error code and a message.", + "properties": { + "code": { + "type": "string", + "description": "An error code that describes the error condition more precisely than an HTTP status code. Can be used to programmatically handle specific error cases." + }, + "message": { + "type": "string", + "description": "A message that describes the error in detail and provides debugging information." + }, + "target": { + "type": "string", + "description": "The target of the particular error (for example, the name of the property in error)." + }, + "details": { + "type": "array", + "items": { + "$ref": "#/definitions/CloudErrorBody" + }, + "description": "Contains nested errors that are related to this error." + } + }, + "x-ms-external": true + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "description": "Azure Subscription ID.", + "required": true, + "type": "string" + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "Version of the API to be used with the client request. Current version is 2017-02-28-preview." + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Name of an Azure Resource group." + }, + "EnvironmentNameParameter": { + "name": "environmentName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights environment associated with the specified resource group.", + "x-ms-parameter-location": "method" + }, + "EventSourceNameParameter": { + "name": "eventSourceName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights event source associated with the specified environment.", + "x-ms-parameter-location": "method" + }, + "ReferenceDataSetNameParameter": { + "name": "referenceDataSetName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights reference data set associated with the specified environment.", + "x-ms-parameter-location": "method" + }, + "AccessPolicyNameParameter": { + "name": "accessPolicyName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Time Series Insights access policy associated with the specified environment.", + "x-ms-parameter-location": "method" + } + } +} From 56731da8c0d1f6ee255275b81e03ab148c075990 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 19 Aug 2020 16:28:43 +0800 Subject: [PATCH 43/61] Fix some issues in m4 test (#671) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential * Add two m4 configuration and fix some issues * Add support for enum with one value * Fixed an enum related issue and add some RPs in the test * Fix some issues in m4 test --- tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md | 2 -- .../functions/helpers/ManagedIdentity/readme.noprofile.md | 4 +++- tests-upgrade/functions/helpers/Storage/readme.noprofile.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md b/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md index 9563f3d19db..114f3c1d6f2 100644 --- a/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md +++ b/tests-upgrade/functions/helpers/KeyVault/readme.noprofile.md @@ -10,8 +10,6 @@ input-file: # subject-prefix: '' directive: - # Remove unnedded cmdlets - - remove-operation: Operations_List # hide all cmdlets - where: subject: ^VaultDeleted$|^Vault$|^VaultNameAvailability$|^VaultAccessPolicy$ diff --git a/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md b/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md index 182ddc3f059..cc028e4031b 100644 --- a/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md +++ b/tests-upgrade/functions/helpers/ManagedIdentity/readme.noprofile.md @@ -11,7 +11,9 @@ subject-prefix: '' directive: # Remove unnedded cmdlets - - remove-operation: Operations_List + - where: + subject: ^Operation$ + remove: true # Hide Storage Account cmdlets - where: diff --git a/tests-upgrade/functions/helpers/Storage/readme.noprofile.md b/tests-upgrade/functions/helpers/Storage/readme.noprofile.md index 8aabb9ae9db..a2bbb2b9471 100644 --- a/tests-upgrade/functions/helpers/Storage/readme.noprofile.md +++ b/tests-upgrade/functions/helpers/Storage/readme.noprofile.md @@ -53,7 +53,7 @@ In this directory, run AutoRest: require: - $(this-folder)/../../../readme.azure.noprofile.md input-file: - #- $(repo)/specification/storage/resource-manager/Microsoft.Storage/stable/2019-04-01/storage.json + - $(repo)/specification/storage/resource-manager/Microsoft.Storage/stable/2019-04-01/storage.json - $(repo)/specification/storage/resource-manager/Microsoft.Storage/stable/2019-04-01/blob.json subject-prefix: '' From 9403b4ffae6eeaac858b36a158aab22f599427d5 Mon Sep 17 00:00:00 2001 From: xichen Date: Thu, 20 Aug 2020 13:52:47 +0800 Subject: [PATCH 44/61] skip content type request parameter (#673) Co-authored-by: xichen --- powershell/autorest-configuration.md | 1 + powershell/llcsharp/operation/method.ts | 16 +++++++++------- powershell/plugins/create-commands-v2.ts | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 3426260430a..3fe44180218 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -10,6 +10,7 @@ modelerfour: emit-yaml-tags: false lenient-model-deduplication: true additional-checks: false + always-create-content-type-parameter: false ``` > if the modeler is loaded already, use that one, otherwise grab it. diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index f20a51ef635..127dc877cce 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -348,13 +348,15 @@ export class NewOperationMethod extends Method { // add body paramter if there should be one. if (this.operation.requests && this.operation.requests.length && this.operation.requests[0].parameters && this.operation.requests[0].parameters.length) { // this request does have a request body. - const param = this.operation.requests[0].parameters[0]; - this.bodyParameter = new NewOperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { - // TODO: temp solution. We need a class like NewKnowMediaType - mediaType: knownMediaType(KnownMediaType.Json), - contentType: KnownMediaType.Json - }); - this.addParameter(this.bodyParameter); + const param = this.operation.requests[0].parameters.find((p) => !p.origin || p.origin.indexOf('modelerfour:synthesized') < 0); + if (param) { + this.bodyParameter = new NewOperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { + // TODO: temp solution. We need a class like NewKnowMediaType + mediaType: knownMediaType(KnownMediaType.Json), + contentType: KnownMediaType.Json + }); + this.addParameter(this.bodyParameter); + } } for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index 25f558d4d7c..d1e71f4d10e 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -408,7 +408,7 @@ export /* @internal */ class Inferrer { // the body parameter // xichen: How to handle if has multiple requests? - const body = (operation.requests && operation.requests[0].parameters) ? operation.requests[0].parameters[0] : null; + const body = operation.requests?.[0].parameters?.find((p) => !p.origin || p.origin.indexOf('modelerfour:synthesized') < 0) || null; // skip-for-time-being, looks x-ms-requestBody-name is not supported any more //const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : ''; const bodyParameterName = body ? body.language.default.name : ''; From d4ce30095da76085c271277f63f51da4dd8fd785 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 21 Aug 2020 10:56:55 +0800 Subject: [PATCH 45/61] Use the latest m4 (#674) * Add databricks, fix several issues * Fixed a completer related issue and add support for credential * Add two m4 configuration and fix some issues * Add support for enum with one value * Fixed an enum related issue and add some RPs in the test * Fix some issues in m4 test * just for test, do not merge * Update autorest-configuration.md --- powershell/autorest-configuration.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 3fe44180218..cf1aba9ddd2 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -11,6 +11,7 @@ modelerfour: lenient-model-deduplication: true additional-checks: false always-create-content-type-parameter: false + always-seal-x-ms-enums: true ``` > if the modeler is loaded already, use that one, otherwise grab it. @@ -18,7 +19,8 @@ modelerfour: ``` yaml use-extension: "@autorest/remodeler" : "~2.1.0" - "@autorest/modelerfour": "4.15.378" + #"@autorest/modelerfour": "4.15.378" + "@autorest/modelerfour": "http://tinyurl.com/y2r8qhs4" # will use highest 2.0.x ``` @@ -468,4 +470,4 @@ cli: choiceValue: 'pascal' constant: 'pascal' type: 'pascal' -``` \ No newline at end of file +``` From 078f32bb66e4fcd79b25ac68255f0d2c84f00c50 Mon Sep 17 00:00:00 2001 From: xichen Date: Mon, 24 Aug 2020 12:04:35 +0800 Subject: [PATCH 46/61] Fix choice issue (#675) Co-authored-by: xichen --- powershell/internal/project.ts | 6 ++++-- powershell/llcsharp/schema/schema-resolver.ts | 6 +----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 7724490d74a..1d0feb10bb0 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -17,7 +17,7 @@ import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; -import { BooleanSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; +import { BooleanSchema, ChoiceSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -72,7 +72,9 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { try { if (!this.inResolve) { this.inResolve = true; - if (schema && (schema.type === SchemaType.Boolean || (schema.type === SchemaType.Constant && (schema).valueType.type === SchemaType.Boolean))) { + if (schema && (schema.type === SchemaType.Boolean + || (schema.type === SchemaType.Constant && (schema).valueType.type === SchemaType.Boolean) + || (schema.type === SchemaType.Choice && (schema).choiceType.type === SchemaType.Boolean))) { return new NewPSSwitch(schema, required); } } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 40e25040299..fe51afa73ef 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -238,11 +238,7 @@ export class NewSchemaDefinitionResolver { return this.resolveTypeDeclaration((schema).valueType, required, state); case SchemaType.Choice: { - const choiceSchema = schema as ChoiceSchema; - if ((choiceSchema.choiceType).type === SchemaType.DateTime && (choiceSchema.choiceType).format === StringFormat.DateTimeRfc1123) { - return new NewDateTime1123(schema as DateTimeSchema, required); - } - return new NewString(schema, required); + return this.resolveTypeDeclaration((schema).choiceType, required, state); } case SchemaType.SealedChoice: if (schema.language.default.skip === true) { From 2b337ef947ec5da1f85b5b2107e86fa771171db1 Mon Sep 17 00:00:00 2001 From: xichen Date: Tue, 25 Aug 2020 14:47:20 +0800 Subject: [PATCH 47/61] Fix enum boolean response which has only one value (#676) Co-authored-by: xichen --- powershell/cmdlets/class.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 6e4b01d967e..13091709d02 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; +import { Schema as NewSchema, SchemaType, ArraySchema, SchemaResponse, HttpParameter, ObjectSchema, DictionarySchema, ChoiceSchema, SealedChoiceSchema } from '@azure-tools/codemodel'; import { command, getAllProperties, JsonType, http, getAllPublicVirtualProperties, getVirtualPropertyFromPropertyName, ParameterLocation, getAllVirtualProperties, VirtualParameter, VirtualProperty } from '@azure-tools/codemodel-v3'; import { CommandOperation, VirtualParameter as NewVirtualParameter } from '../utils/command-operation'; import { getAllProperties as NewGetAllProperties, getAllPublicVirtualProperties as NewGetAllPublicVirtualProperties, getVirtualPropertyFromPropertyName as NewGetVirtualPropertyFromPropertyName, VirtualProperty as NewVirtualProperty } from '../utils/schema'; @@ -2665,7 +2665,9 @@ export class NewCmdletClass extends Class { const resultSchema = length(props) !== 1 ? schema : props[0].schema; // make sure return type for boolean stays boolean! - if (resultSchema.type === SchemaType.Boolean) { + if (resultSchema.type === SchemaType.Boolean || + (resultSchema.type === SchemaType.Choice && (resultSchema).choiceType.type === SchemaType.Boolean && (resultSchema).choices.length === 1) || + (resultSchema.type === SchemaType.SealedChoice && (resultSchema).choiceType.type === SchemaType.Boolean && (resultSchema).choices.length === 1)) { outputTypes.add(`typeof(${dotnet.Bool})`); } else { const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state); From 589b23accc5201f78b7732bdc956cd5d326759ee Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 26 Aug 2020 10:12:38 +0800 Subject: [PATCH 48/61] Enable two test cases, and drop the workaround for x-ms-enum (#677) --- tests-upgrade/Configuration.json | 2 ++ tests-upgrade/readme.azure.noprofile.md | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 380e8a9c98c..9d25b6c293d 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -23,6 +23,7 @@ "datamodels-datatypes-array", "datamodels-datatypes-integer", "datamodels-datatypes-string", + "datamodels-datatypes-object", "datamodels-combineschema", "directive-model", "directive-tableformat", @@ -30,6 +31,7 @@ "extension-ms-clientflatten", "extension-ms-clientname", "extension-ms-discriminatorvalue", + "extension-ms-enum", "extension-ms-examples", "extension-ms-longruningoperation", "extension-ms-mutability", diff --git a/tests-upgrade/readme.azure.noprofile.md b/tests-upgrade/readme.azure.noprofile.md index 31602028ac6..82284693a17 100644 --- a/tests-upgrade/readme.azure.noprofile.md +++ b/tests-upgrade/readme.azure.noprofile.md @@ -44,7 +44,4 @@ directive: set: default: script: '(Get-AzContext).Subscription.Id' - - from: swagger-document - where: $ - transform: return $.replace(/"modelAsString":\ true/g, '"modelAsString":\ false') ``` \ No newline at end of file From 1c7f54cb0e1aafd8bdab2c7ffc4521b58312c391 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Wed, 26 Aug 2020 13:53:43 +0800 Subject: [PATCH 49/61] Upgrade modelerfour to 4.15.414 (#679) --- powershell/autorest-configuration.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index cf1aba9ddd2..048f6282ca0 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -19,8 +19,7 @@ modelerfour: ``` yaml use-extension: "@autorest/remodeler" : "~2.1.0" - #"@autorest/modelerfour": "4.15.378" - "@autorest/modelerfour": "http://tinyurl.com/y2r8qhs4" + "@autorest/modelerfour": "4.15.414" # will use highest 2.0.x ``` From 01e526eb8104437d176a9a1b439d2e86e20c0805 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 31 Aug 2020 20:17:28 +0800 Subject: [PATCH 50/61] Add utils folder include a script to decrypt securestring (#682) * Enable two test cases, and drop the workaround for x-ms-enum * Add utils folder include a script to decrypt securestring --- powershell/autorest-configuration.md | 1 + powershell/generators/nuspec.ts | 1 + powershell/internal/project.ts | 4 ++++ powershell/plugins/powershell-v2.ts | 3 +++ .../resources/utils/Unprotect-SecureString.ps1 | 16 ++++++++++++++++ tests-upgrade/AutoRestUpgradeTest.ps1 | 7 +++++-- 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 powershell/resources/utils/Unprotect-SecureString.ps1 diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 048f6282ca0..2c9dd6aacab 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -63,6 +63,7 @@ module-folder: $(current-folder)/generated cmdlet-folder: $(module-folder)/cmdlets model-cmdlet-folder: $(module-folder)/model-cmdlets custom-cmdlet-folder: $(current-folder)/custom +utils-cmdlet-folder: $(current-folder)/utils internal-cmdlet-folder: $(current-folder)/internal test-folder: $(current-folder)/test runtime-folder: $(module-folder)/runtime diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index fb44a1df572..598b8250418 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -41,6 +41,7 @@ export async function generateNuspec(project: Project | NewProject) { + `, undefined, 'source-file-other'); } diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 1d0feb10bb0..9afaf33d7e8 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -92,6 +92,7 @@ export class Project extends codeDomProject { public cmdletFolder!: string; public customFolder!: string; + public utilsFolder!: string; public internalFolder!: string; public testFolder!: string; public runtimeFolder!: string; @@ -193,6 +194,7 @@ export class Project extends codeDomProject { this.cmdletFolder = await this.state.getValue('cmdlet-folder'); this.customFolder = await this.state.getValue('custom-cmdlet-folder'); + this.utilsFolder = await this.state.getValue('utils-cmdlet-folder'); this.internalFolder = await this.state.getValue('internal-cmdlet-folder'); this.testFolder = await this.state.getValue('test-folder'); this.runtimeFolder = await this.state.getValue('runtime-folder'); @@ -250,6 +252,7 @@ export class NewProject extends codeDomProject { public cmdletFolder!: string; public customFolder!: string; + public utilsFolder!: string; public internalFolder!: string; public testFolder!: string; public runtimeFolder!: string; @@ -353,6 +356,7 @@ export class NewProject extends codeDomProject { this.cmdletFolder = await this.state.getValue('cmdlet-folder'); this.customFolder = await this.state.getValue('custom-cmdlet-folder'); + this.utilsFolder = await this.state.getValue('utils-cmdlet-folder'); this.internalFolder = await this.state.getValue('internal-cmdlet-folder'); this.testFolder = await this.state.getValue('test-folder'); this.runtimeFolder = await this.state.getValue('runtime-folder'); diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts index 12d8802b7b1..b92c5643a41 100644 --- a/powershell/plugins/powershell-v2.ts +++ b/powershell/plugins/powershell-v2.ts @@ -32,6 +32,9 @@ async function copyRequiredFiles(project: NewProject) { // Runtime files await copyResources(join(resources, 'psruntime'), async (fname, content) => project.state.writeFile(join(project.runtimeFolder, fname), content, undefined, sourceFileCSharp), project.overrides, transformOutput); + // utils cmdlets + await copyResources(join(resources, 'utils'), async (fname, content) => project.state.writeFile(join(project.utilsFolder, fname), content, undefined, sourceFileCSharp), project.overrides, transformOutput); + // Modules files await copyBinaryResources(join(resources, 'modules'), async (fname, content) => project.state.writeFile(join(project.dependencyModuleFolder, fname), content, undefined, 'binary-file')); diff --git a/powershell/resources/utils/Unprotect-SecureString.ps1 b/powershell/resources/utils/Unprotect-SecureString.ps1 new file mode 100644 index 00000000000..cb05b51a622 --- /dev/null +++ b/powershell/resources/utils/Unprotect-SecureString.ps1 @@ -0,0 +1,16 @@ +#This script converts securestring to plaintext + +param( + [Parameter(Mandatory, ValueFromPipeline)] + [System.Security.SecureString] + ${SecureString} +) + +$ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString) +try { + $plaintext = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr) +} finally { + [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr) +} + +return $plaintext \ No newline at end of file diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index 938758f39bf..66c2e796052 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -66,6 +66,9 @@ function IsNeedIgnore([string]$inputFileName , [Array]$ignoreArray) { $Ignore =$True break + } elseif ($ignoreDetail.Contains("*.") -and $inputFileName.EndsWith($ignoreDetail.Split(".")[-1])) { + $Ignore =$True + break } } return $Ignore @@ -117,8 +120,8 @@ function CompareGeneratedCode([string]$inputSourcePath,[string]$inputTargetPath, #in m3Path cd $inputSourcePath $initFileList = Get-ChildItem -Recurse -force - $initIgnoreFileList = (($inputSourcePath+'\generated\modules'), ($inputSourcePath+'\.gitignore'),($inputSourcePath+'\tools\Resources\.gitignore')) - $targetIgnoreFileList = (($inputTargetPath+'\generated\modules'), ($inputTargetPath+'\.gitignore'),($inputTargetPath+'\tools\Resources\.gitignore')) + $initIgnoreFileList = (($inputSourcePath+'\generated\modules'), ($inputSourcePath+'\utils'), ($inputSourcePath+'\*.nuspec'), ($inputSourcePath+'\.gitignore'),($inputSourcePath+'\tools\Resources\.gitignore')) + $targetIgnoreFileList = (($inputTargetPath+'\generated\modules'), ($inputTargetPath+'\utils'),($inputTargetPath+'\*.nuspec'),($inputTargetPath+'\.gitignore'),($inputTargetPath+'\tools\Resources\.gitignore')) #foreach initFileList and get the hashcode of them foreach( $initFile in $initFileList) { From 5bfd3a1e6b84c6455799103f30e50cf64a049c59 Mon Sep 17 00:00:00 2001 From: Yeming Liu Date: Tue, 1 Sep 2020 15:53:37 +0800 Subject: [PATCH 51/61] fix deserialize dictionary value bug (#684) --- powershell/llcsharp/model/model-class-json.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 08496a9350c..5af56bcfe27 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -30,6 +30,7 @@ import { popTempVar, pushTempVar } from '../schema/primitive'; import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; +import { NewModelInterface } from './interface'; export class JsonSerializableClass extends Class { private btj!: Method; @@ -299,8 +300,9 @@ export class NewJsonSerializableClass extends Class { // wildcard style deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); - } else if (vType instanceof ObjectImplementation) { - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${this.modelClass.fullName}.FromJson(j) ,${exclusions.value} );`)); + } else if (vType instanceof NewModelInterface) { + // use the class of the dictionary value to deserialize values + deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${vType.classImplementation.fullName}.FromJson(j) ,${exclusions.value} );`)); } else { deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, null ,${exclusions.value} );`)); } From 7cb3568b0f877fec70eb361fe81cb6bf77ecdcdc Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 1 Sep 2020 16:52:17 +0800 Subject: [PATCH 52/61] Generate model for all the dictionaries and add support for unixtime (#685) * Enable two test cases, and drop the workaround for x-ms-enum * Add utils folder include a script to decrypt securestring * Generate model for all the dictionaries and add support for unixtime --- powershell/llcsharp/model/namespace.ts | 5 ++ powershell/llcsharp/schema/schema-resolver.ts | 5 +- tests-upgrade/Configuration.json | 1 + .../datamodels-datatypes-unixtime/readme.md | 10 +++ .../swagger.json | 76 +++++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 tests-upgrade/datamodels-datatypes-unixtime/readme.md create mode 100644 tests-upgrade/datamodels-datatypes-unixtime/swagger.json diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 57680266b50..58d0d0d64ac 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -179,6 +179,11 @@ export class NewModelsNamespace extends Namespace { this.NewResolveTypeDeclaration(schema, true, state); } } + if (schemas.dictionaries) { + for (const schema of schemas.dictionaries) { + this.NewResolveTypeDeclaration(schema, true, state); + } + } if (schemas.any) { for (const schema of schemas.any) { diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index fe51afa73ef..bd1eab1c708 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel'; +import { codeModelSchema, ArraySchema, UnixTimeSchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel'; import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; @@ -222,6 +222,9 @@ export class NewSchemaDefinitionResolver { // fallback to int if the format isn't recognized return new NewNumeric(schema, required, required ? 'int' : 'int?'); + case SchemaType.UnixTime: + return new NewUnixTime(schema, required); + case SchemaType.Number: switch ((schema).precision) { case 64: diff --git a/tests-upgrade/Configuration.json b/tests-upgrade/Configuration.json index 9d25b6c293d..045f89ef52b 100644 --- a/tests-upgrade/Configuration.json +++ b/tests-upgrade/Configuration.json @@ -24,6 +24,7 @@ "datamodels-datatypes-integer", "datamodels-datatypes-string", "datamodels-datatypes-object", + "datamodels-datatypes-unixtime", "datamodels-combineschema", "directive-model", "directive-tableformat", diff --git a/tests-upgrade/datamodels-datatypes-unixtime/readme.md b/tests-upgrade/datamodels-datatypes-unixtime/readme.md new file mode 100644 index 00000000000..cd6b9c0ac24 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-unixtime/readme.md @@ -0,0 +1,10 @@ +### AutoRest Configuration +> see https://aka.ms/autorest + +``` yaml +require: + - $(this-folder)/../readme.azure.noprofile.md +input-file: + - $(this-folder)/swagger.json + +``` diff --git a/tests-upgrade/datamodels-datatypes-unixtime/swagger.json b/tests-upgrade/datamodels-datatypes-unixtime/swagger.json new file mode 100644 index 00000000000..27427d16396 --- /dev/null +++ b/tests-upgrade/datamodels-datatypes-unixtime/swagger.json @@ -0,0 +1,76 @@ +{ + "swagger": "2.0", + "info": { + "title": "DatabricksClient", + "version": "2018-04-01", + "description": "ARM Databricks" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/resourceGroup": { + "get": { + "tags": [ + "Workspaces" + ], + "operationId": "Workspaces_Get", + "description": "Gets the workspace.", + "responses": { + "200": { + "description": "OK-Return workspace." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "#/definitions/BasicErrorModel" + } + } + } + } + } + }, + "definitions": { + "BasicErrorModel": { + "type": "object", + "required": [ + "message", + "code" + ], + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer", + "format": "unixtime" + } + } + } + } +} \ No newline at end of file From aa99bef23d1caed3418f0dff48a3b7067737e4f1 Mon Sep 17 00:00:00 2001 From: Yeming Liu Date: Tue, 8 Sep 2020 10:59:52 +0800 Subject: [PATCH 53/61] git clone need not --recurse (#686) --- docs/development.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/development.md b/docs/development.md index 6ea7880855d..b87b03c6841 100644 --- a/docs/development.md +++ b/docs/development.md @@ -14,11 +14,9 @@ Use of this project requires the following: ## Cloning this repository -Make sure that you clone this repository with `--recurse` - there is a submodule with common code that we pull from the `https://github.com/azure/perks` project. - ``` powershell # clone recursively -git clone https://github.com/azure/autorest.powershell --recurse +git clone https://github.com/azure/autorest.powershell # one-time cd autorest.powershell From c923769420da05be5581f9081c0c39d0c652c362 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 14 Sep 2020 20:35:15 +0800 Subject: [PATCH 54/61] handle duplicated properties in parentes, fixes https://github.com/Azure/autorest.powershell/issues/688 (#690) * handle duplicated properties in parentes, fixes https://github.com/Azure/autorest.powershell/issues/688 * Remove no-needed comments --- powershell/plugins/plugin-tweak-model.ts | 88 +++++++++++++----------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 83a0401fc44..bb2b2cdd569 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Property, SealedChoiceSchema, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema } from '@azure-tools/codemodel'; +import { Property, SealedChoiceSchema, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema, ConditionalValue } from '@azure-tools/codemodel'; //import { ModelState } from '@azure-tools/codemodel-v3'; //import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; @@ -35,38 +35,40 @@ export function titleToAzureServiceName(title: string): string { } -// function dropDuplicatePropertiesInChildSchemas(schema: Schema, state: State, map: Map = new Map()) { -// let success = true; -// for (const parent of values(schema.allOf)) { -// handle parents first -// if (!dropDuplicatePropertiesInChildSchemas(parent, state, map)) { -// return false; -// } -// } -// for (const { key: id, value: property } of items(schema.properties)) { -// see if it's in the parent. -// const pProp = map.get(property.serializedName); -// if (pProp) { -// if the parent prop is the same type as the child prop -// we're going to drop the child property. -// if (pProp.schema.type === property.schema.type) { -// if it's an object type, it has to be the exact same schema type too -// if (pProp.schema.type != JsonType.Object || pProp.schema === property.schema) { -// state.verbose(`Property '${property.serializedName}' in '${schema.details.default.name}' has a property the same as the parent, and is dropping the duplicate.`, {}); -// delete schema.properties[id]; -// } else { -// const conflict = `Property '${property.serializedName}' in '${schema.details.default.name}' has a conflict with a parent schema (allOf ${schema.allOf.joinWith(each => each.details.default.name)}.`; -// state.error(conflict, [], {}); -// success = false; -// } -// } -// } -// else { -// map.set(property.serializedName, property); -// } -// } -// return success; -// } +function dropDuplicatePropertiesInChildSchemas(schema: ObjectSchema, state: State, map: Map = new Map()) { + let success = true; + for (const parent of values(schema.parents?.immediate)) { + //handle parents first + if (!dropDuplicatePropertiesInChildSchemas(parent, state, map)) { + return false; + } + } + for (const { key: id, value: property } of items(schema.properties)) { + //see if it's in the parent. + const pProp = map.get(property.serializedName); + if (pProp) { + //if the parent prop is the same type as the child prop + //we're going to drop the child property. + if (pProp.schema.type === property.schema.type) { + //if it's an object type, it has to be the exact same schema type too + if (pProp.schema.type != SchemaType.Object || pProp.schema === property.schema) { + state.verbose(`Property '${property.serializedName}' in '${schema.language.default.name}' has a property the same as the parent, and is dropping the duplicate.`, {}); + if (schema.properties) { + delete schema.properties[id]; + } + } else { + const conflict = `Property '${property.serializedName}' in '${schema.language.default.name}' has a conflict with a parent schema (allOf ${schema.parents?.immediate.joinWith(each => each.language.default.name)}.`; + state.error(conflict, [], {}); + success = false; + } + } + } + else { + map.set(property.serializedName, property); + } + } + return success; +} async function tweakModelV2(state: State): Promise { const title = pascalCase(fixLeadingNumber(deconstruct(await state.getValue('title', state.model.info.title)))); @@ -142,16 +144,15 @@ async function tweakModelV2(state: State): Promise { // } // } - // xichen: should be no duplicate properties in m4. Skip // schemas that have parents and implement properties that are in the parent schemas // will have the property dropped in the child schema - // for (const schema of values(model.schemas)) { - // if (length(schema.allOf) > 0) { - // if (!dropDuplicatePropertiesInChildSchemas(schema, state)) { - // throw new Error('Schemas are in conflict.'); - // } - // } - // } + for (const schema of values(model.schemas.objects)) { + if (length(schema.parents?.immediate) > 0) { + if (!dropDuplicatePropertiesInChildSchemas(schema, state)) { + throw new Error('Schemas are in conflict.'); + } + } + } if (await state.getValue('use-storage-pipeline', false)) { @@ -310,6 +311,9 @@ async function tweakModelV2(state: State): Promise { // identify properties that are constants for (const schema of values(schemas.objects)) { for (const property of values(schema.properties)) { + if (property === undefined) { + continue; + } if (property.required) { if (property.schema.type === SchemaType.Choice) { const choiceSchema = property.schema as ChoiceSchema; @@ -637,4 +641,4 @@ export async function tweakModelPlugin(service: Host) { //const result = tweakModelV2(session); await service.WriteFile('code-model-v4-tweakcodemodel-v2.yaml', serialize(await tweakModelV2(state)), undefined, 'code-model-v4'); //return processCodeModel(tweakModelV2, service, 'tweakcodemodel-v2'); -} \ No newline at end of file +} From ee9a56857e2683ddbd12e040eb344b64c7890d9f Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 18 Sep 2020 18:49:31 +0800 Subject: [PATCH 55/61] Add support for no-inline (#691) --- .../plugins/plugin-create-inline-properties.ts | 2 +- powershell/plugins/plugin-tweak-m4-model.ts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index f05e414f25a..2d4227bd097 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -160,7 +160,7 @@ function createVirtualProperties(schema: ObjectSchema, stack: Array, thr // dolauli pay attention to the condition check const isDict = property.schema.type === SchemaType.Dictionary || (property.schema).parents?.immediate?.find((s) => s.type === SchemaType.Dictionary); const canInline = - // (!property.schema.details.default['skip-inline']) && + (!property.schema.language.default['skip-inline']) && (!property.schema.language.default.byReference) && (!isDict) && (property.schema).language.default.inline === 'yes'; diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index b9a75942066..3a50303699a 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -7,11 +7,14 @@ import { serialize } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { NewModelState } from '../utils/model-state'; import { StatusCodes } from '../utils/http-definitions'; +import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Host } from '@azure-tools/autorest-extension-base'; type State = NewModelState; +let directives: Array = []; + async function tweakModel(state: State): Promise { const model = state.model; @@ -21,9 +24,22 @@ async function tweakModel(state: State): Promise { removeM4DefaultDescription(model); + handleNoinlineDirective(state); + return model; } +function handleNoinlineDirective(state: State) { + var inlineModels: string[] = new Array; + for (const directive of directives.filter(each => each['no-inline'])) { + inlineModels = inlineModels.concat(>values(directive['no-inline']).toArray()); + } + for (const model of state.model.schemas.objects || []) { + if (inlineModels.includes(model.language.default.name)) { + model.language.default['skip-inline'] = true; + } + } +} function addResponseHeaderSchema(model: CodeModel) { // In remodeler, each operations response headers will has its own scheam. Each header will be schema's property. // But in m4, if 'schema' is not explicitly defined, even 'headers' is specified, there won't be a schema for headers. @@ -153,6 +169,8 @@ function recursiveRemoveM4DefaultDescription(schema: Schema, visited: Set(service).init(); service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } From ac262b194016fd8e2f247d982443a48e20511252 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Mon, 12 Oct 2020 14:54:25 +0800 Subject: [PATCH 56/61] Add support support for API, whose request body is just an object without specifying any details (#694) --- powershell/plugins/create-commands-v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index d1e71f4d10e..d53d8132d1e 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -288,7 +288,7 @@ export /* @internal */ class Inferrer { // let's add a variant where it's expanded out. // *IF* the body is an object or dictionary - if (body.schema.type === SchemaType.Object || body.schema.type === SchemaType.Dictionary) { + if (body.schema.type === SchemaType.Object || body.schema.type === SchemaType.Dictionary || body.schema.type === SchemaType.Any) { const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); opExpanded.details.default.dropBodyParameter = true; opExpanded.parameters.push(new IParameter(`${bodyParameterName}Body`, body.schema, { From ce56adb72296bb6176958618a3ce5830330aa538 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 13 Oct 2020 10:15:13 +0800 Subject: [PATCH 57/61] M4 master merge (#695) * Emit Signal method and delegate to provide a hook into events * Update Az.Accounts dependency to 1.8.4 * Adding target attribute to nuspec file elements * Using backslash path separator in nuspec for cross platform compatability * Remove Init method constructor call. * Revert "Emit Signal method and delegate to provide a hook into events" * Emit Signal method and delegate to provide hook into events for Non-Azure scenarios. * Update ISendAsync.cs (#662) * Update ISendAsync.cs pass only Authorization to next header for long running operations. * Update ISendAsync.cs * Update ISendAsync.cs fix potential null reference * Update ISendAsync.cs * Update ISendAsync.cs * Update ISendAsync.cs * update gitignore (#670) * Add scan pipelines (#681) * Update development.md - add how to debug (#683) * Update development.md * Update development.md * Fix some merging issues Co-authored-by: George Ndungu Co-authored-by: Tim Mullender Co-authored-by: Yabo Hu Co-authored-by: Yeming Liu Co-authored-by: Dingmeng Xue --- .azure-pipelines/credscan-suppressions.json | 0 .azure-pipelines/daily-build.yml | 50 ++ .azure-pipelines/security-scan.yml | 15 + docs/development.md | 3 +- powershell/cmdlets/class.ts | 8 + powershell/generators/gitignore.ts | 1 + powershell/generators/nuspec.ts | 12 +- powershell/internal/project.ts | 4 +- powershell/module/module-class.ts | 61 +++ .../assets/tools/Resources/readme.md | 2 +- .../1.7.4/Accounts.generated.format.ps1xml | 422 ---------------- .../Az.Accounts/1.7.4/Accounts.types.ps1xml | 281 ----------- .../Az.Accounts/1.7.4/Az.Accounts.psm1 | 319 ------------ ...PowerShell.Authentication.Abstractions.dll | Bin 100432 -> 0 bytes ...erShell.Authentication.ResourceManager.dll | Bin 70008 -> 0 bytes .../{1.7.4 => 1.8.1}/Accounts.format.ps1xml | 264 +++++----- .../1.8.1/Accounts.generated.format.ps1xml | 422 ++++++++++++++++ .../Az.Accounts/1.8.1/Accounts.types.ps1xml | 281 +++++++++++ .../{1.7.4 => 1.8.1}/Az.Accounts.nuspec | 4 +- .../{1.7.4 => 1.8.1}/Az.Accounts.psd1 | 276 +++++----- .../Az.Accounts/1.8.1/Az.Accounts.psm1 | 339 +++++++++++++ .../{1.7.4 => 1.8.1}/Hyak.Common.dll | Bin .../Microsoft.ApplicationInsights.dll | Bin .../Microsoft.Azure.Common.dll | Bin ...PowerShell.Authentication.Abstractions.dll | Bin 0 -> 101760 bytes ...l.Authentication.ResourceManager.deps.json | 258 +++++----- ...erShell.Authentication.ResourceManager.dll | Bin 0 -> 70520 bytes ....Azure.PowerShell.Authentication.deps.json | 228 ++++----- ...rosoft.Azure.PowerShell.Authentication.dll | Bin 105848 -> 105848 bytes ...Microsoft.Azure.PowerShell.Clients.Aks.dll | Bin 89168 -> 88960 bytes ...Azure.PowerShell.Clients.Authorization.dll | Bin 150096 -> 149880 bytes ...osoft.Azure.PowerShell.Clients.Compute.dll | Bin 1418824 -> 1418616 bytes ...ft.Azure.PowerShell.Clients.Graph.Rbac.dll | Bin 578128 -> 577920 bytes ...soft.Azure.PowerShell.Clients.KeyVault.dll | Bin 121936 -> 121720 bytes ...osoft.Azure.PowerShell.Clients.Monitor.dll | Bin 412744 -> 412536 bytes ...osoft.Azure.PowerShell.Clients.Network.dll | Bin 1687624 -> 1687416 bytes ...zure.PowerShell.Clients.PolicyInsights.dll | Bin 177232 -> 177016 bytes ...ure.PowerShell.Clients.ResourceManager.dll | Bin 1109584 -> 1109368 bytes ....PowerShell.Clients.Storage.Management.dll | Bin 132688 -> 132472 bytes ...soft.Azure.PowerShell.Clients.Websites.dll | Bin 3271272 -> 3271040 bytes ...zure.PowerShell.Cmdlets.Accounts.deps.json | 288 +++++------ ...soft.Azure.PowerShell.Cmdlets.Accounts.dll | Bin 386936 -> 390016 bytes ...e.PowerShell.Cmdlets.Accounts.dll-Help.xml | 470 ++++++++++++------ .../Microsoft.Azure.PowerShell.Common.dll | Bin 245832 -> 245624 bytes .../Microsoft.Azure.PowerShell.Storage.dll | Bin 19528 -> 19320 bytes .../Microsoft.Azure.PowerShell.Strategies.dll | Bin 64592 -> 64376 bytes .../Microsoft.Rest.ClientRuntime.Azure.dll | Bin .../Microsoft.Rest.ClientRuntime.dll | Bin ...soft.WindowsAzure.Storage.DataMovement.dll | Bin .../Microsoft.WindowsAzure.Storage.dll | Bin .../1.8.1/NetCoreAssemblies/Azure.Core.dll | Bin 0 -> 128888 bytes .../Microsoft.Bcl.AsyncInterfaces.dll | Bin 0 -> 20856 bytes ...Model.Clients.ActiveDirectory.Platform.dll | Bin ....IdentityModel.Clients.ActiveDirectory.dll | Bin .../System.Numerics.Vectors.dll | Bin 0 -> 163464 bytes ...System.Runtime.CompilerServices.Unsafe.dll | Bin 0 -> 18808 bytes .../System.Text.Encodings.Web.dll | Bin 0 -> 99192 bytes .../NetCoreAssemblies/System.Text.Json.dll | Bin 0 -> 294264 bytes .../System.Threading.Tasks.Extensions.dll | Bin 0 -> 14712 bytes .../PostImportScripts/LoadAuthenticators.ps1 | 144 +++--- .../1.8.1/PreloadAssemblies/Azure.Core.dll | Bin 0 -> 128888 bytes ...rosoft.Azure.PowerShell.Authenticators.dll | Bin 19832 -> 19840 bytes .../Microsoft.Bcl.AsyncInterfaces.dll | Bin 0 -> 20856 bytes ...Model.Clients.ActiveDirectory.Platform.dll | Bin ....IdentityModel.Clients.ActiveDirectory.dll | Bin .../PreloadAssemblies/Newtonsoft.Json.10.dll | Bin 663136 -> 662928 bytes .../PreloadAssemblies/System.Buffers.dll | Bin ...m.Diagnostics.DiagnosticSource.4.0.4.0.dll | Bin 0 -> 49528 bytes .../System.Diagnostics.DiagnosticSource.dll | Bin 0 -> 43952 bytes .../1.8.1/PreloadAssemblies/System.Memory.dll | Bin 0 -> 148760 bytes .../System.Net.Http.WinHttpHandler.dll | Bin .../System.Numerics.Vectors.dll | Bin 0 -> 163712 bytes .../System.Private.ServiceModel.dll | Bin .../System.Reflection.DispatchProxy.dll | Bin ...untime.CompilerServices.Unsafe.4.0.4.0.dll | Bin 0 -> 22160 bytes ...untime.CompilerServices.Unsafe.4.0.4.1.dll | Bin 0 -> 23600 bytes ...untime.CompilerServices.Unsafe.4.0.5.0.dll | Bin 0 -> 16760 bytes .../System.Security.AccessControl.dll | Bin .../System.Security.Permissions.dll | Bin .../System.Security.Principal.Windows.dll | Bin .../System.ServiceModel.Primitives.dll | Bin .../System.Text.Encodings.Web.dll | Bin 0 -> 57720 bytes .../PreloadAssemblies/System.Text.Json.dll | Bin 0 -> 294264 bytes ...tem.Threading.Tasks.Extensions.4.2.0.0.dll | Bin 0 -> 32904 bytes ...tem.Threading.Tasks.Extensions.4.3.1.0.dll | Bin 0 -> 14712 bytes .../System.Xml.ReaderWriter.dll | Bin 0 -> 606592 bytes .../StartupScripts/AzError.ps1 | 176 +++---- .../{1.7.4 => 1.8.1}/[Content_Types].xml | 0 .../Az.Accounts/{1.7.4 => 1.8.1}/_rels/.rels | 4 +- .../b4e383786e734eb49545960a9feff173.psmdcp} | 2 +- .../runtime/csharp/pipeline/ISendAsync.cs | 15 +- tests-upgrade/AutoRestUpgradeTest.ps1 | 4 +- 92 files changed, 2332 insertions(+), 2021 deletions(-) create mode 100644 .azure-pipelines/credscan-suppressions.json create mode 100644 .azure-pipelines/daily-build.yml create mode 100644 .azure-pipelines/security-scan.yml delete mode 100644 powershell/resources/modules/Az.Accounts/1.7.4/Accounts.generated.format.ps1xml delete mode 100644 powershell/resources/modules/Az.Accounts/1.7.4/Accounts.types.ps1xml delete mode 100644 powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psm1 delete mode 100644 powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll delete mode 100644 powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Accounts.format.ps1xml (54%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/Accounts.generated.format.ps1xml create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/Accounts.types.ps1xml rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Az.Accounts.nuspec (94%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Az.Accounts.psd1 (54%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psm1 rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Hyak.Common.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.ApplicationInsights.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.Common.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json (90%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Authentication.deps.json (91%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Authentication.dll (91%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Aks.dll (93%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Authorization.dll (95%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Compute.dll (99%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Graph.Rbac.dll (98%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.KeyVault.dll (95%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Monitor.dll (98%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Network.dll (99%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.PolicyInsights.dll (96%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.ResourceManager.dll (99%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll (94%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Clients.Websites.dll (99%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json (90%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll (66%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll-Help.xml (95%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Common.dll (56%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Storage.dll (72%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Azure.PowerShell.Strategies.dll (91%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Rest.ClientRuntime.Azure.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.Rest.ClientRuntime.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.WindowsAzure.Storage.DataMovement.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/Microsoft.WindowsAzure.Storage.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/Azure.Core.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/Microsoft.Bcl.AsyncInterfaces.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/NetCoreAssemblies/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/NetCoreAssemblies/Microsoft.IdentityModel.Clients.ActiveDirectory.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Numerics.Vectors.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Runtime.CompilerServices.Unsafe.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Text.Encodings.Web.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Text.Json.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Threading.Tasks.Extensions.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PostImportScripts/LoadAuthenticators.ps1 (63%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Azure.Core.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/Microsoft.Azure.PowerShell.Authenticators.dll (76%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Microsoft.Bcl.AsyncInterfaces.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/Microsoft.IdentityModel.Clients.ActiveDirectory.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/Newtonsoft.Json.10.dll (99%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Buffers.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Diagnostics.DiagnosticSource.4.0.4.0.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Diagnostics.DiagnosticSource.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Memory.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Net.Http.WinHttpHandler.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Numerics.Vectors.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Private.ServiceModel.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Reflection.DispatchProxy.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.4.0.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.4.1.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.5.0.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Security.AccessControl.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Security.Permissions.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.Security.Principal.Windows.dll (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/PreloadAssemblies/System.ServiceModel.Primitives.dll (100%) create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Text.Encodings.Web.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Text.Json.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Threading.Tasks.Extensions.4.2.0.0.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Threading.Tasks.Extensions.4.3.1.0.dll create mode 100644 powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Xml.ReaderWriter.dll rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/StartupScripts/AzError.ps1 (64%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/[Content_Types].xml (100%) rename powershell/resources/modules/Az.Accounts/{1.7.4 => 1.8.1}/_rels/.rels (66%) rename powershell/resources/modules/Az.Accounts/{1.7.4/package/services/metadata/core-properties/14a2e5dcca424832934ab543719a1374.psmdcp => 1.8.1/package/services/metadata/core-properties/b4e383786e734eb49545960a9feff173.psmdcp} (99%) diff --git a/.azure-pipelines/credscan-suppressions.json b/.azure-pipelines/credscan-suppressions.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.azure-pipelines/daily-build.yml b/.azure-pipelines/daily-build.yml new file mode 100644 index 00000000000..777ab1e4639 --- /dev/null +++ b/.azure-pipelines/daily-build.yml @@ -0,0 +1,50 @@ +# Please don't use ADO UI defined scheduled triggers because it takes precedence over YAML scheduled triggers. +# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/scheduled-triggers +schedules: +- cron: "0 0 * * *" + displayName: Daily Midnight Build + branches: + include: + - master + +trigger: none +pr: none + +pool: + name: Hosted VS2017 + demands: npm + +steps: +- task: NodeTool@0 + displayName: 'Use Node 10.16.0' + inputs: + versionSpec: 10.16.0 + +- task: Npm@1 + displayName: 'Install autorest@beta' + inputs: + command: custom + verbose: false + customCommand: 'install -g "@autorest/autorest"' + +- task: Npm@1 + displayName: 'Install @microsoft/rush' + inputs: + command: custom + verbose: false + customCommand: 'install -g @microsoft/rush@5.12.0' + +- task: CmdLine@2 + displayName: 'Rush sync-versions' + inputs: + script: 'rush sync-versions' + +- task: CmdLine@2 + displayName: 'Rush Update' + inputs: + script: 'rush update' + +- task: CmdLine@2 + displayName: 'Rush Rebuild' + inputs: + script: 'rush rebuild' \ No newline at end of file diff --git a/.azure-pipelines/security-scan.yml b/.azure-pipelines/security-scan.yml new file mode 100644 index 00000000000..190e3067ee6 --- /dev/null +++ b/.azure-pipelines/security-scan.yml @@ -0,0 +1,15 @@ +trigger: + branches: + include: + - '*' + +pool: + vmImage: "windows-2019" + +steps: +- task: ms-codeanalysis.vss-microsoft-security-code-analysis-devops.build-task-credscan.CredScan@2 + displayName: 'Run CredScan' + continueOnError: true + inputs: + toolMajorVersion: "V2" + suppressionsFile: .azure-pipelines\credscan-suppressions.json \ No newline at end of file diff --git a/docs/development.md b/docs/development.md index b87b03c6841..b28094db19a 100644 --- a/docs/development.md +++ b/docs/development.md @@ -71,7 +71,8 @@ To use the locally built version of the plugin, add `--use:` to the comman ### Debugging -COMING SOON. +1. Start generating: `autorest-beta --use:C:\path\to\local\autorest.powershell --powershell.debugger`. It will wait for debugger to attach. +1. Start debugging: open autorest.powershell repo in vscode; press `F5`. You will see "Debugger attached." in your autorest console, then you can start debugging. ### Testing diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 13091709d02..efe286423d3 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -1091,6 +1091,10 @@ export class CmdletClass extends Class { // in azure mode, we signal the AzAccount module with every event that makes it here. yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`; yield If(`${token.value}.IsCancellationRequested`, Return()); + } else { + // In Non-Azure Modes, emit the Signal method without coorelation and processrecordid + yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`; + yield If(`${token.value}.IsCancellationRequested`, Return()); } yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`; // any handling of the signal on our side... @@ -2310,6 +2314,10 @@ export class NewCmdletClass extends Class { // in azure mode, we signal the AzAccount module with every event that makes it here. yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`; yield If(`${token.value}.IsCancellationRequested`, Return()); + } else { + // In Non-Azure Modes, emit the Signal method without coorelation and processrecordid + yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`; + yield If(`${token.value}.IsCancellationRequested`, Return()); } yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`; // any handling of the signal on our side... diff --git a/powershell/generators/gitignore.ts b/powershell/generators/gitignore.ts index 7791a3c6e0b..84764c3f372 100644 --- a/powershell/generators/gitignore.ts +++ b/powershell/generators/gitignore.ts @@ -13,6 +13,7 @@ obj generated internal exports +tools custom/*.psm1 test/*-TestResults.xml /*.ps1 diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index 598b8250418..ac810323dae 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -36,12 +36,12 @@ export async function generateNuspec(project: Project | NewProject) { - - - - - - + + + + + + `, undefined, 'source-file-other'); } diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 9afaf33d7e8..2b57a317d87 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -173,7 +173,7 @@ export class Project extends codeDomProject { // Values this.moduleVersion = await this.state.getValue('module-version'); this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || []; - this.accountsVersionMinimum = '1.7.4'; + this.accountsVersionMinimum = '1.8.1'; this.helpLinkPrefix = await this.state.getValue('help-link-prefix'); this.metadata = await this.state.getValue('metadata'); this.license = await this.state.getValue('header-text', ''); @@ -335,7 +335,7 @@ export class NewProject extends codeDomProject { // skip-for-time-being //this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || []; this.profiles = []; - this.accountsVersionMinimum = '1.7.4'; + this.accountsVersionMinimum = '1.8.1'; this.helpLinkPrefix = await this.state.getValue('help-link-prefix'); this.metadata = await this.state.getValue('metadata'); this.license = await this.state.getValue('header-text', ''); diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index 8edad8193c6..58b81933822 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -129,6 +129,21 @@ export class ModuleClass extends Class { createInitAndPipeline(namespace: Namespace) { const $this = this; + // Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId) + const customEventListenerFunc = System.Func( + dotnet.String, + System.Threading.CancellationToken, + System.Func(System.EventArgs), + this.incomingSignalFunc, + InvocationInfo, + dotnet.String, + System.Exception, + /* returns */ System.Threading.Tasks.Task()); + + const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); + const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc)); + const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); + // non-azure init method this.initMethod.add(function* () { yield '// called at module init time...'; @@ -152,6 +167,22 @@ export class ModuleClass extends Class { }); this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); + + // Add Signal extensibility point + const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); + // Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module + const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { + parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async, + description: 'Called to dispatch events to the common module listener', + returnsDescription: `A that will be complete when handling of the event is completed.` + })); + + signalImpl.push(Using('NoSynchronizationContext', '')); + signalImpl.add(function* () { + // Emit call to EventListener after explicit null check. + // Not using Null-Conditional operator causes Null Reference exception when Func is null, due to awaiting null Task. + yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`) + }); } createAzureInitAndPipeline(namespace: Namespace) { @@ -379,6 +410,20 @@ export class NewModuleClass extends Class { createInitAndPipeline(namespace: Namespace) { const $this = this; + // Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId) + const customEventListenerFunc = System.Func( + dotnet.String, + System.Threading.CancellationToken, + System.Func(System.EventArgs), + this.incomingSignalFunc, + InvocationInfo, + dotnet.String, + System.Exception, + /* returns */ System.Threading.Tasks.Task()); + + const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); + const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc)); + const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); // non-azure init method this.initMethod.add(function* () { @@ -403,6 +448,22 @@ export class NewModuleClass extends Class { }); this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); + + // Add Signal extensibility point + const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); + // Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module + const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { + parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async, + description: 'Called to dispatch events to the common module listener', + returnsDescription: `A that will be complete when handling of the event is completed.` + })); + + signalImpl.push(Using('NoSynchronizationContext', '')); + signalImpl.add(function* () { + // Emit call to EventListener after explicit null check. + // Not using Null-Conditional operator causes Null Reference exception when Func is null, due to awaiting null Task. + yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`) + }); } createAzureInitAndPipeline(namespace: Namespace) { diff --git a/powershell/resources/assets/tools/Resources/readme.md b/powershell/resources/assets/tools/Resources/readme.md index 723a5c218b6..29a16fb828d 100644 --- a/powershell/resources/assets/tools/Resources/readme.md +++ b/powershell/resources/assets/tools/Resources/readme.md @@ -17,7 +17,7 @@ This directory contains the PowerShell module for the Resources service. This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension. ## Module Requirements -- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater +- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.8.1 or greater ## Authentication AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent. diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.generated.format.ps1xml b/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.generated.format.ps1xml deleted file mode 100644 index e9518b3db3f..00000000000 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.generated.format.ps1xml +++ /dev/null @@ -1,422 +0,0 @@ - - - - - Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment - - Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment - - - - - Left - - - - Left - - - - Left - - - - - - - - Left - Name - - - Left - ResourceManagerUrl - - - Left - ActiveDirectoryAuthority - - - - - - - - Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription - - Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription - - - - - Left - - - - Left - - - - Left - - - - Left - - - - - - - - Left - Name - - - Left - Id - - - Left - TenantId - - - Left - State - - - - - - - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile - - - - - Left - - - - Left - - - - Left - - - - Left - - - - - - - - Left - $_.Context.Account.ToString() - - - Left - $_.Context.Subscription.Name - - - Left - $_.Context.Tenant.ToString() - - - Left - $_.Context.Environment.ToString() - - - - - - - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext - - - - - 40 - Left - - - - Left - - - - Left - - - - Left - - - - Left - - - - - - - - Left - Name - - - Left - Account - - - Left - $_.Subscription.Name - - - Left - Environment - - - Left - $_.Tenant.ToString() - - - - - - - - Microsoft.Azure.Commands.Profile.Models.PSAzureTenant - - Microsoft.Azure.Commands.Profile.Models.PSAzureTenant - - - - - Left - - - - Left - - - - - - - - Left - Id - - - Left - Directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.types.ps1xml b/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.types.ps1xml deleted file mode 100644 index 974f390a7c3..00000000000 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.types.ps1xml +++ /dev/null @@ -1,281 +0,0 @@ - - - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile - - - PSStandardMembers - - - SerializationDepth - 10 - - - - - - - Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext - - - PSStandardMembers - - - SerializationDepth - 10 - - - - - - - Microsoft.Azure.Commands.Common.Authentication.Core.AuthenticationStoreTokenCache - - - PSStandardMembers - - - SerializationMethod - SpecificProperties - - - PropertySerializationSet - - CacheData - - - - - - - - Microsoft.Azure.Commands.Common.Authentication.Core.ProtectedFileTokenCache - - - PSStandardMembers - - - SerializationMethod - SpecificProperties - - - PropertySerializationSet - - CacheData - - - - - - - - Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer - - - PSStandardMembers - - - SerializationDepth - 10 - - - - - - Microsoft.Azure.Commands.Profile.Models.AzureContextConverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psm1 b/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psm1 deleted file mode 100644 index 9c131a504b5..00000000000 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psm1 +++ /dev/null @@ -1,319 +0,0 @@ -# -# Script module for module 'Az.Accounts' that is executed when 'Az.Accounts' is imported in a PowerShell session. -# -# Generated by: Microsoft Corporation -# -# Generated on: 03/27/2020 11:36:10 -# - -$PSDefaultParameterValues.Clear() -Set-StrictMode -Version Latest - -function Test-DotNet -{ - try - { - if ((Get-PSDrive 'HKLM' -ErrorAction Ignore) -and (-not (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' -ErrorAction Stop | Get-ItemPropertyValue -ErrorAction Stop -Name Release | Where-Object { $_ -ge 461808 }))) - { - throw ".NET Framework versions lower than 4.7.2 are not supported in Az. Please upgrade to .NET Framework 4.7.2 or higher." - } - } - catch [System.Management.Automation.DriveNotFoundException] - { - Write-Verbose ".NET Framework version check failed." - } -} - -if ($true -and ($PSEdition -eq 'Desktop')) -{ - if ($PSVersionTable.PSVersion -lt [Version]'5.1') - { - throw "PowerShell versions lower than 5.1 are not supported in Az. Please upgrade to PowerShell 5.1 or higher." - } - - Test-DotNet -} - -if (Test-Path -Path "$PSScriptRoot\StartupScripts" -ErrorAction Ignore) -{ - Get-ChildItem "$PSScriptRoot\StartupScripts" -ErrorAction Stop | ForEach-Object { - . $_.FullName - } -} - -if (Get-Module AzureRM.profile -ErrorAction Ignore) -{ - Write-Warning ("AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session or used in the same script or runbook. If you are running PowerShell in an environment you control you can use the 'Uninstall-AzureRm' cmdlet to remove all AzureRm modules from your machine. " + - "If you are running in Azure Automation, take care that none of your runbooks import both Az and AzureRM modules. More information can be found here: https://aka.ms/azps-migration-guide.") - throw ("AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session or used in the same script or runbook. If you are running PowerShell in an environment you control you can use the 'Uninstall-AzureRm' cmdlet to remove all AzureRm modules from your machine. " + - "If you are running in Azure Automation, take care that none of your runbooks import both Az and AzureRM modules. More information can be found here: https://aka.ms/azps-migration-guide.") -} - -$preloadPath = (Join-Path $PSScriptRoot -ChildPath "PreloadAssemblies") -if($PSEdition -eq 'Desktop' -and (Test-Path $preloadPath -ErrorAction Ignore)) -{ - try - { - Get-ChildItem -ErrorAction Stop -Path $preloadPath -Filter "*.dll" | ForEach-Object { - Add-Type -Path $_.FullName -ErrorAction Ignore | Out-Null - } - } - catch {} -} - -$netCorePath = (Join-Path $PSScriptRoot -ChildPath "NetCoreAssemblies") -if($PSEdition -eq 'Core' -and (Test-Path $netCorePath -ErrorAction Ignore)) -{ - try - { - $loadedAssemblies = ([System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {New-Object -TypeName System.Reflection.AssemblyName -ArgumentList $_.FullName} ) - Get-ChildItem -ErrorAction Stop -Path $netCorePath -Filter "*.dll" | ForEach-Object { - $assemblyName = ([System.Reflection.AssemblyName]::GetAssemblyName($_.FullName)) - $matches = ($loadedAssemblies | Where-Object {$_.Name -eq $assemblyName.Name}) - if (-not $matches) - { - Add-Type -Path $_.FullName -ErrorAction Ignore | Out-Null - } - } - } - catch {} -} - - -Import-Module (Join-Path -Path $PSScriptRoot -ChildPath Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll) - - -if (Test-Path -Path "$PSScriptRoot\PostImportScripts" -ErrorAction Ignore) -{ - Get-ChildItem "$PSScriptRoot\PostImportScripts" -ErrorAction Stop | ForEach-Object { - . $_.FullName - } -} - -$FilteredCommands = @() - -if ($Env:ACC_CLOUD -eq $null) -{ - $FilteredCommands | ForEach-Object { - - $existingDefault = $false - foreach ($key in $global:PSDefaultParameterValues.Keys) - { - if ($_ -like "$key") - { - $existingDefault = $true - } - } - - if (!$existingDefault) - { - $global:PSDefaultParameterValues.Add($_, - { - if ((Get-Command Get-AzContext -ErrorAction Ignore) -eq $null) - { - $context = Get-AzureRmContext - } - else - { - $context = Get-AzContext - } - if (($context -ne $null) -and $context.ExtendedProperties.ContainsKey("Default Resource Group")) { - $context.ExtendedProperties["Default Resource Group"] - } - }) - } - } -} - -# SIG # Begin signature block -# MIIjhgYJKoZIhvcNAQcCoIIjdzCCI3MCAQExDzANBglghkgBZQMEAgEFADB5Bgor -# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG -# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD93NjbGgh13Rz7 -# oIGFHWzqX68u3Sk2HcapUqpsLYn7J6CCDYEwggX/MIID56ADAgECAhMzAAABUZ6N -# j0Bxow5BAAAAAAFRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD -# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy -# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p -# bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw -# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u -# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy -# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -# AQCVWsaGaUcdNB7xVcNmdfZiVBhYFGcn8KMqxgNIvOZWNH9JYQLuhHhmJ5RWISy1 -# oey3zTuxqLbkHAdmbeU8NFMo49Pv71MgIS9IG/EtqwOH7upan+lIq6NOcw5fO6Os -# +12R0Q28MzGn+3y7F2mKDnopVu0sEufy453gxz16M8bAw4+QXuv7+fR9WzRJ2CpU -# 62wQKYiFQMfew6Vh5fuPoXloN3k6+Qlz7zgcT4YRmxzx7jMVpP/uvK6sZcBxQ3Wg -# B/WkyXHgxaY19IAzLq2QiPiX2YryiR5EsYBq35BP7U15DlZtpSs2wIYTkkDBxhPJ -# IDJgowZu5GyhHdqrst3OjkSRAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE -# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUV4Iarkq57esagu6FUBb270Zijc8w -# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 -# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU0MTM1MB8GA1UdIwQYMBaAFEhu -# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu -# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w -# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 -# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx -# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAWg+A -# rS4Anq7KrogslIQnoMHSXUPr/RqOIhJX+32ObuY3MFvdlRElbSsSJxrRy/OCCZdS -# se+f2AqQ+F/2aYwBDmUQbeMB8n0pYLZnOPifqe78RBH2fVZsvXxyfizbHubWWoUf -# NW/FJlZlLXwJmF3BoL8E2p09K3hagwz/otcKtQ1+Q4+DaOYXWleqJrJUsnHs9UiL -# crVF0leL/Q1V5bshob2OTlZq0qzSdrMDLWdhyrUOxnZ+ojZ7UdTY4VnCuogbZ9Zs -# 9syJbg7ZUS9SVgYkowRsWv5jV4lbqTD+tG4FzhOwcRQwdb6A8zp2Nnd+s7VdCuYF -# sGgI41ucD8oxVfcAMjF9YX5N2s4mltkqnUe3/htVrnxKKDAwSYliaux2L7gKw+bD -# 1kEZ/5ozLRnJ3jjDkomTrPctokY/KaZ1qub0NUnmOKH+3xUK/plWJK8BOQYuU7gK -# YH7Yy9WSKNlP7pKj6i417+3Na/frInjnBkKRCJ/eYTvBH+s5guezpfQWtU4bNo/j -# 8Qw2vpTQ9w7flhH78Rmwd319+YTmhv7TcxDbWlyteaj4RK2wk3pY1oSz2JPE5PNu -# Nmd9Gmf6oePZgy7Ii9JLLq8SnULV7b+IP0UXRY9q+GdRjM2AEX6msZvvPCIoG0aY -# HQu9wZsKEK2jqvWi8/xdeeeSI9FN6K1w4oVQM4Mwggd6MIIFYqADAgECAgphDpDS -# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK -# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 -# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 -# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla -# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS -# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT -# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB -# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG -# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S -# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz -# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 -# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u -# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 -# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl -# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP -# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB -# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF -# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM -# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ -# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud -# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO -# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 -# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y -# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p -# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y -# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB -# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw -# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA -# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY -# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj -# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd -# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ -# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf -# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ -# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j -# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B -# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 -# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 -# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I -# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWzCCFVcCAQEwgZUwfjELMAkG -# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx -# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z -# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAVGejY9AcaMOQQAAAAABUTAN -# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor -# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQghNiWwTYi -# QEZG87D5uLNO7t2PbqVXEVnQqmZPQe4alVswQgYKKwYBBAGCNwIBDDE0MDKgFIAS -# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN -# BgkqhkiG9w0BAQEFAASCAQAxBGKva/9e5RokmCrjfgx2Kp41e+OKnIpbryhNEW4T -# sI9fl0CiPY2PwWmSWlrjas/vkScPioCIzIHtXRV71vVon7DyLfySUUxQWfDNO8li -# VXBZ2M7nEZLsvRyfWbbWY89TvZrSVp0isBCkGxwrb6SnHwT3dQCXH8l6mdZiDHa2 -# s6iNtN0hz0qtpvIIkIUXPNCW4R6A46+Kh96HLGDWHfMD5gV1yDtTVQU6qdC9XS3W -# HAK1FV/pupU86I0dXADcJuYGN3m/XdJhyns2hE9CuhqxW2JzGHYiejf8DmxgXbFn -# iocixujU0wGB19EvBk0MIYlwYRuQnNKhA1hYFviYx7HJoYIS5TCCEuEGCisGAQQB -# gjcDAwExghLRMIISzQYJKoZIhvcNAQcCoIISvjCCEroCAQMxDzANBglghkgBZQME -# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB -# MDEwDQYJYIZIAWUDBAIBBQAEIFaVtuz7SMNc+3d6IJHuW00dA83j6FP3VEElx6nw -# 8kXpAgZee7+ObAgYEzIwMjAwMzI3MTE0NzIyLjUwMVowBIACAfSggdCkgc0wgcox -# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt -# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p -# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg -# RVNOOkFFMkMtRTMyQi0xQUZDMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt -# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAEWkyLqv7stTeYAAAAAARYw -# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 -# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh -# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN -# MTkxMTEzMjE0MDM0WhcNMjEwMjExMjE0MDM0WjCByjELMAkGA1UEBhMCVVMxEzAR -# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p -# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg -# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046QUUyQy1FMzJCLTFB -# RkMxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G -# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQ+Bvz/b3qJ78uPatar4wiUxnCRJTB -# mwgp3jva3J5U7I1wqCpIJPjNC/PaR35UPuVhY3dXRRIvmiKl2n7GnvAfsIAcLvM1 -# TbU+N0dY86LaiQiU/JOKStAGjCj4w5X1eB3daoyclIoRqeTtCZIeAmKYnar9lFHn -# 7Rnm5lF6MkeRBwmZMHwar/CDYT+CO5GX+IZrh8Ym7RwdJSJfvybkUTJppzVeeSpp -# 9KphHypvuyfdlW3+W1uIZQmvzviiLZtl25S0IxHRCJZZ8EwTFwtXgDp6uYL3xxtu -# +L+lBvWnWXu9dPY1F4P7GQWrMqfRwDdWL1xzkuMOFj3UvXxG4ciBTeodAgMBAAGj -# ggEbMIIBFzAdBgNVHQ4EFgQU5b9eK7gX6BfNR+UfeTT+V8ghVQswHwYDVR0jBBgw -# FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov -# L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB -# XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 -# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx -# MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN -# BgkqhkiG9w0BAQsFAAOCAQEANoNq19qpo9sDL+lJ0rx7xd3M3q/33v01JYtSw0eg -# 0EWnKvUVMZy/B/RIoh97TKC3yzymWQBjExR+1SY6c746cZdSBM6t5cjDjO2x6mi2 -# t4dwvT3j5ufs5QYs8xrnoZCKLdZSCIY8/SB81eFdypJ130eZeMyEp9GfSM4pEQlM -# +o8ctdLFwDVJVOuDwkO2QP7JZXO64CRKilMbG0mnk9ythSsxvudbVygh7u2xCJI+ -# nrEVXMp9cVQn1XMAKG5wT7ympculX/FTen/W9/QOAtkykjbabACBt78TrCDINIrI -# dcjhSyIiVJgBK/4iUo61xfOtdXQhFBR1HIgLVmJZYv9iCDCCBnEwggRZoAMCAQIC -# CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD -# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy -# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp -# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIx -# NDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV -# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG -# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3 -# DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF -# ++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRD -# DNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSx -# z5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1 -# rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16Hgc -# sOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB -# 4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqF -# bVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -# EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYD -# VR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwv -# cHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEB -# BE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j -# ZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCB -# kjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jv -# c29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQe -# MiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQA -# LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUx -# vs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GAS -# inbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1 -# L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWO -# M7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4 -# pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45 -# V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x -# 4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEe -# gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn -# QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp -# 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT -# X4/edIhJEqGCAs4wggI3AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG -# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj -# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP -# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpBRTJDLUUzMkItMUFG -# QzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG -# BSsOAwIaAxUAh01b3PJPoIsbWoIM1z76zOzdlkOggYMwgYCkfjB8MQswCQYDVQQG -# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG -# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg -# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOIoOEMwIhgPMjAy -# MDAzMjcxNjMwNTlaGA8yMDIwMDMyODE2MzA1OVowdzA9BgorBgEEAYRZCgQBMS8w -# LTAKAgUA4ig4QwIBADAKAgEAAgIPCQIB/zAHAgEAAgIoHDAKAgUA4imJwwIBADA2 -# BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIB -# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAHxMDqVuuCGBd4By6w5za3TeufC3ypwZ -# IKPBg9wc22gQYpGMe0wckgSU4eQOjbudj9tuBEpMPHGEQXJqQuLZJPm8vocGgXhu -# Llxla9oKoO8Q5LH1Dxb3BmGrEJxI48CB6o5LsSnSuNAM6+9ds9hFMIS0/TICesnn -# scCP5LCFEKZ7MYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m -# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB -# IDIwMTACEzMAAAEWkyLqv7stTeYAAAAAARYwDQYJYIZIAWUDBAIBBQCgggFKMBoG -# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgvYndyKaa -# Xt5u8EV7tkq9iO7K3bteHp1Zt+EsdFiKFPQwgfoGCyqGSIb3DQEJEAIvMYHqMIHn -# MIHkMIG9BCCDIpT2pGApCJdcKZshNt20sQ2FjGogyEFoz6Je0sGQyjCBmDCBgKR+ -# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS -# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT -# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABFpMi6r+7LU3mAAAA -# AAEWMCIEIFZT6aTDpXBffMedVCut8Vp6XNEIpPqr6N6nAIngHM8fMA0GCSqGSIb3 -# DQEBCwUABIIBAEz+5VKVya/7YXurU/JEAcsDnRoa3cZdX1+bEyVKB8OdFeZcX+Qi -# 0OhnKtWAXHBEJBMSO+MT3G4cqeLBhariruF5RUow0NvHq6Q5v4nor6FFGJxIcVfm -# VF29kPzaozfeAh29xljtvs9z+P3zjEPEKem5dzopi6y6elf7wXCR7yHSW87S8Wpm -# X1fO6gHf1dpy3/0I6cOmegizB3pntMgVSLKlpkURKvuPSe6io9reM9e1i01p7b8H -# fpE/08I9LvGNFRPc07aOQdOhDearlAF+4VLT9T838/kuoaoK1sFYdi3VsM+h6GXZ -# LmMxwwaKlO9KeMyDBljsJmQZpnpCqzQcDz0= -# SIG # End signature block diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll b/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll deleted file mode 100644 index 08cac637b6482a583577cb77b591a4ddf6c5c2cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100432 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 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll b/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll deleted file mode 100644 index 96375ddb1ed742fd80e7c458ca6d4cc5e0bb147c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70008 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 V=RwE%jm^r@RvWjY`2b8J{s(V#GfDse diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.format.ps1xml b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.format.ps1xml similarity index 54% rename from powershell/resources/modules/Az.Accounts/1.7.4/Accounts.format.ps1xml rename to powershell/resources/modules/Az.Accounts/1.8.1/Accounts.format.ps1xml index e5352f04b0c..23bd02cb15f 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Accounts.format.ps1xml +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.format.ps1xml @@ -175,42 +175,42 @@ - + - - + + - + - - - - - - - + + + + + + + - + - - - - - - - - - - - - + + + + + + + + + + + + @@ -250,119 +250,119 @@ - + - + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.generated.format.ps1xml b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.generated.format.ps1xml new file mode 100644 index 00000000000..33077baf469 --- /dev/null +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.generated.format.ps1xml @@ -0,0 +1,422 @@ + + + + + Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment + + Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment + + + + + Left + + + + Left + + + + Left + + + + + + + + Left + Name + + + Left + ResourceManagerUrl + + + Left + ActiveDirectoryAuthority + + + + + + + + Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription + + Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription + + + + + Left + + + + Left + + + + Left + + + + Left + + + + + + + + Left + Name + + + Left + Id + + + Left + TenantId + + + Left + State + + + + + + + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile + + + + + Left + + + + Left + + + + Left + + + + Left + + + + + + + + Left + $_.Context.Account.ToString() + + + Left + $_.Context.Subscription.Name + + + Left + $_.Context.Tenant.ToString() + + + Left + $_.Context.Environment.ToString() + + + + + + + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext + + + + + 40 + Left + + + + Left + + + + Left + + + + Left + + + + Left + + + + + + + + Left + Name + + + Left + Account + + + Left + $_.Subscription.Name + + + Left + Environment + + + Left + $_.Tenant.ToString() + + + + + + + + Microsoft.Azure.Commands.Profile.Models.PSAzureTenant + + Microsoft.Azure.Commands.Profile.Models.PSAzureTenant + + + + + Left + + + + Left + + + + + + + + Left + Id + + + Left + Directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.types.ps1xml b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.types.ps1xml new file mode 100644 index 00000000000..019773629f1 --- /dev/null +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Accounts.types.ps1xml @@ -0,0 +1,281 @@ + + + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureProfile + + + PSStandardMembers + + + SerializationDepth + 10 + + + + + + + Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext + + + PSStandardMembers + + + SerializationDepth + 10 + + + + + + + Microsoft.Azure.Commands.Common.Authentication.Core.AuthenticationStoreTokenCache + + + PSStandardMembers + + + SerializationMethod + SpecificProperties + + + PropertySerializationSet + + CacheData + + + + + + + + Microsoft.Azure.Commands.Common.Authentication.Core.ProtectedFileTokenCache + + + PSStandardMembers + + + SerializationMethod + SpecificProperties + + + PropertySerializationSet + + CacheData + + + + + + + + Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer + + + PSStandardMembers + + + SerializationDepth + 10 + + + + + + Microsoft.Azure.Commands.Profile.Models.AzureContextConverter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.nuspec b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.nuspec similarity index 94% rename from powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.nuspec rename to powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.nuspec index ea7f86d99be..2ae40fc04d5 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.nuspec +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.nuspec @@ -2,7 +2,7 @@ Az.Accounts - 1.7.4 + 1.8.1 Microsoft Corporation Microsoft Corporation true @@ -11,7 +11,7 @@ Microsoft Azure PowerShell - Accounts credential management cmdlets for Azure Resource Manager in Windows PowerShell and PowerShell Core. For more information on account credential management, please visit the following: https://docs.microsoft.com/powershell/azure/authenticate-azureps - * Fixed 'Get-AzTenant'/'Get-AzDefault'/'Set-AzDefault' throw NullReferenceException when not login [#10292] + * Fixed an issue that may cause Az to skip logs in Azure Automation or PowerShell jobs [#11492] Microsoft Corporation. All rights reserved. Azure ResourceManager ARM Accounts Authentication Environment Subscription PSModule PSIncludes_Cmdlet PSCmdlet_Disable-AzDataCollection PSCmdlet_Disable-AzContextAutosave PSCmdlet_Enable-AzDataCollection PSCmdlet_Enable-AzContextAutosave PSCmdlet_Remove-AzEnvironment PSCmdlet_Get-AzEnvironment PSCmdlet_Set-AzEnvironment PSCmdlet_Add-AzEnvironment PSCmdlet_Get-AzSubscription PSCmdlet_Connect-AzAccount PSCmdlet_Get-AzContext PSCmdlet_Set-AzContext PSCmdlet_Import-AzContext PSCmdlet_Save-AzContext PSCmdlet_Get-AzTenant PSCmdlet_Send-Feedback PSCmdlet_Resolve-AzError PSCmdlet_Select-AzContext PSCmdlet_Rename-AzContext PSCmdlet_Remove-AzContext PSCmdlet_Clear-AzContext PSCmdlet_Disconnect-AzAccount PSCmdlet_Get-AzContextAutosaveSetting PSCmdlet_Set-AzDefault PSCmdlet_Get-AzDefault PSCmdlet_Clear-AzDefault PSCmdlet_Register-AzModule PSCmdlet_Enable-AzureRmAlias PSCmdlet_Disable-AzureRmAlias PSCmdlet_Uninstall-AzureRm PSCmdlet_Get-AzProfile PSCmdlet_Select-AzProfile PSCommand_Disable-AzDataCollection PSCommand_Disable-AzContextAutosave PSCommand_Enable-AzDataCollection PSCommand_Enable-AzContextAutosave PSCommand_Remove-AzEnvironment PSCommand_Get-AzEnvironment PSCommand_Set-AzEnvironment PSCommand_Add-AzEnvironment PSCommand_Get-AzSubscription PSCommand_Connect-AzAccount PSCommand_Get-AzContext PSCommand_Set-AzContext PSCommand_Import-AzContext PSCommand_Save-AzContext PSCommand_Get-AzTenant PSCommand_Send-Feedback PSCommand_Resolve-AzError PSCommand_Select-AzContext PSCommand_Rename-AzContext PSCommand_Remove-AzContext PSCommand_Clear-AzContext PSCommand_Disconnect-AzAccount PSCommand_Get-AzContextAutosaveSetting PSCommand_Set-AzDefault PSCommand_Get-AzDefault PSCommand_Clear-AzDefault PSCommand_Register-AzModule PSCommand_Enable-AzureRmAlias PSCommand_Disable-AzureRmAlias PSCommand_Uninstall-AzureRm PSCommand_Get-AzProfile PSCommand_Select-AzProfile PSCommand_Add-AzAccount PSCommand_Login-AzAccount PSCommand_Remove-AzAccount PSCommand_Logout-AzAccount PSCommand_Select-AzSubscription PSCommand_Resolve-Error PSCommand_Save-AzProfile PSCommand_Get-AzDomain diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psd1 b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psd1 similarity index 54% rename from powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psd1 rename to powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psd1 index 6171c53d5a7..c7bbc649a38 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Az.Accounts.psd1 +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 3/26/2020 +# Generated on: 5/28/2020 # @{ @@ -12,7 +12,7 @@ RootModule = 'Az.Accounts.psm1' # Version number of this module. -ModuleVersion = '1.7.4' +ModuleVersion = '1.8.1' # Supported PSEditions CompatiblePSEditions = 'Core', 'Desktop' @@ -142,7 +142,7 @@ PrivateData = @{ # IconUri = '' # ReleaseNotes of this module - ReleaseNotes = '* Fixed ''Get-AzTenant''/''Get-AzDefault''/''Set-AzDefault'' throw NullReferenceException when not login [#10292]' + ReleaseNotes = '* Fixed an issue that may cause Az to skip logs in Azure Automation or PowerShell jobs [#11492]' # Prerelease string of this module # Prerelease = '' @@ -167,42 +167,42 @@ PrivateData = @{ # SIG # Begin signature block -# MIIjhgYJKoZIhvcNAQcCoIIjdzCCI3MCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# MIIjjwYJKoZIhvcNAQcCoIIjgDCCI3wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG -# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCs9W+AwzXpeC8Q -# WMlYcwJwBsk3oMHo1v2xMWUZSViRNqCCDYEwggX/MIID56ADAgECAhMzAAABUZ6N -# j0Bxow5BAAAAAAFRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDuurAhAAKv07yX +# tNSM61tReUSrZGbTrOcsz0tXs7L536CCDYEwggX/MIID56ADAgECAhMzAAABh3IX +# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p -# bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw +# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -# AQCVWsaGaUcdNB7xVcNmdfZiVBhYFGcn8KMqxgNIvOZWNH9JYQLuhHhmJ5RWISy1 -# oey3zTuxqLbkHAdmbeU8NFMo49Pv71MgIS9IG/EtqwOH7upan+lIq6NOcw5fO6Os -# +12R0Q28MzGn+3y7F2mKDnopVu0sEufy453gxz16M8bAw4+QXuv7+fR9WzRJ2CpU -# 62wQKYiFQMfew6Vh5fuPoXloN3k6+Qlz7zgcT4YRmxzx7jMVpP/uvK6sZcBxQ3Wg -# B/WkyXHgxaY19IAzLq2QiPiX2YryiR5EsYBq35BP7U15DlZtpSs2wIYTkkDBxhPJ -# IDJgowZu5GyhHdqrst3OjkSRAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE -# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUV4Iarkq57esagu6FUBb270Zijc8w +# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB +# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH +# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d +# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ +# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV +# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 -# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU0MTM1MB8GA1UdIwQYMBaAFEhu +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx -# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAWg+A -# rS4Anq7KrogslIQnoMHSXUPr/RqOIhJX+32ObuY3MFvdlRElbSsSJxrRy/OCCZdS -# se+f2AqQ+F/2aYwBDmUQbeMB8n0pYLZnOPifqe78RBH2fVZsvXxyfizbHubWWoUf -# NW/FJlZlLXwJmF3BoL8E2p09K3hagwz/otcKtQ1+Q4+DaOYXWleqJrJUsnHs9UiL -# crVF0leL/Q1V5bshob2OTlZq0qzSdrMDLWdhyrUOxnZ+ojZ7UdTY4VnCuogbZ9Zs -# 9syJbg7ZUS9SVgYkowRsWv5jV4lbqTD+tG4FzhOwcRQwdb6A8zp2Nnd+s7VdCuYF -# sGgI41ucD8oxVfcAMjF9YX5N2s4mltkqnUe3/htVrnxKKDAwSYliaux2L7gKw+bD -# 1kEZ/5ozLRnJ3jjDkomTrPctokY/KaZ1qub0NUnmOKH+3xUK/plWJK8BOQYuU7gK -# YH7Yy9WSKNlP7pKj6i417+3Na/frInjnBkKRCJ/eYTvBH+s5guezpfQWtU4bNo/j -# 8Qw2vpTQ9w7flhH78Rmwd319+YTmhv7TcxDbWlyteaj4RK2wk3pY1oSz2JPE5PNu -# Nmd9Gmf6oePZgy7Ii9JLLq8SnULV7b+IP0UXRY9q+GdRjM2AEX6msZvvPCIoG0aY -# HQu9wZsKEK2jqvWi8/xdeeeSI9FN6K1w4oVQM4Mwggd6MIIFYqADAgECAgphDpDS +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy +# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K +# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV +# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr +# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx +# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe +# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g +# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf +# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI +# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 +# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea +# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 @@ -242,119 +242,119 @@ PrivateData = @{ # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I -# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWzCCFVcCAQEwgZUwfjELMAkG +# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZDCCFWACAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z -# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAVGejY9AcaMOQQAAAAABUTAN +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor -# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgvW8z/v0k -# GPxsq9zqQ5rvfuJK+q9Y6rEKepSzLSzZa/owQgYKKwYBBAGCNwIBDDE0MDKgFIAS +# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg0bWN4ISJ +# vps5kSf9K7psHiLoBv3Thd3OEZWVHm/B8TswQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN -# BgkqhkiG9w0BAQEFAASCAQAyT1vY2EXtkylHPfhTcS0I8Ew6VNPC7rdfGZsFoTxm -# 6OxRaZfI8ICgeekSwoAexj8tyRNitH5cqpzrJLATcoz90ioJFhp+XDCdjdaTMuTX -# hetdNM7hBSZjXYSkwiX7KRZXuupVXq+ipIgjrq4mQYMicWuUc8I4qwP4y9OdxZoG -# jg090TiO8MMoXTP7t1DjbnrxmeYUenJ9IgRylAGI9k62OB476N74sXB4pQIBIcvQ -# op9RzuVuK80GLk3J548yvn54Bmau/avP59PSMELiL4FlRV0uAQMuk1TK3yWDxbhE -# EpMwbPJMm/D+H/72VFvWAK6Rjqqm4vYprp1QCx/KO2r8oYIS5TCCEuEGCisGAQQB -# gjcDAwExghLRMIISzQYJKoZIhvcNAQcCoIISvjCCEroCAQMxDzANBglghkgBZQME -# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB -# MDEwDQYJYIZIAWUDBAIBBQAEICiuO4I0LHyJtulTtZBCkTiRVlqOrvQGWT7QxRla -# Dw0rAgZee4qQQn8YEzIwMjAwMzI3MTE1NzMzLjA0OFowBIACAfSggdCkgc0wgcox +# BgkqhkiG9w0BAQEFAASCAQCwJXsIokZyVWJoO/Jh5A5x1W9w60dDYdpn2v0u4b7S +# zlY7ugBjbcA7iF+72h9IKZ8Ug/XWMYCXplpm0cHE4F35DjcG8Kr/Vx87gfiQZ0X4 +# heyLsEI6fme6cRy4I0x1BRBZ5uBwPZ5Qi7A1azcPkBGwgyctLDhLkXUfrj8/zC5O +# d5Ya/R5HUc+mN88k10xeyBYEpFUqCONCCxLupfxLdlDRt9uDCvhqWE9ZBG1Nzx02 +# jiH273phDWlldG5hdaX0fLUXAKc7tQDaxF6acBypBQBEm2RXTSHHu8Onw2vuBcM8 +# ad/Im2850FVnHifJ/TebUaU+8jHAmZW7vSGpRwQtyz0aoYIS7jCCEuoGCisGAQQB +# gjcDAwExghLaMIIS1gYJKoZIhvcNAQcCoIISxzCCEsMCAQMxDzANBglghkgBZQME +# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB +# MDEwDQYJYIZIAWUDBAIBBQAEICXbtKNkQQuFRTKC/cY72F6h+DxZ0iCVXPTWEuBS +# ixdGAgZepuS2yXQYEzIwMjAwNTI4MDcyNTU1LjE2OVowBIACAfSggdSkgdEwgc4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt -# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p -# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg -# RVNOOkQyQ0QtRTMxMC00QUYxMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt -# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAEiG48AJiXMsecAAAAAASIw -# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 -# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh -# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN -# MTkxMTEzMjE0MDQzWhcNMjEwMjExMjE0MDQzWjCByjELMAkGA1UEBhMCVVMxEzAR -# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p -# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg -# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046RDJDRC1FMzEwLTRB -# RjExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G -# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfFQNIYkE+wXLcD2Ufk2s4kUKUhTQ9 -# 5+R/Q6DUhduOGdLJsSKhocU1Kl8L1zEqk/k1k+5oVCiBp5L9FO7ycSh779B+Q8Te -# iERLM+nbMdsAxUCbPjR0sQ63kJTFpDgB/4HOpeLULMPQ6iEl0jfEs2uqdt/gWIq4 -# KyK0ZXoP/Oo6S7zhWz4Cjczk7gS0ilAfSt7xB5lEhQhLCtkp9rzO6CKqMLW5ujYV -# yhmFcfrdx74/Y6E2Gs9u1YOk8Ktn4Y4cW/2E2e+4BeMs9AS+0XWbk/NYY2xiPHjZ -# qlzoVZEKGldOJ09P+kIh/jntp3Tpqr2NTeDt9OjT1qUY1yzJddR0pcLJAgMBAAGj -# ggEbMIIBFzAdBgNVHQ4EFgQUjjY9VWprwC9x2Djj4TS9nRczt8gwHwYDVR0jBBgw -# FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov -# L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB -# XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 -# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx -# MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN -# BgkqhkiG9w0BAQsFAAOCAQEAi6RHbsMi/wa2g3J+VTuchJyiNZ0fZlqWuihOJOux -# N59QvCd66Hp2pBaRCF4jfx+wbrGEeOdJ5luTZIUD88hJof4Q7Q37ZX78snbMd/gh -# r177Z1bf7t3yRM2cQ3vH6j20jWtlacoWeG/CRsCX0VHy/5o+qJxb/SfVC5WB+aZB -# cF/j7cdzHls7CMcTpzDaon2+q5J0mB+bV/I7kGyLx4kIQOgvox1xeXywxtFOgVef -# BCKYHL59hLoQZsOUwr8k8kd/P8wWckaDTuWt/uRq41wzYw/nd3ACzfTHVF6DY9qQ -# FQVEGJ0RA4cEs6EIX94sN/zpVTnUG+0PPdXBcgBKUkjK2zCCBnEwggRZoAMCAQIC -# CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD -# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy -# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp -# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIx -# NDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV -# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG -# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3 -# DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF -# ++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRD -# DNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSx -# z5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1 -# rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16Hgc -# sOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB -# 4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqF -# bVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -# EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYD -# VR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwv -# cHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEB -# BE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j -# ZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCB -# kjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jv -# c29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQe -# MiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQA -# LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUx -# vs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GAS -# inbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1 -# L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWO -# M7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4 -# pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45 -# V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x -# 4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEe -# gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn -# QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp -# 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT -# X4/edIhJEqGCAs4wggI3AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG -# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj -# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP -# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpEMkNELUUzMTAtNEFG -# MTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG -# BSsOAwIaAxUAUOwD/JcbpKVMXpF2Vh77MyVNm9mggYMwgYCkfjB8MQswCQYDVQQG -# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG -# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg -# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOIoA0IwIhgPMjAy -# MDAzMjcxMjQ0NTBaGA8yMDIwMDMyODEyNDQ1MFowdzA9BgorBgEEAYRZCgQBMS8w -# LTAKAgUA4igDQgIBADAKAgEAAgIi5QIB/zAHAgEAAgIRljAKAgUA4ilUwgIBADA2 -# BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIB -# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAJJIF1iO1PdC7/FxzqJRAmfVyvxX3Qc6 -# 48Xy+gnmkzm7Rhm5hkZiOwH1wSBMuImj617LuhCCmNxRfKYxw9s3WmJM8rOUkove -# dDWWuBWsTOvj4su4mHgMOQgRzG4vE6gy2lCEf1mttYmQ669tWsyt/d+gWORpXfX8 -# JLMvq3PKae/mMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m -# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB -# IDIwMTACEzMAAAEiG48AJiXMsecAAAAAASIwDQYJYIZIAWUDBAIBBQCgggFKMBoG -# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgk9J0f312 -# vNTzw3Vz0NTITu8OK47D5QvFs7oYMFCiQhcwgfoGCyqGSIb3DQEJEAIvMYHqMIHn -# MIHkMIG9BCC78GCJXmIyzmqyWSlw5bflow9yQ3g4vvs34oNSwngxCTCBmDCBgKR+ -# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS -# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT -# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABIhuPACYlzLHnAAAA -# AAEiMCIEIEhxBp/HbNnypXcfqIHDj1WZ+OLyTdLNZq9FU9n00sQAMA0GCSqGSIb3 -# DQEBCwUABIIBANENUjQBZ3LdfnlM5J95ierZHYwP2kI9kS35cwfLDOwI5lUh+iak -# Leq9/mtWmcuDmuAXCpArC5jktLGWQplZ7b/cI41/dBn74lwkbAqt2PhKQ41ouHRW -# 9ZjhiHOJlGCZe4ruJJ6MtkOHmfuAjdoZAW6iyO75TJJMY7VAXDwqRK/c60U5r1Jr -# bm/hb3Q1pTt++hrAcq/ejREXEfTA/oWtecGF37IphQx7w5AuqcMvFMXgYepGEz5D -# RDStjxKgO2/Yx7ADK9iRXBOWt1NbLu+LLaozuDC78PCLKcunRbni5KqCsRXMUZ+5 -# vM08G8RS3n4omsAY5nhU23fA9l8KRXJTrYA= +# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p +# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg +# VFNTIEVTTjpGN0E2LUUyNTEtMTUwQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt +# U3RhbXAgU2VydmljZaCCDkEwggT1MIID3aADAgECAhMzAAABJYvei2xyJjHdAAAA +# AAElMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo +# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw +# MB4XDTE5MTIxOTAxMTQ1OFoXDTIxMDMxNzAxMTQ1OFowgc4xCzAJBgNVBAYTAlVT +# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK +# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy +# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGN0E2 +# LUUyNTEtMTUwQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj +# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANB7H2N2YFvs4cnBJiYx +# Sitk3ABy/xXLfpOUm7NxXHsb6UWq3bONY4yVI4ySbVegC4nxVnlKEF50ANcMYMrE +# c1mEu7cRbzHmi38g6TqLMtOUAW28hc6DNez8do4zvZccrKQxkcB0v9+lm0BIzk9q +# Waxdfg6XyVeSb2NHnkrnoLur36ENT7a2MYdoTVlaVpuU1RcGFpmC0IkJ3rRTJm+A +# jv+43Nxp+PT9XDZtqK32cMBV3bjK39cJmcdjfJftmweMi4emyX4+kNdqLUPB72nS +# vIJmyX1I4wd7G0gd72qVNu1Zgnxa1Yugf10QxDFUueY88M5WYGPstmFKOLfw31Wn +# P8UCAwEAAaOCARswggEXMB0GA1UdDgQWBBTzqsrlByb5ATk0FcYI8iIIF0Mk+DAf +# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH +# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU +# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF +# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 +# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG +# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQCTHFk8YSAiACGypk1NmTnxXW9CInmN +# rbEeXlOoYDofCPlKKguDcVIuJOYZX4G0WWlhS2Sd4HiOtmy42ky19tMx0bun/EDI +# hW3C9edNeoqUIPVP0tyv3ilV53McYnMvVNg1DJkkGi4J/OSCTNxw64U595Y9+cxO +# IjlQFbk52ajIc9BYNIYehuhbV1Mqpd4m25UNNhsdMqzjON8IEwWObKVG7nZmmLP7 +# 0wF5GPiIB6i7QX/fG8jN6mggqBRYJn2aZWJYSRXAK1MZtXx4rvcp4QTS18xT9hjZ +# SagY9zxjBu6sMR96V6Atb5geR+twYAaV+0Kaq0504t6CEugbRRvH8HuxMIIGcTCC +# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC +# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv +# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN +# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv +# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw +# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0 +# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw +# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe +# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx +# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G +# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA +# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7 +# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC +# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX +# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v +# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI +# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g +# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93 +# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB +# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA +# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh +# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS +# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK +# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon +# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi +# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/ +# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII +# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0 +# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a +# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ +# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ +# NR4Iuto229Nfj950iEkSoYICzzCCAjgCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT +# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD +# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP +# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpG +# N0E2LUUyNTEtMTUwQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy +# dmljZaIjCgEBMAcGBSsOAwIaAxUARdMv4VBtzYb7cxde8hEpWvahcKeggYMwgYCk +# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD +# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF +# AOJ5mEcwIhgPMjAyMDA1MjgwNTU0MTVaGA8yMDIwMDUyOTA1NTQxNVowdDA6Bgor +# BgEEAYRZCgQBMSwwKjAKAgUA4nmYRwIBADAHAgEAAgIQaTAHAgEAAgIR2zAKAgUA +# 4nrpxwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID +# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAHSCuUKIja9Clnf/S578 +# vI9iyR2zx4t4KTE8Oc1a4hK7szarn0tHKrWDZ9eCGo1xziv73RzUH6uQxWT9c+ni +# paMbwPfe+nnleZBpLYEZnWsKITEBaOozaKV4p75+m0+ZWnCWsCCEZUsVrCI4Mufl +# fCQzViL04ZiX24Q/YEGp6BtYMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMx +# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT +# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt +# U3RhbXAgUENBIDIwMTACEzMAAAEli96LbHImMd0AAAAAASUwDQYJYIZIAWUDBAIB +# BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx +# IgQgnhg9UziffkIa501CNaIfYHD9t0ZymAWV6kze+W5WmsQwgfoGCyqGSIb3DQEJ +# EAIvMYHqMIHnMIHkMIG9BCBd38ayLm8wX/qJfYIOH5V+YvlG+poWQXCW6LKN70H3 +# DjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw +# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABJYve +# i2xyJjHdAAAAAAElMCIEIOE7tRdqMTLKlfH4tn6vc8stJmZ790PkjFTsb858jugw +# MA0GCSqGSIb3DQEBCwUABIIBAGpK5oraWz2zXT/4EhnqmSwlnmtyxs6GgoerJrc/ +# VUaCkwPJvHAdNocuEUFFzkPIr9JCLoHLhr7Qru7JvLM7myHm+536WdLNyEXB3U2n +# ASGU9QOUgvH+PFcWLskBYC4fstF0L2WR+hlX5+9rIJwWhk1cItSxRySa7+YvthDR +# HrtCWlivm+bwqPobxS3062wgiGm0pWllw5WBJipqMM7KNOxIMWbPk15uPkn4Osuq +# 0m84MeY6640BxWDokxm+MxUWTCLMxxKOursQRH3z8H6IEvdTjRuvQvXcwJDL8evv +# LslVpDno2+WliluRTrzyX/bgpHHiY3PFM2kMssHL/J4Gt08= # SIG # End signature block diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psm1 b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psm1 new file mode 100644 index 00000000000..994af339fcb --- /dev/null +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Az.Accounts.psm1 @@ -0,0 +1,339 @@ +# +# Script module for module 'Az.Accounts' that is executed when 'Az.Accounts' is imported in a PowerShell session. +# +# Generated by: Microsoft Corporation +# +# Generated on: 05/28/2020 06:50:01 +# + +$PSDefaultParameterValues.Clear() +Set-StrictMode -Version Latest + +function Test-DotNet +{ + try + { + if ((Get-PSDrive 'HKLM' -ErrorAction Ignore) -and (-not (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' -ErrorAction Stop | Get-ItemPropertyValue -ErrorAction Stop -Name Release | Where-Object { $_ -ge 461808 }))) + { + throw ".NET Framework versions lower than 4.7.2 are not supported in Az. Please upgrade to .NET Framework 4.7.2 or higher." + } + } + catch [System.Management.Automation.DriveNotFoundException] + { + Write-Verbose ".NET Framework version check failed." + } +} + +if ($true -and ($PSEdition -eq 'Desktop')) +{ + if ($PSVersionTable.PSVersion -lt [Version]'5.1') + { + throw "PowerShell versions lower than 5.1 are not supported in Az. Please upgrade to PowerShell 5.1 or higher." + } + + Test-DotNet +} + +if ($true -and ($PSEdition -eq 'Core')) +{ + if ($PSVersionTable.PSVersion -lt [Version]'6.2.4') + { + throw "Current Az version doesn't support PowerShell Core versions lower than 6.2.4. Please upgrade to PowerShell Core 6.2.4 or higher." + } +} + +if (Test-Path -Path "$PSScriptRoot\StartupScripts" -ErrorAction Ignore) +{ + Get-ChildItem "$PSScriptRoot\StartupScripts" -ErrorAction Stop | ForEach-Object { + . $_.FullName + } +} + +if (Get-Module AzureRM.profile -ErrorAction Ignore) +{ + Write-Warning ("AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session or used in the same script or runbook. If you are running PowerShell in an environment you control you can use the 'Uninstall-AzureRm' cmdlet to remove all AzureRm modules from your machine. " + + "If you are running in Azure Automation, take care that none of your runbooks import both Az and AzureRM modules. More information can be found here: https://aka.ms/azps-migration-guide.") + throw ("AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session or used in the same script or runbook. If you are running PowerShell in an environment you control you can use the 'Uninstall-AzureRm' cmdlet to remove all AzureRm modules from your machine. " + + "If you are running in Azure Automation, take care that none of your runbooks import both Az and AzureRM modules. More information can be found here: https://aka.ms/azps-migration-guide.") +} + +$preloadPath = (Join-Path $PSScriptRoot -ChildPath "PreloadAssemblies") +if($PSEdition -eq 'Desktop' -and (Test-Path $preloadPath -ErrorAction Ignore)) +{ + try + { + Get-ChildItem -ErrorAction Stop -Path $preloadPath -Filter "*.dll" | ForEach-Object { + try + { + Add-Type -Path $_.FullName -ErrorAction Ignore | Out-Null + } + catch { + Write-Verbose $_ + } + } + } + catch {} +} + +$netCorePath = (Join-Path $PSScriptRoot -ChildPath "NetCoreAssemblies") +if($PSEdition -eq 'Core' -and (Test-Path $netCorePath -ErrorAction Ignore)) +{ + try + { + $loadedAssemblies = ([System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {New-Object -TypeName System.Reflection.AssemblyName -ArgumentList $_.FullName} ) + Get-ChildItem -ErrorAction Stop -Path $netCorePath -Filter "*.dll" | ForEach-Object { + $assemblyName = ([System.Reflection.AssemblyName]::GetAssemblyName($_.FullName)) + $matches = ($loadedAssemblies | Where-Object {$_.Name -eq $assemblyName.Name}) + if (-not $matches) + { + try + { + Add-Type -Path $_.FullName -ErrorAction Ignore | Out-Null + } + catch { + Write-Verbose $_ + } + } + } + } + catch {} +} + + +Import-Module (Join-Path -Path $PSScriptRoot -ChildPath Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll) + + +if (Test-Path -Path "$PSScriptRoot\PostImportScripts" -ErrorAction Ignore) +{ + Get-ChildItem "$PSScriptRoot\PostImportScripts" -ErrorAction Stop | ForEach-Object { + . $_.FullName + } +} + +$FilteredCommands = @() + +if ($Env:ACC_CLOUD -eq $null) +{ + $FilteredCommands | ForEach-Object { + + $existingDefault = $false + foreach ($key in $global:PSDefaultParameterValues.Keys) + { + if ($_ -like "$key") + { + $existingDefault = $true + } + } + + if (!$existingDefault) + { + $global:PSDefaultParameterValues.Add($_, + { + if ((Get-Command Get-AzContext -ErrorAction Ignore) -eq $null) + { + $context = Get-AzureRmContext + } + else + { + $context = Get-AzContext + } + if (($context -ne $null) -and $context.ExtendedProperties.ContainsKey("Default Resource Group")) { + $context.ExtendedProperties["Default Resource Group"] + } + }) + } + } +} + +# SIG # Begin signature block +# MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAOvvTds8RMroSM +# 4jK/KyvMyRtBp0iXYFrUmBz7UipKR6CCDYEwggX/MIID56ADAgECAhMzAAABh3IX +# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB +# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH +# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d +# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ +# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV +# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw +# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu +# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu +# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w +# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy +# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K +# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV +# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr +# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx +# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe +# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g +# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf +# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI +# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 +# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea +# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS +# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 +# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla +# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS +# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT +# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG +# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S +# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz +# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 +# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u +# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 +# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl +# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP +# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB +# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF +# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM +# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ +# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud +# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO +# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 +# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p +# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB +# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw +# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA +# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY +# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj +# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd +# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ +# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf +# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ +# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j +# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B +# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 +# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 +# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I +# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN +# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor +# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgSAuohsCY +# 1WvrvFLuGrpt391tmwt+DwhUHagVMNjTnc8wQgYKKwYBBAGCNwIBDDE0MDKgFIAS +# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN +# BgkqhkiG9w0BAQEFAASCAQC89iy3NBWqZwCUaYz9XoaWyi+tTrpqb9+KYQaMxL1n +# 7H+h7RImGRiyznWchO8G37mvbG6RrWxH0IY1u14s3qRqGdoD01GoAOtTMVf8Nmf5 +# LCT1xD5B2W+kVY/lWnF2FKNvB5w6qB05eMLyt4d4ORMjLBrh1cz2BonkY5xd3/MT +# MHiwKmnJD3esZHlV0HVzTXKu10lQr3BKGIICX3tUMY1nZI2T7ENcxz3k1GQer+Gm +# K8edSssSn0lLZS1qyxx2ainSqFx6W5I9tpB5QPqRGs9ObHanV4PfyXVIJ1fvjrKN +# ubmxC3Ev1t08dLInjHyVisq5IvumU3MhM1WenSnEv0E0oYIS8TCCEu0GCisGAQQB +# gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME +# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB +# MDEwDQYJYIZIAWUDBAIBBQAEICNGSHQ9aQGoYVLoatBgJT7hrcZ0kz7R5r99heVm +# n9eHAgZepuaL2lgYEzIwMjAwNTI4MDcxMTI2LjQ3MlowBIACAfSggdSkgdEwgc4x +# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt +# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p +# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg +# VFNTIEVTTjowQTU2LUUzMjktNEQ0RDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt +# U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABJy9uo++RqBmoAAAA +# AAEnMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo +# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw +# MB4XDTE5MTIxOTAxMTQ1OVoXDTIxMDMxNzAxMTQ1OVowgc4xCzAJBgNVBAYTAlVT +# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK +# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy +# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjowQTU2 +# LUUzMjktNEQ0RDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj +# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPgB3nERnk6fS40vvWeD +# 3HCgM9Ep4xTIQiPnJXE9E+HkZVtTsPemoOyhfNAyF95E/rUvXOVTUcJFL7Xb16jT +# KPXONsCWY8DCixSDIiid6xa30TiEWVcIZRwiDlcx29D467OTav5rA1G6TwAEY5rQ +# jhUHLrOoJgfJfakZq6IHjd+slI0/qlys7QIGakFk2OB6mh/ln/nS8G4kNRK6Do4g +# xDtnBSFLNfhsSZlRSMDJwFvrZ2FCkaoexd7rKlUNOAAScY411IEqQeI1PwfRm3aW +# bS8IvAfJPC2Ah2LrtP8sKn5faaU8epexje7vZfcZif/cbxgUKStJzqbdvTBNc93n +# /Z8CAwEAAaOCARswggEXMB0GA1UdDgQWBBTl9JZVgF85MSRbYlOJXbhY022V8jAf +# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH +# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU +# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF +# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 +# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG +# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQAKyo180VXHBqVnjZwQy7NlzXbo2+W5 +# qfHxR7ANV5RBkRkdGamkwUcDNL+DpHObFPJHa0oTeYKE0Zbl1MvvfS8RtGGdhGYG +# CJf+BPd/gBCs4+dkZdjvOzNyuVuDPGlqQ5f7HS7iuQ/cCyGHcHYJ0nXVewF2Lk+J +# lrWykHpTlLwPXmCpNR+gieItPi/UMF2RYTGwojW+yIVwNyMYnjFGUxEX5/DtJjRZ +# mg7PBHMrENN2DgO6wBelp4ptyH2KK2EsWT+8jFCuoKv+eJby0QD55LN5f8SrUPRn +# K86fh7aVOfCglQofo5ABZIGiDIrg4JsV4k6p0oBSIFOAcqRAhiH+1spCMIIGcTCC +# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC +# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv +# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN +# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv +# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw +# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0 +# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw +# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe +# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx +# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G +# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA +# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7 +# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC +# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX +# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v +# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI +# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g +# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93 +# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB +# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA +# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh +# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS +# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK +# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon +# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi +# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/ +# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII +# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0 +# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a +# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ +# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ +# NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT +# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD +# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP +# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjow +# QTU2LUUzMjktNEQ0RDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy +# dmljZaIjCgEBMAcGBSsOAwIaAxUAs5W4TmyDHMRM7iz6mgGojqvXHzOggYMwgYCk +# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD +# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF +# AOJ5mikwIhgPMjAyMDA1MjgwNjAyMTdaGA8yMDIwMDUyOTA2MDIxN1owdzA9Bgor +# BgEEAYRZCgQBMS8wLTAKAgUA4nmaKQIBADAKAgEAAgIghAIB/zAHAgEAAgIRsTAK +# AgUA4nrrqQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB +# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAKlrFVoLzatzP6jP +# zjn/Uk7ez7jWLI5wxXcP+z6595VcC/2ZsI3HN7LIdB6Bp80Tiz1Te2S5pUBGm1OD +# TwvbRARh2Ocs8XSCV01rt3RaSnmV2XzZwpPiPMM1xWz7sGfvkxh/P/ERYPvD90e1 +# c/lup9Qod2acmX5UPbBCJ17pH/JsMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC +# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp +# bWUtU3RhbXAgUENBIDIwMTACEzMAAAEnL26j75GoGagAAAAAAScwDQYJYIZIAWUD +# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B +# CQQxIgQggrSfnkwcsMTOxiqyqyp6WA8bdfFsGWnVxlMc42q2NqowgfoGCyqGSIb3 +# DQEJEAIvMYHqMIHnMIHkMIG9BCAbkuhLEoYdahb/BUyVszO2VDi6kB3MSaof/+8u +# 7SM+IjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u +# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp +# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB +# Jy9uo++RqBmoAAAAAAEnMCIEIAYecV94YBfChiHO2X367cIGW5iIaPzmTqnRpYsp +# 9/mvMA0GCSqGSIb3DQEBCwUABIIBAI5HhXklMmMwHFtce3Jot4RdGHmWqtlIZy2Z +# cxWtT+CNVhGpdKZVgnH2BoLj/sGDgYWCCEG4fElhYR+QvnBtXewteI0XPb0funyG +# epL5QVCcTw+GsBrkAtDn20hLn7YoybL66psj5cUCve1jdry5XZEntyMCQgQCNluw +# 23iNRHGEH2nWBSBdwuatvtxHQhXEPhUOUxfYijGdzwbA4bz83hLI5lFIvia6wH+P +# bwHSlaOybJ3P7wjXnImLOHcuKouU7MInBY3rV3dkZ8v5YhLQQ0zAdnAZ0sBqIMlx +# rrmDvenSWGeCavl2FyhrtSPZyW3t2ykSIDl+eJ60vE0u0crIyuo= +# SIG # End signature block diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Hyak.Common.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Hyak.Common.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/Hyak.Common.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Hyak.Common.dll diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.ApplicationInsights.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.ApplicationInsights.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.ApplicationInsights.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.ApplicationInsights.dll diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.Common.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.Common.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.Common.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.Common.dll diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll new file mode 100644 index 0000000000000000000000000000000000000000..29a8b6bdf3236274f0f4a925d15a88c2b995cf6a GIT binary patch literal 101760 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 PHfmkXg5_)zAqf8;c@mLM literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json similarity index 90% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json index de3ac377af5..b42bc3fddc1 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.deps.json @@ -13,21 +13,21 @@ "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", "Microsoft.Azure.PowerShell.Authentication": "1.0.0", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "NETStandard.Library": "2.0.3", @@ -77,7 +77,7 @@ } } }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.Azure.Common": "2.2.1", @@ -87,11 +87,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -100,11 +100,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Aks.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -113,11 +113,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Authorization.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -126,15 +126,15 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Compute.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -142,11 +142,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Graph.Rbac.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -161,11 +161,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.KeyVault.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -179,14 +179,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Monitor.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -194,11 +194,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Network.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -207,14 +207,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.PolicyInsights.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -222,11 +222,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.ResourceManager.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -235,11 +235,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -253,16 +253,16 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Websites.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -270,23 +270,23 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Common.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20" }, "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Storage.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -295,7 +295,7 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Strategies.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, @@ -1153,21 +1153,21 @@ "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.19.2", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -1206,110 +1206,110 @@ "path": "microsoft.azure.common/2.2.1", "hashPath": "microsoft.azure.common.2.2.1.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Xqxbr64G6km1CnJEzfE+mJqN9ehYCVlURmOECbUOS68XkRkG9cYN9eUz70YAoyLz/exdKlm5EUnaE6Cd4UiMfA==", - "path": "microsoft.azure.powershell.authentication.abstractions/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-ETNjmwE9SjJgKngxlOcwoGRfuoJ3PfaYU+BA2hK6AFxiaYS5oh6RCzZdi8D00cICjmmfeJW0/YOgh07LChXvzg==", + "path": "microsoft.azure.powershell.authentication.abstractions/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-hUBtnv5oknG1AHJzPQUx75hDePgwg+f7xzWGUo1JUGiGxnSQ3g+U2z5PpPUX48xpbuQ6BS+cxl7lG/wqyzkyNQ==", - "path": "microsoft.azure.powershell.clients.aks/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.aks.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-JWxCoGP5cc8jIs6hIVpzKr4NqlVw9b/t6HRyGzz26hBdFwUB7vjC85iOMwNyXx3k7pQYyhpboXskMUjR7m7Y8w==", + "path": "microsoft.azure.powershell.clients.aks/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.aks.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-VGJHNeqYk9P1rrhTC+acZKiCE+XcmcFAJgCvmXMsFP0HoTydtmI+7fMGN5pnxZo4BrYZhlzcq1BKau9iOJg5Ug==", - "path": "microsoft.azure.powershell.clients.authorization/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-FXB2541v1wLgutY9nEDdhoFRe5Xx5k7AkFUc7gVyXw7rpv40iU8hBFEdN2U5EWI6PD3YXuPf19knEodB+EhKfw==", + "path": "microsoft.azure.powershell.clients.authorization/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Z0Im2Ug9EI3ILic32qnwE+0FEBikWHJd7eWVgQvHiLOTJ395SA6xDGeVKJ3KJdtAigB9SYW0cEB73yukkZMxIA==", - "path": "microsoft.azure.powershell.clients.compute/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.compute.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-AJ5FVC2Cx9NkPLnovuF/+3kkXJOtrtbAPaaeLXsJ5DCdr/rOARgaIzMZERPDZ0KZaq9Wbz9RX2Tiq+MoemL/jw==", + "path": "microsoft.azure.powershell.clients.compute/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.compute.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-rB/87uRPZRSknc46YZqkH1WXsOzwcB1Zr9/Ji8+eJv3/62jIZ1eShZ+g/WrdH/q8qFNCerpYeYYH073P1BiRvg==", - "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nJ8cNAUi1TPt2Uwu+ltbiqpfbsPRB6emxSsgN2+AAUlSnmxECN2ED8vehDCV0cgSA9ctkdfvTffP62J7yEZIvw==", + "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dtQI7phThrQXJv0yq4oSekOMkDd+OQIeEt7hzldOdp7UsI0P761mGCus+WWf1QnnkfwK2fEdqWp1p5fa0J2XBQ==", - "path": "microsoft.azure.powershell.clients.keyvault/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nUzPB8cqLkpCm9tJ4jTmD19HyLfoVlRGyISd9VhvtMKbXeCe8ALOfjrvd0iA0STPSsvfv5SQJjzpm4z7oWwnDw==", + "path": "microsoft.azure.powershell.clients.keyvault/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dXaNnPmMukMg8Z4V3v8gloAy8b3Esmv7RJ2EpjpJsPE3kn66Sk5mL4xYCn4vYDLsjk+RDK7G2wNS9iZNHGy55A==", - "path": "microsoft.azure.powershell.clients.monitor/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Qn5ZCRf0X5hwHxX2necOdw4aI1BfBO+PfvxW+vCV8sKLZO6NMws7Ah6KelkxyReqJ25IyTkKaDw1uzvxB4srbA==", + "path": "microsoft.azure.powershell.clients.monitor/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-0LGD9Mq8FodlL/y3CoFwKbiKfPztcNVS4Gs3YdLty5WBwEVqFyeF+EFO6rJh79A1gfL6/PZC1DATy3RLO10ZuQ==", - "path": "microsoft.azure.powershell.clients.network/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.network.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-cXZY84Ngul8uWrWGRsYMhgjzUQzPEpotG0kK36x29SUped8+LHj4tFlw1zQzguMn4wlJKKg9EqHeO7tvYk1Clw==", + "path": "microsoft.azure.powershell.clients.network/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.network.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-k/4FIRfVPMLPkfppJlAZsbo2uuCSx9GjehDDKvpeyMWkY8E7423DklbJAS35KGCsm9VPqfcSdk6oqLD8q8hm8Q==", - "path": "microsoft.azure.powershell.clients.policyinsights/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-B7tgo5CckvUaO4KtHb+R8B/ou1gknGIuKggvQeWnf5ef0w5uVoQYx+Z34AJeDQou8yqoQhwcxri/BDovY1S3Ng==", + "path": "microsoft.azure.powershell.clients.policyinsights/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QfnsA+f9iM4bv/NpYDxl8I/axEdT7IHxnprK+sFso0evbLEwnzaHTTe7+WjO+GIJhdH+x6C3ZX+A1PmbWknjBw==", - "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-jhbIeAHnlorlyuVbeFSCu3EwxWRE+zQIjbQpCktPVOyWSVazuupZOd8pIMYwWKQ17ECNBmZT1hTxemQq6g0MVA==", + "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-yglEu0Wz2VJrzHJreLpBG1MWKpjBFLYyFgO+rOpuac669rTA9sZdeIhG1ZirMX0+Yf6KqNvrVx4ipLHXbRQqUA==", - "path": "microsoft.azure.powershell.clients.storage.management/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-chQnmrzfsCrkM7vjVYLowGkQ3uZXjYXdWFx6dbDRsVKJdZMruECGojUJzsXmmGzw0tcX0PUuLcOSPgrX64tDUw==", + "path": "microsoft.azure.powershell.clients.storage.management/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-NHjNDNC9Gzf26DYSwzl87Y1Dlc1rkFwFM6qaTyPllFG66qYzNzUmDqx0SIwHojdGxUb2jfLEzW7kH8hstt4kAg==", - "path": "microsoft.azure.powershell.clients.websites/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.websites.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-n0CrbLC7mGvKcJgWHhPd36I4xjvPi451Qkhe4njW1LcK1sSgsu/F+N7MKbWgFVdAgfHF7nBNseaF6uPTAVxO4Q==", + "path": "microsoft.azure.powershell.clients.websites/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.websites.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QtuzSQichST5FFl/nPL30S3InM/acZ65iq3um2CWGH+OrVJYcbYG4jG++5TQUCCZELhgV3Pl0RExFbo0gLd2Zw==", - "path": "microsoft.azure.powershell.common/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.common.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-/gOD/wU1cHvwqMk0TylhYOaOIxnYX9mK3JbwbjVxlkxIw6kUNfaS8vw4ZBIwzNR8o2GfUut3rBniaXfP+ZU99g==", + "path": "microsoft.azure.powershell.common/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.common.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-j1Ag9gJj3J8Yknfuo976gx4XqZd2cK7o5zpH5MIsUHMJb45lA3AC0aVw3P4Xue0tQaLzHAdun77Y8tTQebLyxg==", - "path": "microsoft.azure.powershell.storage/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.storage.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-efBoANDAUqPCvSAQ+KVe83bBooeCnKcmN2fulZEUxSeoVkTmIzpY+lpBIQfAK5aIqlIE/usvRRW/tyqjIvlprQ==", + "path": "microsoft.azure.powershell.storage/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.storage.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Vh8alQsYjEVq26aIyNRF9QCaNSuMXN9lA0RupxFU0kYmJO7lo3Oz9iXz6KR5+tsyeZYTeLK3G7OaQ/bIUIxhhw==", - "path": "microsoft.azure.powershell.strategies/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.strategies.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Cg5OnAFIfF7Wb0oUvQ8R/+j01RHjvGT/kLy+KOxsX9eS86RaZHiP4ZT5UYLIp+d3ASVTuQ8BcGn/18fqqgZuNQ==", + "path": "microsoft.azure.powershell.strategies/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.strategies.1.3.14-preview.nupkg.sha512" }, "Microsoft.CSharp/4.3.0": { "type": "package", diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.ResourceManager.dll new file mode 100644 index 0000000000000000000000000000000000000000..1cf97f717333e9550ee4111c925191279d931aff GIT binary patch literal 70520 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 literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.deps.json b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.deps.json similarity index 91% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.deps.json rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.deps.json index 2b8db42127a..d57557585a3 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.deps.json +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.deps.json @@ -12,21 +12,21 @@ "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.19.2", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -77,7 +77,7 @@ } } }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.Azure.Common": "2.2.1", @@ -87,11 +87,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -100,11 +100,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Aks.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -113,11 +113,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Authorization.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -126,15 +126,15 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Compute.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -142,11 +142,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Graph.Rbac.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -161,11 +161,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.KeyVault.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -179,14 +179,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Monitor.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -194,11 +194,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Network.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -207,14 +207,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.PolicyInsights.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -222,11 +222,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.ResourceManager.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -235,11 +235,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -253,16 +253,16 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Websites.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -270,23 +270,23 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Common.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20" }, "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Storage.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -295,7 +295,7 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Strategies.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, @@ -1177,110 +1177,110 @@ "path": "microsoft.azure.common/2.2.1", "hashPath": "microsoft.azure.common.2.2.1.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Xqxbr64G6km1CnJEzfE+mJqN9ehYCVlURmOECbUOS68XkRkG9cYN9eUz70YAoyLz/exdKlm5EUnaE6Cd4UiMfA==", - "path": "microsoft.azure.powershell.authentication.abstractions/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-ETNjmwE9SjJgKngxlOcwoGRfuoJ3PfaYU+BA2hK6AFxiaYS5oh6RCzZdi8D00cICjmmfeJW0/YOgh07LChXvzg==", + "path": "microsoft.azure.powershell.authentication.abstractions/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-hUBtnv5oknG1AHJzPQUx75hDePgwg+f7xzWGUo1JUGiGxnSQ3g+U2z5PpPUX48xpbuQ6BS+cxl7lG/wqyzkyNQ==", - "path": "microsoft.azure.powershell.clients.aks/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.aks.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-JWxCoGP5cc8jIs6hIVpzKr4NqlVw9b/t6HRyGzz26hBdFwUB7vjC85iOMwNyXx3k7pQYyhpboXskMUjR7m7Y8w==", + "path": "microsoft.azure.powershell.clients.aks/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.aks.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-VGJHNeqYk9P1rrhTC+acZKiCE+XcmcFAJgCvmXMsFP0HoTydtmI+7fMGN5pnxZo4BrYZhlzcq1BKau9iOJg5Ug==", - "path": "microsoft.azure.powershell.clients.authorization/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-FXB2541v1wLgutY9nEDdhoFRe5Xx5k7AkFUc7gVyXw7rpv40iU8hBFEdN2U5EWI6PD3YXuPf19knEodB+EhKfw==", + "path": "microsoft.azure.powershell.clients.authorization/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Z0Im2Ug9EI3ILic32qnwE+0FEBikWHJd7eWVgQvHiLOTJ395SA6xDGeVKJ3KJdtAigB9SYW0cEB73yukkZMxIA==", - "path": "microsoft.azure.powershell.clients.compute/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.compute.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-AJ5FVC2Cx9NkPLnovuF/+3kkXJOtrtbAPaaeLXsJ5DCdr/rOARgaIzMZERPDZ0KZaq9Wbz9RX2Tiq+MoemL/jw==", + "path": "microsoft.azure.powershell.clients.compute/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.compute.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-rB/87uRPZRSknc46YZqkH1WXsOzwcB1Zr9/Ji8+eJv3/62jIZ1eShZ+g/WrdH/q8qFNCerpYeYYH073P1BiRvg==", - "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nJ8cNAUi1TPt2Uwu+ltbiqpfbsPRB6emxSsgN2+AAUlSnmxECN2ED8vehDCV0cgSA9ctkdfvTffP62J7yEZIvw==", + "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dtQI7phThrQXJv0yq4oSekOMkDd+OQIeEt7hzldOdp7UsI0P761mGCus+WWf1QnnkfwK2fEdqWp1p5fa0J2XBQ==", - "path": "microsoft.azure.powershell.clients.keyvault/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nUzPB8cqLkpCm9tJ4jTmD19HyLfoVlRGyISd9VhvtMKbXeCe8ALOfjrvd0iA0STPSsvfv5SQJjzpm4z7oWwnDw==", + "path": "microsoft.azure.powershell.clients.keyvault/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dXaNnPmMukMg8Z4V3v8gloAy8b3Esmv7RJ2EpjpJsPE3kn66Sk5mL4xYCn4vYDLsjk+RDK7G2wNS9iZNHGy55A==", - "path": "microsoft.azure.powershell.clients.monitor/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Qn5ZCRf0X5hwHxX2necOdw4aI1BfBO+PfvxW+vCV8sKLZO6NMws7Ah6KelkxyReqJ25IyTkKaDw1uzvxB4srbA==", + "path": "microsoft.azure.powershell.clients.monitor/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-0LGD9Mq8FodlL/y3CoFwKbiKfPztcNVS4Gs3YdLty5WBwEVqFyeF+EFO6rJh79A1gfL6/PZC1DATy3RLO10ZuQ==", - "path": "microsoft.azure.powershell.clients.network/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.network.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-cXZY84Ngul8uWrWGRsYMhgjzUQzPEpotG0kK36x29SUped8+LHj4tFlw1zQzguMn4wlJKKg9EqHeO7tvYk1Clw==", + "path": "microsoft.azure.powershell.clients.network/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.network.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-k/4FIRfVPMLPkfppJlAZsbo2uuCSx9GjehDDKvpeyMWkY8E7423DklbJAS35KGCsm9VPqfcSdk6oqLD8q8hm8Q==", - "path": "microsoft.azure.powershell.clients.policyinsights/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-B7tgo5CckvUaO4KtHb+R8B/ou1gknGIuKggvQeWnf5ef0w5uVoQYx+Z34AJeDQou8yqoQhwcxri/BDovY1S3Ng==", + "path": "microsoft.azure.powershell.clients.policyinsights/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QfnsA+f9iM4bv/NpYDxl8I/axEdT7IHxnprK+sFso0evbLEwnzaHTTe7+WjO+GIJhdH+x6C3ZX+A1PmbWknjBw==", - "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-jhbIeAHnlorlyuVbeFSCu3EwxWRE+zQIjbQpCktPVOyWSVazuupZOd8pIMYwWKQ17ECNBmZT1hTxemQq6g0MVA==", + "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-yglEu0Wz2VJrzHJreLpBG1MWKpjBFLYyFgO+rOpuac669rTA9sZdeIhG1ZirMX0+Yf6KqNvrVx4ipLHXbRQqUA==", - "path": "microsoft.azure.powershell.clients.storage.management/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-chQnmrzfsCrkM7vjVYLowGkQ3uZXjYXdWFx6dbDRsVKJdZMruECGojUJzsXmmGzw0tcX0PUuLcOSPgrX64tDUw==", + "path": "microsoft.azure.powershell.clients.storage.management/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-NHjNDNC9Gzf26DYSwzl87Y1Dlc1rkFwFM6qaTyPllFG66qYzNzUmDqx0SIwHojdGxUb2jfLEzW7kH8hstt4kAg==", - "path": "microsoft.azure.powershell.clients.websites/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.websites.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-n0CrbLC7mGvKcJgWHhPd36I4xjvPi451Qkhe4njW1LcK1sSgsu/F+N7MKbWgFVdAgfHF7nBNseaF6uPTAVxO4Q==", + "path": "microsoft.azure.powershell.clients.websites/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.websites.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QtuzSQichST5FFl/nPL30S3InM/acZ65iq3um2CWGH+OrVJYcbYG4jG++5TQUCCZELhgV3Pl0RExFbo0gLd2Zw==", - "path": "microsoft.azure.powershell.common/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.common.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-/gOD/wU1cHvwqMk0TylhYOaOIxnYX9mK3JbwbjVxlkxIw6kUNfaS8vw4ZBIwzNR8o2GfUut3rBniaXfP+ZU99g==", + "path": "microsoft.azure.powershell.common/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.common.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-j1Ag9gJj3J8Yknfuo976gx4XqZd2cK7o5zpH5MIsUHMJb45lA3AC0aVw3P4Xue0tQaLzHAdun77Y8tTQebLyxg==", - "path": "microsoft.azure.powershell.storage/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.storage.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-efBoANDAUqPCvSAQ+KVe83bBooeCnKcmN2fulZEUxSeoVkTmIzpY+lpBIQfAK5aIqlIE/usvRRW/tyqjIvlprQ==", + "path": "microsoft.azure.powershell.storage/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.storage.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Vh8alQsYjEVq26aIyNRF9QCaNSuMXN9lA0RupxFU0kYmJO7lo3Oz9iXz6KR5+tsyeZYTeLK3G7OaQ/bIUIxhhw==", - "path": "microsoft.azure.powershell.strategies/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.strategies.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Cg5OnAFIfF7Wb0oUvQ8R/+j01RHjvGT/kLy+KOxsX9eS86RaZHiP4ZT5UYLIp+d3ASVTuQ8BcGn/18fqqgZuNQ==", + "path": "microsoft.azure.powershell.strategies/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.strategies.1.3.14-preview.nupkg.sha512" }, "Microsoft.CSharp/4.3.0": { "type": "package", diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.dll similarity index 91% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Authentication.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Authentication.dll index 509252112550d248c6217b6138420a8653a1522a..b875aab2ac95c5f0bb2804bbdc85d797a0dd4841 100644 GIT binary patch delta 4420 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 delta 4358 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 delta 3809 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 B`wp=3>?Wh^1#hR7O1 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 Fe*r1SxwQZQ delta 3659 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 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.KeyVault.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.KeyVault.dll similarity index 95% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.KeyVault.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.KeyVault.dll index 27fd361ac74772f96b212c964b0a7821e83e325e..48084e9b118710bc1f5822afb5136ed1cb0fb084 100644 GIT binary patch delta 3400 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 delta 3591 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 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Monitor.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Monitor.dll similarity index 98% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Monitor.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Monitor.dll index e4e62026c836020630e0a1b392b51ecbcf1cc1fa..c9ba30e65e64b89e2bb2a51d7cdb19d82ab1ecb2 100644 GIT binary patch delta 3435 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 delta 3600 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 D`VHsO diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Network.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Network.dll similarity index 99% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Network.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Network.dll index a6343616befa5a3f7b35e95f42962c0fc6fb6e02..ed5099a953f4b5b734aafbae3a8a53332dfa378f 100644 GIT binary patch delta 3526 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 AegFUf delta 3691 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 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll similarity index 94% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll index 6b866774f5a4a57d05c3469a10a35edfa8be7230..b9675dcf8b193ca40eb3560801b2e6865198aed6 100644 GIT binary patch delta 3442 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 H07Cu)K_L1p diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Websites.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Websites.dll similarity index 99% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Clients.Websites.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Clients.Websites.dll index 2e37ed9a27bdd58929be8ffb74b6bd6a21fc4929..6073480a7f7a6e0bb47af22f549ccb857c12342c 100644 GIT binary patch delta 3683 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 KSnAIfiufC5yna#u diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json similarity index 90% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json index 1d3961f5532..13610a76691 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json +++ b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Cmdlets.Accounts.deps.json @@ -13,22 +13,22 @@ "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", "Microsoft.Azure.PowerShell.Authentication": "1.0.0", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Azure.PowerShell.Authentication.ResourceManager": "1.0.0", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "NETStandard.Library": "2.0.3", @@ -79,7 +79,7 @@ } } }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.Azure.Common": "2.2.1", @@ -89,11 +89,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Authentication.Abstractions.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -102,11 +102,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Aks.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -115,11 +115,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Authorization.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -128,15 +128,15 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Compute.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -144,11 +144,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Graph.Rbac.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -163,11 +163,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.KeyVault.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -181,14 +181,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Monitor.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -196,11 +196,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Network.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -209,14 +209,14 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.PolicyInsights.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -224,11 +224,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.ResourceManager.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -237,11 +237,11 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Storage.Management.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -255,16 +255,16 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Clients.Websites.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "dependencies": { "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -272,23 +272,23 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Common.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "dependencies": { - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20" }, "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Storage.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "dependencies": { "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -297,7 +297,7 @@ "runtime": { "lib/netstandard2.0/Microsoft.Azure.PowerShell.Strategies.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.3.11.0" + "fileVersion": "1.3.14.0" } } }, @@ -1185,21 +1185,21 @@ "Hyak.Common": "1.2.2", "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.19.2", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", @@ -1215,21 +1215,21 @@ "Microsoft.ApplicationInsights": "2.4.0", "Microsoft.Azure.Common": "2.2.1", "Microsoft.Azure.PowerShell.Authentication": "1.0.0", - "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Network": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Common": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Storage": "1.3.11-preview", - "Microsoft.Azure.PowerShell.Strategies": "1.3.11-preview", + "Microsoft.Azure.PowerShell.Authentication.Abstractions": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Aks": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Authorization": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Compute": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.KeyVault": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Monitor": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Network": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.PolicyInsights": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.ResourceManager": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Storage.Management": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Clients.Websites": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Common": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Storage": "1.3.14-preview", + "Microsoft.Azure.PowerShell.Strategies": "1.3.14-preview", "Microsoft.Rest.ClientRuntime": "2.3.20", "Microsoft.Rest.ClientRuntime.Azure": "3.3.19", "Newtonsoft.Json": "10.0.3" @@ -1267,110 +1267,110 @@ "path": "microsoft.azure.common/2.2.1", "hashPath": "microsoft.azure.common.2.2.1.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Authentication.Abstractions/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Xqxbr64G6km1CnJEzfE+mJqN9ehYCVlURmOECbUOS68XkRkG9cYN9eUz70YAoyLz/exdKlm5EUnaE6Cd4UiMfA==", - "path": "microsoft.azure.powershell.authentication.abstractions/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-ETNjmwE9SjJgKngxlOcwoGRfuoJ3PfaYU+BA2hK6AFxiaYS5oh6RCzZdi8D00cICjmmfeJW0/YOgh07LChXvzg==", + "path": "microsoft.azure.powershell.authentication.abstractions/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.authentication.abstractions.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Aks/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Aks/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-hUBtnv5oknG1AHJzPQUx75hDePgwg+f7xzWGUo1JUGiGxnSQ3g+U2z5PpPUX48xpbuQ6BS+cxl7lG/wqyzkyNQ==", - "path": "microsoft.azure.powershell.clients.aks/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.aks.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-JWxCoGP5cc8jIs6hIVpzKr4NqlVw9b/t6HRyGzz26hBdFwUB7vjC85iOMwNyXx3k7pQYyhpboXskMUjR7m7Y8w==", + "path": "microsoft.azure.powershell.clients.aks/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.aks.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Authorization/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-VGJHNeqYk9P1rrhTC+acZKiCE+XcmcFAJgCvmXMsFP0HoTydtmI+7fMGN5pnxZo4BrYZhlzcq1BKau9iOJg5Ug==", - "path": "microsoft.azure.powershell.clients.authorization/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-FXB2541v1wLgutY9nEDdhoFRe5Xx5k7AkFUc7gVyXw7rpv40iU8hBFEdN2U5EWI6PD3YXuPf19knEodB+EhKfw==", + "path": "microsoft.azure.powershell.clients.authorization/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.authorization.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Compute/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Compute/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Z0Im2Ug9EI3ILic32qnwE+0FEBikWHJd7eWVgQvHiLOTJ395SA6xDGeVKJ3KJdtAigB9SYW0cEB73yukkZMxIA==", - "path": "microsoft.azure.powershell.clients.compute/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.compute.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-AJ5FVC2Cx9NkPLnovuF/+3kkXJOtrtbAPaaeLXsJ5DCdr/rOARgaIzMZERPDZ0KZaq9Wbz9RX2Tiq+MoemL/jw==", + "path": "microsoft.azure.powershell.clients.compute/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.compute.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Graph.Rbac/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-rB/87uRPZRSknc46YZqkH1WXsOzwcB1Zr9/Ji8+eJv3/62jIZ1eShZ+g/WrdH/q8qFNCerpYeYYH073P1BiRvg==", - "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nJ8cNAUi1TPt2Uwu+ltbiqpfbsPRB6emxSsgN2+AAUlSnmxECN2ED8vehDCV0cgSA9ctkdfvTffP62J7yEZIvw==", + "path": "microsoft.azure.powershell.clients.graph.rbac/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.graph.rbac.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.KeyVault/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dtQI7phThrQXJv0yq4oSekOMkDd+OQIeEt7hzldOdp7UsI0P761mGCus+WWf1QnnkfwK2fEdqWp1p5fa0J2XBQ==", - "path": "microsoft.azure.powershell.clients.keyvault/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-nUzPB8cqLkpCm9tJ4jTmD19HyLfoVlRGyISd9VhvtMKbXeCe8ALOfjrvd0iA0STPSsvfv5SQJjzpm4z7oWwnDw==", + "path": "microsoft.azure.powershell.clients.keyvault/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.keyvault.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Monitor/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-dXaNnPmMukMg8Z4V3v8gloAy8b3Esmv7RJ2EpjpJsPE3kn66Sk5mL4xYCn4vYDLsjk+RDK7G2wNS9iZNHGy55A==", - "path": "microsoft.azure.powershell.clients.monitor/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Qn5ZCRf0X5hwHxX2necOdw4aI1BfBO+PfvxW+vCV8sKLZO6NMws7Ah6KelkxyReqJ25IyTkKaDw1uzvxB4srbA==", + "path": "microsoft.azure.powershell.clients.monitor/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.monitor.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Network/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Network/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-0LGD9Mq8FodlL/y3CoFwKbiKfPztcNVS4Gs3YdLty5WBwEVqFyeF+EFO6rJh79A1gfL6/PZC1DATy3RLO10ZuQ==", - "path": "microsoft.azure.powershell.clients.network/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.network.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-cXZY84Ngul8uWrWGRsYMhgjzUQzPEpotG0kK36x29SUped8+LHj4tFlw1zQzguMn4wlJKKg9EqHeO7tvYk1Clw==", + "path": "microsoft.azure.powershell.clients.network/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.network.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.PolicyInsights/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-k/4FIRfVPMLPkfppJlAZsbo2uuCSx9GjehDDKvpeyMWkY8E7423DklbJAS35KGCsm9VPqfcSdk6oqLD8q8hm8Q==", - "path": "microsoft.azure.powershell.clients.policyinsights/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-B7tgo5CckvUaO4KtHb+R8B/ou1gknGIuKggvQeWnf5ef0w5uVoQYx+Z34AJeDQou8yqoQhwcxri/BDovY1S3Ng==", + "path": "microsoft.azure.powershell.clients.policyinsights/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.policyinsights.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.ResourceManager/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QfnsA+f9iM4bv/NpYDxl8I/axEdT7IHxnprK+sFso0evbLEwnzaHTTe7+WjO+GIJhdH+x6C3ZX+A1PmbWknjBw==", - "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-jhbIeAHnlorlyuVbeFSCu3EwxWRE+zQIjbQpCktPVOyWSVazuupZOd8pIMYwWKQ17ECNBmZT1hTxemQq6g0MVA==", + "path": "microsoft.azure.powershell.clients.resourcemanager/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.resourcemanager.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Storage.Management/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-yglEu0Wz2VJrzHJreLpBG1MWKpjBFLYyFgO+rOpuac669rTA9sZdeIhG1ZirMX0+Yf6KqNvrVx4ipLHXbRQqUA==", - "path": "microsoft.azure.powershell.clients.storage.management/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-chQnmrzfsCrkM7vjVYLowGkQ3uZXjYXdWFx6dbDRsVKJdZMruECGojUJzsXmmGzw0tcX0PUuLcOSPgrX64tDUw==", + "path": "microsoft.azure.powershell.clients.storage.management/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.storage.management.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Clients.Websites/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Clients.Websites/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-NHjNDNC9Gzf26DYSwzl87Y1Dlc1rkFwFM6qaTyPllFG66qYzNzUmDqx0SIwHojdGxUb2jfLEzW7kH8hstt4kAg==", - "path": "microsoft.azure.powershell.clients.websites/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.clients.websites.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-n0CrbLC7mGvKcJgWHhPd36I4xjvPi451Qkhe4njW1LcK1sSgsu/F+N7MKbWgFVdAgfHF7nBNseaF6uPTAVxO4Q==", + "path": "microsoft.azure.powershell.clients.websites/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.clients.websites.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Common/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Common/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-QtuzSQichST5FFl/nPL30S3InM/acZ65iq3um2CWGH+OrVJYcbYG4jG++5TQUCCZELhgV3Pl0RExFbo0gLd2Zw==", - "path": "microsoft.azure.powershell.common/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.common.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-/gOD/wU1cHvwqMk0TylhYOaOIxnYX9mK3JbwbjVxlkxIw6kUNfaS8vw4ZBIwzNR8o2GfUut3rBniaXfP+ZU99g==", + "path": "microsoft.azure.powershell.common/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.common.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Storage/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Storage/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-j1Ag9gJj3J8Yknfuo976gx4XqZd2cK7o5zpH5MIsUHMJb45lA3AC0aVw3P4Xue0tQaLzHAdun77Y8tTQebLyxg==", - "path": "microsoft.azure.powershell.storage/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.storage.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-efBoANDAUqPCvSAQ+KVe83bBooeCnKcmN2fulZEUxSeoVkTmIzpY+lpBIQfAK5aIqlIE/usvRRW/tyqjIvlprQ==", + "path": "microsoft.azure.powershell.storage/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.storage.1.3.14-preview.nupkg.sha512" }, - "Microsoft.Azure.PowerShell.Strategies/1.3.11-preview": { + "Microsoft.Azure.PowerShell.Strategies/1.3.14-preview": { "type": "package", "serviceable": true, - "sha512": "sha512-Vh8alQsYjEVq26aIyNRF9QCaNSuMXN9lA0RupxFU0kYmJO7lo3Oz9iXz6KR5+tsyeZYTeLK3G7OaQ/bIUIxhhw==", - "path": "microsoft.azure.powershell.strategies/1.3.11-preview", - "hashPath": "microsoft.azure.powershell.strategies.1.3.11-preview.nupkg.sha512" + "sha512": "sha512-Cg5OnAFIfF7Wb0oUvQ8R/+j01RHjvGT/kLy+KOxsX9eS86RaZHiP4ZT5UYLIp+d3ASVTuQ8BcGn/18fqqgZuNQ==", + "path": "microsoft.azure.powershell.strategies/1.3.14-preview", + "hashPath": "microsoft.azure.powershell.strategies.1.3.14-preview.nupkg.sha512" }, "Microsoft.CSharp/4.3.0": { "type": "package", diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll similarity index 66% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll index 1585413c13cfe9ec38b4da9c68b729a703ec3c43..f9747c586149145b0d39d76c00fb68127f4bef44 100644 GIT binary patch delta 68939 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À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

RF{eI=gCp`63&yO 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 aok~A<-HE?W^)_`9L%-_>s-#m5X#WSf38Nzb literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Runtime.CompilerServices.Unsafe.dll b/powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 0000000000000000000000000000000000000000..be64036f12fe7cba2ad12805e011cea81b2320f8 GIT binary patch literal 18808 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�Q`Ssy68Q3pJ*Q4?78tE6iEZ%EU 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 literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/PostImportScripts/LoadAuthenticators.ps1 b/powershell/resources/modules/Az.Accounts/1.8.1/PostImportScripts/LoadAuthenticators.ps1 similarity index 63% rename from powershell/resources/modules/Az.Accounts/1.7.4/PostImportScripts/LoadAuthenticators.ps1 rename to powershell/resources/modules/Az.Accounts/1.8.1/PostImportScripts/LoadAuthenticators.ps1 index bebbc58aa1d..218322e074d 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/PostImportScripts/LoadAuthenticators.ps1 +++ b/powershell/resources/modules/Az.Accounts/1.8.1/PostImportScripts/LoadAuthenticators.ps1 @@ -7,39 +7,39 @@ # MIIjhgYJKoZIhvcNAQcCoIIjdzCCI3MCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD/helSA7zmokTO -# voMQIFn0NOno2ACkcCODe3RV4cMkvKCCDYEwggX/MIID56ADAgECAhMzAAABUZ6N -# j0Bxow5BAAAAAAFRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# voMQIFn0NOno2ACkcCODe3RV4cMkvKCCDYEwggX/MIID56ADAgECAhMzAAABh3IX +# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p -# bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw +# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -# AQCVWsaGaUcdNB7xVcNmdfZiVBhYFGcn8KMqxgNIvOZWNH9JYQLuhHhmJ5RWISy1 -# oey3zTuxqLbkHAdmbeU8NFMo49Pv71MgIS9IG/EtqwOH7upan+lIq6NOcw5fO6Os -# +12R0Q28MzGn+3y7F2mKDnopVu0sEufy453gxz16M8bAw4+QXuv7+fR9WzRJ2CpU -# 62wQKYiFQMfew6Vh5fuPoXloN3k6+Qlz7zgcT4YRmxzx7jMVpP/uvK6sZcBxQ3Wg -# B/WkyXHgxaY19IAzLq2QiPiX2YryiR5EsYBq35BP7U15DlZtpSs2wIYTkkDBxhPJ -# IDJgowZu5GyhHdqrst3OjkSRAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE -# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUV4Iarkq57esagu6FUBb270Zijc8w +# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB +# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH +# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d +# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ +# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV +# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 -# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU0MTM1MB8GA1UdIwQYMBaAFEhu +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx -# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAWg+A -# rS4Anq7KrogslIQnoMHSXUPr/RqOIhJX+32ObuY3MFvdlRElbSsSJxrRy/OCCZdS -# se+f2AqQ+F/2aYwBDmUQbeMB8n0pYLZnOPifqe78RBH2fVZsvXxyfizbHubWWoUf -# NW/FJlZlLXwJmF3BoL8E2p09K3hagwz/otcKtQ1+Q4+DaOYXWleqJrJUsnHs9UiL -# crVF0leL/Q1V5bshob2OTlZq0qzSdrMDLWdhyrUOxnZ+ojZ7UdTY4VnCuogbZ9Zs -# 9syJbg7ZUS9SVgYkowRsWv5jV4lbqTD+tG4FzhOwcRQwdb6A8zp2Nnd+s7VdCuYF -# sGgI41ucD8oxVfcAMjF9YX5N2s4mltkqnUe3/htVrnxKKDAwSYliaux2L7gKw+bD -# 1kEZ/5ozLRnJ3jjDkomTrPctokY/KaZ1qub0NUnmOKH+3xUK/plWJK8BOQYuU7gK -# YH7Yy9WSKNlP7pKj6i417+3Na/frInjnBkKRCJ/eYTvBH+s5guezpfQWtU4bNo/j -# 8Qw2vpTQ9w7flhH78Rmwd319+YTmhv7TcxDbWlyteaj4RK2wk3pY1oSz2JPE5PNu -# Nmd9Gmf6oePZgy7Ii9JLLq8SnULV7b+IP0UXRY9q+GdRjM2AEX6msZvvPCIoG0aY -# HQu9wZsKEK2jqvWi8/xdeeeSI9FN6K1w4oVQM4Mwggd6MIIFYqADAgECAgphDpDS +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy +# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K +# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV +# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr +# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx +# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe +# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g +# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf +# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI +# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 +# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea +# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 @@ -82,52 +82,52 @@ # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWzCCFVcCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z -# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAVGejY9AcaMOQQAAAAABUTAN +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgh4BQ586h # Tqk36MSJKedOnw3lSOJxHG25rKnVeFjGH5owQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN -# BgkqhkiG9w0BAQEFAASCAQBFmxAfD+8GJoXgDiwldaZ0n8Ye7vj2qJi21WPZizjh -# xagOWA4fm2K3q0uZxRwsfQtnYAK5xD6gI5zvQ54IJffqU2pzbS0sJBE71PuJgtbL -# zNUKjStfI2qbFL9D6NS1F1G4rj0G/kXHqs9Q5zLaZUYCvIqIXJ/k6nQ8W4odtFZd -# EXOmFHNPDhrlaCpTXHhCgea+F5WfFLpJnmeeUcGIkCc97IF/AFfIHOKRP3ELSeE4 -# rvhycOlJqBRmNPhhYKD6j3arXw0G4NWLAiH8+tYFxYyfEEQlx9qL1MOqi9soyO/W -# Vg1a7wjs2GwhfHkE95N8YFhsrLIotPqIxTu+3Tvqq6e5oYIS5TCCEuEGCisGAQQB +# BgkqhkiG9w0BAQEFAASCAQBGVBuZ+EBbhPnuVojalkYYpGpB1qSRp4/IGlsMU1v7 +# iVZ+ADqhB0+Pzh1toFZH2QH/deDcOxsXiCHbb+PzW4kTMUNXbFJxTR+dFPpKKGod +# /bo1Jg1HaQTWzZ/0Xk1M8WgZfrcLusIjhg+NqLPvf8KxYubxWx2zPTE5fjzhAl1w +# r8M42a3ue4v56nkcWIyFJQqiQ52aFZNu3W3ZpKCjVfqWBUmPLOEyPZpRfUB/VVUP +# 3vIppRzvZ9+L78xv7IVMg7DTIbFAPRrRiPbM+3DaJAsCfPSr8G7FFrgYKDyRCI8e +# ghhJduoWCiHnLiOwa0ffzsBcttwPI8JEno//2NBJRbwQoYIS5TCCEuEGCisGAQQB # gjcDAwExghLRMIISzQYJKoZIhvcNAQcCoIISvjCCEroCAQMxDzANBglghkgBZQME # AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB -# MDEwDQYJYIZIAWUDBAIBBQAEILcDy2pHysJCIxms33rNltksyje0+3aV10sohMgk -# syhRAgZee4xcbnQYEzIwMjAwMzI3MTE0NjI2Ljg4OVowBIACAfSggdCkgc0wgcox +# MDEwDQYJYIZIAWUDBAIBBQAEIEjXCGTsuqTyuQmfXh1Z5hZBYwm/SLi3WPMMwsNa +# qnaQAgZeznA4GvIYEzIwMjAwNTI4MDcxMzI3LjY4N1owBIACAfSggdCkgc0wgcox # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p # Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg -# RVNOOjNCQkQtRTMzOC1FOUExMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt -# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAEdwsIIrj66rkgAAAAAAR0w +# RVNOOjNFN0EtRTM1OS1BMjVEMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt +# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAEgGjnb2WufrfIAAAAAASAw # DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN -# MTkxMTEzMjE0MDM5WhcNMjEwMjExMjE0MDM5WjCByjELMAkGA1UEBhMCVVMxEzAR +# MTkxMTEzMjE0MDQyWhcNMjEwMjExMjE0MDQyWjCByjELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg -# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046M0JCRC1FMzM4LUU5 -# QTExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G -# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCchQH6oX71mAoc+VCAKSiDgnETucME -# aJxwdS3HcbgOZ/tKrXE/FtiGPjteOzMfiSjoel30WiBUktEx1c6z/4C3XMIaHWNj -# 7/IR6D9Z77i2ium0KvIQKGsfmF9a6KMgg2HWM4RJfznaVWtH9T5KvItF2sHKDDce -# O/c7hUAaIzLqVCNME2r6Vr7kYfInu5NHH0qkgOIGZW9BVgmtpepWZoSuXcGmF/H1 -# Mc32N/Kv8sXV/hYlE3TTgCzA8s5tNovsophzD9X0AcssNsJ0qRqbA7u/sr3JZtQa -# zjPtjfw1wGvh1UMJ3lcmrgadwlllRw21Kzj1XNEu+NYp8izPI7qvoPzlAgMBAAGj -# ggEbMIIBFzAdBgNVHQ4EFgQUF15aFGDeyPIIvitDagjPwK2bwqkwHwYDVR0jBBgw +# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046M0U3QS1FMzU5LUEy +# NUQxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G +# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1BOuDmpgS5mLJDPUQaEcVyH5bHBLc +# 4Lvq5gGHF5J1yPhhbg8NSErV0fP+N5CQwe4KTLU/BROOpHlO/BV1UGOs+BavEPGR +# iVYdhAqKmzWU+TWbAOVxkrnpa/FJ6A5Q5cvINSiOabyOfHe2dMFCQPlggBzqC3x9 +# lnnJkUxSpetfTcj6FVCwxYVPk55zz4O4UpmeiHDiWEBpC9r64VHZZOSz89Z7ML1l +# penM2r8+WnabZLPoU2Y7p9QrPzQH7gvQiu/zgcYYMqmVIlfFTPS1iOvZbAqk1U6B +# NRgnOKirD+0+8yujM4CY/0DlZDDlLfU7Vg8ojsGg7peVh+MnYDwlyKGxAgMBAAGj +# ggEbMIIBFzAdBgNVHQ4EFgQUmdk2BLDfR8UfnN3pLGUCcaciVc8wHwYDVR0jBBgw # FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov # L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB # XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx # MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN -# BgkqhkiG9w0BAQsFAAOCAQEAYIyRnZDwDMs44NAV6+H6bPnjG99RXw4ReKdj0SSO -# 5IdwCFEjMLkPHfz9le5V3hABha6886EMxv3S29yfpUHW5qbCtLCn8CydiZ8eyNKc -# FHuKmEmw6syWq4U/tWOHj45vAFp1612VI3/+bZ0ng82AdN6jnjKluw/wTftqtG6I -# c/tNNY6xtqVR+ZZcq8oMEnKfYj3ovs2iW48L27yGtWD9F6huJSRIuIbK23M0vohR -# Oez5tnnWTLULo1cRj8tmadTLTcVOczgfu3Zza0zFuFBbUfkEZ0gMG61nJrkFnXil -# yXh94Fh6/9IwFGyDpoYH8J3BAUp/WhbeBfrQyTVWG8xJMDCCBnEwggRZoAMCAQIC +# BgkqhkiG9w0BAQsFAAOCAQEAYulQdnFLE5FCLMEUPpBNSy+OCJwmY7ihAF4Jye0S +# Q8fDJ0CYhsYU/uHUl8oTTuX5JQONX6QnKSU/+/0XuezSFtuYsN+uVrvGIciGXCKP +# uPtgFjFJBSW5y4xxurfzAuPO12wGJdVD4J+0ihF5Wr+RNUbX9MPiU+0qsIKDPs2p +# A3KNdXCP9m4WLi/+Fb0KMGwoX6XtDCvBHVw2qXbqcItlh4JfM9vLfjCgwS6zbIt7 +# igBKOLXRWaOqpeIfqsBHVitPN5RsneeXPqHpBOT+wCsm7lkqDAOS98RDWyJe8hZA +# geeXLHF7gL/lBgQbzScWYx0tg/4+hlPijywAAe0SBMDkmDCCBnEwggRZoAMCAQIC # CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp @@ -165,33 +165,33 @@ # X4/edIhJEqGCAs4wggI3AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP -# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozQkJELUUzMzgtRTlB -# MTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG -# BSsOAwIaAxUARCOfRHfis0duDUIQ/Cx9aR44J0KggYMwgYCkfjB8MQswCQYDVQQG +# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozRTdBLUUzNTktQTI1 +# RDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG +# BSsOAwIaAxUAv1r8uFykxw2Ng0e88GallxNnXkyggYMwgYCkfjB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg -# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOIoBQwwIhgPMjAy -# MDAzMjcxMjUyMjhaGA8yMDIwMDMyODEyNTIyOFowdzA9BgorBgEEAYRZCgQBMS8w -# LTAKAgUA4igFDAIBADAKAgEAAgIdQQIB/zAHAgEAAgIRsjAKAgUA4ilWjAIBADA2 +# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOJ5l3QwIhgPMjAy +# MDA1MjgwOTUwNDRaGA8yMDIwMDUyOTA5NTA0NFowdzA9BgorBgEEAYRZCgQBMS8w +# LTAKAgUA4nmXdAIBADAKAgEAAgIfEgIB/zAHAgEAAgISXzAKAgUA4nro9AIBADA2 # BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIB -# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAAgNNNuipjNxBHDKp6kKtdGhWjGK//k6 -# 8w4SZD4aBIEhzIF0KDGgtrI08Sgh5F2Vnecqhkl8RVgtPh9aOnpiC3OHX3QlAUYP -# /gSFmaG2R5s02DHRlB/5IHvGaWoxY4os60cmARoZD+Mzc7rR0fbD6XjsrvQLQpqS -# okMwRI6zuwcBMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAFllnKsruuDIfiyfK2KeJHWLOtBPvLfO +# AVFATuQvdCFvYHc+d70GI0mNSgvMBih7bQEQ/q/4BXoRcZUBuwCIKymkpukBjY75 +# dj/jnarEUfGFWIg7c1aWV8CZYRLKFz/L1YmfmKCJr0u5REsMyI7NFANev5nmowrH +# i/dj0tNTULS2MYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB -# IDIwMTACEzMAAAEdwsIIrj66rkgAAAAAAR0wDQYJYIZIAWUDBAIBBQCgggFKMBoG -# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgINFGOUz/ -# YryfqgL70jky+kHl1pDaZ37kFUUPy9ErcGwwgfoGCyqGSIb3DQEJEAIvMYHqMIHn -# MIHkMIG9BCACvgzDQp93fIcLrmzpCe2ICkJF7XEbUl7dckbpZe+akzCBmDCBgKR+ +# IDIwMTACEzMAAAEgGjnb2WufrfIAAAAAASAwDQYJYIZIAWUDBAIBBQCgggFKMBoG +# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgxi7cFz/h +# pyxJCuiajm56t5dJe6dQAvEI/Q7ZKEVEsqYwgfoGCyqGSIb3DQEJEAIvMYHqMIHn +# MIHkMIG9BCAcDFBrFJx21/VR4TsFktJBSYQgHP7GymOt92ieZ8AaVTCBmDCBgKR+ # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT -# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABHcLCCK4+uq5IAAAA -# AAEdMCIEIFSl1yYEMFgCI63B6dDPtVpsYp/4lKOVef29cYXNxD68MA0GCSqGSIb3 -# DQEBCwUABIIBAG829grVE3uHdojtAAZHU2m7FJZ70D1YTDWRF+QTJ9HS1+XRULD3 -# IM/jSOWAP66lYmr1gUUt98UXkS+jBiQyNOl8TNw9yxyMTZQMk3hmEHOd12mf+rWS -# u7WZva3CC8yoUfapjvTFiQx4jgPIuV9xNcXWJvlWUuzOlIr/rC+nJPNko7gR2ZUK -# uFuat7JHlI6iEBghxDn59cQft1d5bUMCLiyH8FJzVuSahpuC53Rx3LJxgt7RoKyX -# WdKH6mXLqWeGww2v/GJdCILBMHlYBcOEhmU3NSNnAuMNO1sGs/Tv8P7hDgPB9eoX -# R3opXxD4sfh7tg366/bzNdTi4DD1YADXXWg= +# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABIBo529lrn63yAAAA +# AAEgMCIEIDTYfwwgjIHOkjd6N0jsAjQgdAx9BUjVlPa0d8mHOvGZMA0GCSqGSIb3 +# DQEBCwUABIIBACeZPDbFXHb6PJwX3RuTqqu4hbrSVA1NQHZ91pSEqa7250r9bRLb +# 3JhzoA1ay0/7qPtzKxWhgSN7aYzX5lZrutVbkn6twEjgXMr2BroxETj2jhAhKYwP +# 4TkThu7/i17ZoYpLM5gUBsukR8bpK6QXbZDYJ+kl1cx+fVFzLnI4lHYCzMFI4zic +# w16kj3Azgltsfh6GtNfZ9lUI6riO6rfKGEt7EsvfJHv/FeqholYgSwVNrK6qBJhL +# KNmMxh2cA9GLo6JWGStsxcFajpuFAV4WysokgbHpikMFjY8NjtMsNnMKxd/dFiot +# WaldaA9wCGo/qXwpLz3V4dnI2CH1CownJFg= # SIG # End signature block diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Azure.Core.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Azure.Core.dll new file mode 100644 index 0000000000000000000000000000000000000000..e52829cd90e5e9c9304cdf1a6473e241845c3c5c GIT binary patch literal 128888 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 MomJEI3oIf24{w;^kN^Mx literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/Microsoft.Azure.PowerShell.Authenticators.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Microsoft.Azure.PowerShell.Authenticators.dll similarity index 76% rename from powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/Microsoft.Azure.PowerShell.Authenticators.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Microsoft.Azure.PowerShell.Authenticators.dll index fc31736f77569117749bd1f27e4f62ba36670ca0..5b85b90e39774b105598bb37c8ed91724e6ea6eb 100644 GIT binary patch delta 2261 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 b!o;&5Bb*K+gy|(pH#+`|32Di3&u{+$mT=?{ diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Microsoft.Bcl.AsyncInterfaces.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/Microsoft.Bcl.AsyncInterfaces.dll new file mode 100644 index 0000000000000000000000000000000000000000..0a784888baf18341861adeed296adc47cb8e153c GIT binary patch literal 20856 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 delta 3251 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 iq^omxm8lvdyZ6!8uVmM2y8i*}vNhU_)mSsO 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 IXGb{$00BiQzyJUM literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Net.Http.WinHttpHandler.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Net.Http.WinHttpHandler.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Net.Http.WinHttpHandler.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Net.Http.WinHttpHandler.dll diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Numerics.Vectors.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Numerics.Vectors.dll new file mode 100644 index 0000000000000000000000000000000000000000..a808165accf4b28833d22169931d4c879defd96d GIT binary patch literal 163712 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�q8Bzlv}ROx-}ptnKD&8tasR$2=E({1 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 literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Private.ServiceModel.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Private.ServiceModel.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Private.ServiceModel.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Private.ServiceModel.dll diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Reflection.DispatchProxy.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Reflection.DispatchProxy.dll similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/PreloadAssemblies/System.Reflection.DispatchProxy.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Reflection.DispatchProxy.dll diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.4.0.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.4.0.dll new file mode 100644 index 0000000000000000000000000000000000000000..0b45903440b92c890a99b27303bc189cecdd09f1 GIT binary patch literal 22160 zcmeHv2|ShC*YI-&^B9qg$1LM>j=3W9P)G=gWH@9zI*z%*2~mp5OhpnZNg5QAP|{>5 zjWU#|C`1F|+s|>x?biL@_x-;6yWji!zNenG_gZ^=_FjAKwbx#UrBf<|fglJA-q~3Q zssbVM=+WR`gBXy^DRz|;y1;Tzyb5J;Puy;sPcSZsO!6kX1>ii~0s~1DoI4Rm4hh8h z1mcX=+u{O9o*k_=gaQzhstZVZ5XAn+ zl)s1JAc%QUPG*3cEy9&4#Bd70u{;2Pw8h^FFxrEIpsmVeqCd%l-UmHE2HytpgLl!R z2SEml(En1j2N_rJAbmqa3{bNq1PyXP5DSg^16boADCP(H+nCbH9?7=zg*)3byVdim zU!LAjBr^I=hrcuguhS+l@$$Js-$QXhf9bqkp-+>o59!OW3TP!d#!e`c4Oc%M%x)2| z-}A!grG1c~n=k&f>$jl(1IwaPJFcD)kdfsL=9%c)l=1z@>DhG=-?M}t2}WkNNL!3J zs4y5c8E?t@xMIcE`dz#*3Sy%74!s=(K|=BnLSvn$&G4Y;I)iKSJ-3!@>x zk+cVm0hP>=K^?!RgJGoSr?p5g0ny6*J`F`%k4Qmu&s^WkC1;=FP)B}u`TVJKt>Fh4`jW9uUUd- zWt2ze2VraELDSm&8OJQFK`{2TQRr}T1m%8DUo=;={2)7R+~?&48uPpIn|@R89Q{xA zZu+@iBp-S~9%0aPIK$lMf%%$2&5aeZ+U6cW!~BBAFh^U&&vJlkSpUcqXgbZncC7&l z8By>c@+wqK8CF(>Rq@&gg#q#hum?=8tm>@|5f08@Ekq4kCQ$92^3o@XS(yE9|LR#knFG7+6uK{=w zK8L}Jq%D4h01iPHQFA?Jgyg{rWrVD0Fa`<)@gp?YK!eX{@CywtK_RJ%G-ynNMAQ}( zBNRo0R2odC!4m)?t<1H7j7}_y8~TW1h43H_r~vzn;zX;1I1qaPlS8vY2qp!!;*f$F z&}y_Tz+cm`wE#my(+k*UuvV9f&*gMPdw?&Oqhmn;V}$e;Fn=(*j&v*<9Rj|SvVcW{ z8B3*Oap)w76UwJ!2hfMWh+d#$>F7*=H7{WK5D)Z%j+KHmK4^Ra%ZCIYc8R&3)u2lu zAqcmCRY0PU8XfBZY2uK@0#*UO-II>JL0^GnAqpLPkG>AcL2(P%ZD<9Qwve*}%-{(+ zHihnj6rh>~Y!Fg{9xh;`kP0+J$2c&fU@oTVm<*;1QiYa+sX#_v1~UleLU92bg)|`} zI;H~3X+w5&%m6bDt%5x1*k%k9N(Tz3V}Sr$10~b3-2l^v@(~P55LgRl$Pl{l2Mja~ z8KQrNTL1+O`O@fr9iJ;ZmuD`%xD-OcK*tu<^IxUhT)@$wE^UU z^l5Q(8r(pGn*ij4wgV^v`2ffW;UGa&Em|3}g)#x;g=$gCU{$;TP?81}ptm5dN`tE) zK9FY>ga^D2}|7|WiABsQm&xMVM z!5(CvAf&ZFCt4CIZk}!ww?C&Cl7b@0KHl3Xze)lh7r5xN=KE<)24m^5sKng&LWUN$ z$bk6!xCJgsT<`7+1_4@B|NK~P40iKg{3Y{rJ2$d7krMo$rb>BZV6dAPQQ6bq|EH|b zTnc1G3ZxICoBQH1o1Yɀ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 OyIXQg_#$)@0sTLk9O=pc literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.5.0.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Runtime.CompilerServices.Unsafe.4.0.5.0.dll new file mode 100644 index 0000000000000000000000000000000000000000..0c27a0e21c7ea37e109b34ae8fdb80d298890785 GIT binary patch literal 16760 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 z zJ{!$4*N^^~H;dooLd4x!px1|Iqu00bmQzt=v-zbjlB(=ryb!D~mn=9OHCd5wB z{JQ#g^<7$%eP&NdZ|WW!y|M51i0$K^zZv?AaF^eu=wCi-MLzn?to*>N;Zb8QZN4;q z2hBE(eQKBXvGJ2vJ5L;O<@&vmhxbqKnRbo)_Dl(1`^E^nuqfr;6?AUwm*nV@xDCXY zoqVNp2HVDUA+in@v<(>VoIQERu6Xq(rETe|58{^VoMJ`3L-wpZ_T=E3=lU+ZVZCC= zo-aKkt0oPzB#3~Lq%qIO+wE09(sbmSSC6kt9c+7?yz6?Tv}E4qcebnjJ*?JcZESk& z6wu^a{-vR-`j;h9y|-d+%FOV+>WP!DpT1gZc_ZYH(u$`{rUoHhQx9YF(zWSnex`$tPzu9Bn zr;YgaY=Pe7b=AvS2ANy-^j~bOaiDIQy6%>Wjc-=BeTvU{TxxMKxOq$F{i&f2QwWJl zF1UdtsS8kNYtOkvxh>i^#zGWM{~y^}Vf!YRB+bC8bL$Tiz|Wa{z`iq5Gm;^s$neS% zr$Zc4oYUz9ScD7VYEL-15pJXtaHdceL8AY5CndqZcLzA>4sdV>u;wQp2+F?dtuHY`w9;rYcu$>+cIko=P-QdXhT6**>hV zzTM+Zs-fq1`0k0new0be+LYdQn%6d9RC%}8{`(tUQ#SKcoF=R*OV+Wy>^blKgS#qP zS4ZWn4X}Ewb+F7J``~={mX8l?Vs%Y}qbyhF3LEtY>rE8zXZo{0Sa;6 zA@w=ibj&@=fE5YT@ArwnY!)~;?C7p&kKVM_i@9-jS1lf7#_Npm&))GK-K*J*OA>A! z>bm1V&nuCEkKM|3o>&Cb81D6*(=F9IJ2SXCNWuB*&TD`=XLG$CQTUD5B+%SY8_TUx$+!8>9( zyZ>xYmyo)9Q+-R0ss+_wS?gmbUht0pegY$=zd?NBf~A8)9Exsko8JBI%HgjUZmaPx z<1W6`cy0Qx8gh5|0^H#fLRVQ$cFOCD(cvJ56#U;0ol%dD3SDrzrinU4II`fL<%7Hk z4RX8Jp_9!N6FMDxzY;+M7w{)HC$t@av*!5h>!LLL-qXtCtcw;Ujzlb3!;}u5hzKbQ zE(W*~YDS~8? zU8XRD#}?)!XNs8VVjkhy(Ev_3n%Fap6@nHCR3L~;g^6+?@J0rw$WR!00hWfXm<;1@ zHdM;{roAd&ySOnT$B23Px;V{znZ`oBd sycgzO%F&!t$4OxJAN>A^@FH)@mxCV7 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 literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Threading.Tasks.Extensions.4.3.1.0.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Threading.Tasks.Extensions.4.3.1.0.dll new file mode 100644 index 0000000000000000000000000000000000000000..ff691490b4a36b250a2efe4e037f671f0cbbf055 GIT binary patch literal 14712 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 literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Xml.ReaderWriter.dll b/powershell/resources/modules/Az.Accounts/1.8.1/PreloadAssemblies/System.Xml.ReaderWriter.dll new file mode 100644 index 0000000000000000000000000000000000000000..022e63a21a86003cb34d9e4082ad1816c5eedbc0 GIT binary patch literal 606592 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

Ar7)s*Rwm=cG4?*cvUjpP9AnetOn;gMJYDH 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

{)UZ8%zSENXt}>>AelVY(_Gi@Q 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�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 EKMpiCU;qFB literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/StartupScripts/AzError.ps1 b/powershell/resources/modules/Az.Accounts/1.8.1/StartupScripts/AzError.ps1 similarity index 64% rename from powershell/resources/modules/Az.Accounts/1.7.4/StartupScripts/AzError.ps1 rename to powershell/resources/modules/Az.Accounts/1.8.1/StartupScripts/AzError.ps1 index d918db8d202..e5247a5cf49 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/StartupScripts/AzError.ps1 +++ b/powershell/resources/modules/Az.Accounts/1.8.1/StartupScripts/AzError.ps1 @@ -63,42 +63,42 @@ if (Get-Module AzureRM.profile -ErrorAction Ignore) Update-TypeData -AppendPath (Join-Path (Get-Item $PSScriptRoot).Parent.FullName Accounts.types.ps1xml) -ErrorAction Ignore # SIG # Begin signature block -# MIIjhgYJKoZIhvcNAQcCoIIjdzCCI3MCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# MIIjgwYJKoZIhvcNAQcCoIIjdDCCI3ACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDT3s8rOGw0kP8l -# AbYXJ7G9hr2fOKBRtW5xO6fWVEOZvqCCDYEwggX/MIID56ADAgECAhMzAAABUZ6N -# j0Bxow5BAAAAAAFRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# AbYXJ7G9hr2fOKBRtW5xO6fWVEOZvqCCDYEwggX/MIID56ADAgECAhMzAAABh3IX +# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p -# bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ2WhcNMjAwNTAyMjEzNzQ2WjB0MQsw +# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -# AQCVWsaGaUcdNB7xVcNmdfZiVBhYFGcn8KMqxgNIvOZWNH9JYQLuhHhmJ5RWISy1 -# oey3zTuxqLbkHAdmbeU8NFMo49Pv71MgIS9IG/EtqwOH7upan+lIq6NOcw5fO6Os -# +12R0Q28MzGn+3y7F2mKDnopVu0sEufy453gxz16M8bAw4+QXuv7+fR9WzRJ2CpU -# 62wQKYiFQMfew6Vh5fuPoXloN3k6+Qlz7zgcT4YRmxzx7jMVpP/uvK6sZcBxQ3Wg -# B/WkyXHgxaY19IAzLq2QiPiX2YryiR5EsYBq35BP7U15DlZtpSs2wIYTkkDBxhPJ -# IDJgowZu5GyhHdqrst3OjkSRAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE -# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUV4Iarkq57esagu6FUBb270Zijc8w +# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB +# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH +# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d +# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ +# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV +# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 -# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU0MTM1MB8GA1UdIwQYMBaAFEhu +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx -# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAWg+A -# rS4Anq7KrogslIQnoMHSXUPr/RqOIhJX+32ObuY3MFvdlRElbSsSJxrRy/OCCZdS -# se+f2AqQ+F/2aYwBDmUQbeMB8n0pYLZnOPifqe78RBH2fVZsvXxyfizbHubWWoUf -# NW/FJlZlLXwJmF3BoL8E2p09K3hagwz/otcKtQ1+Q4+DaOYXWleqJrJUsnHs9UiL -# crVF0leL/Q1V5bshob2OTlZq0qzSdrMDLWdhyrUOxnZ+ojZ7UdTY4VnCuogbZ9Zs -# 9syJbg7ZUS9SVgYkowRsWv5jV4lbqTD+tG4FzhOwcRQwdb6A8zp2Nnd+s7VdCuYF -# sGgI41ucD8oxVfcAMjF9YX5N2s4mltkqnUe3/htVrnxKKDAwSYliaux2L7gKw+bD -# 1kEZ/5ozLRnJ3jjDkomTrPctokY/KaZ1qub0NUnmOKH+3xUK/plWJK8BOQYuU7gK -# YH7Yy9WSKNlP7pKj6i417+3Na/frInjnBkKRCJ/eYTvBH+s5guezpfQWtU4bNo/j -# 8Qw2vpTQ9w7flhH78Rmwd319+YTmhv7TcxDbWlyteaj4RK2wk3pY1oSz2JPE5PNu -# Nmd9Gmf6oePZgy7Ii9JLLq8SnULV7b+IP0UXRY9q+GdRjM2AEX6msZvvPCIoG0aY -# HQu9wZsKEK2jqvWi8/xdeeeSI9FN6K1w4oVQM4Mwggd6MIIFYqADAgECAgphDpDS +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy +# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K +# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV +# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr +# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx +# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe +# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g +# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf +# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI +# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 +# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea +# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 @@ -138,55 +138,55 @@ Update-TypeData -AppendPath (Join-Path (Get-Item $PSScriptRoot).Parent.FullName # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I -# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWzCCFVcCAQEwgZUwfjELMAkG +# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWDCCFVQCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z -# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAVGejY9AcaMOQQAAAAABUTAN +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgpH7D8Not # WnytrY9dBBVdkjoPJbp/Jb5/OaJtNH+9PHMwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN -# BgkqhkiG9w0BAQEFAASCAQAE1cwm1ioQxwice65esyxlxW83keTkgy5ONhCIoUaZ -# GCvDQJi/3f3zn7+N3geXu1ZA7Gvmh+vMrbMw+hyhjsnEIABJDkO/fvtZLyqkPkEa -# JNW+CXnQuKqcUdXyJ1oTFN/S/aTKjvuAN2XNzshSuZ/4k3RW5wRUGkDnJM5OZYDi -# uSP/MtUNkY9Q0U0FNH+UUeN+OKuFQdmbC8nwLtp6gp1a1paMaYlY81BgbHXql7Jx -# TL23YtScbuwF9893GbPyUSiCFEXXjVNXlH7E8N1O2I2adD/yyAYUhYuVkIM7oLjt -# YiFTA+px68tHes4mXosKOoLk96fFGXm/Oj71zZh4FgVhoYIS5TCCEuEGCisGAQQB -# gjcDAwExghLRMIISzQYJKoZIhvcNAQcCoIISvjCCEroCAQMxDzANBglghkgBZQME +# BgkqhkiG9w0BAQEFAASCAQADqescXpA8SbdcE09Q27Fqhfhi/1FP4cLLDPtjqGIT +# q/R5g7OuG9YU8K6vSUgqCz3/6UOwvJhY14BUzh22T8MequctOPiK7YWWOyVHTe7R +# d1osPatNkFGbslnRh5Dj/ll2FEHXx2YWPMmmFbxwKEB5zaaQaSWTYQMdq94Cdw1S +# Ev2LfqQxqykqKb1hq3hU1Mn/NOL8PJ4RqUpsStLYTy4MYLrK3+amSuOOAcmDGV5h +# zcdni4PVGLx29Oafo+XOIaQSdEucx9yge6i/HSFLK3lFIQqq63g+AswvICCPqME8 +# 1cAdAS/MOl8P10fokuB0CaZLO0Et9ojmsomFQoJjEjlToYIS4jCCEt4GCisGAQQB +# gjcDAwExghLOMIISygYJKoZIhvcNAQcCoIISuzCCErcCAQMxDzANBglghkgBZQME # AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB -# MDEwDQYJYIZIAWUDBAIBBQAEIIN11rIOXqQOCZZVz1EXistFeGNo+HEaozLAh0Kj -# 4TfzAgZee5sWdXIYEzIwMjAwMzI3MTE0NzIzLjE5OFowBIACAfSggdCkgc0wgcox -# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt -# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p -# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg -# RVNOOjEyQkMtRTNBRS03NEVCMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt -# cCBTZXJ2aWNloIIOPDCCBPEwggPZoAMCAQICEzMAAAEh97GBmyNE1wwAAAAAASEw +# MDEwDQYJYIZIAWUDBAIBBQAEIJdKskEWgQvU28avEVv72vBaVdFCKmQg/2KtdodK +# DatLAgZerKV+QvIYEzIwMjAwNTI4MDcxMjI4LjYwMlowBIACAfSggdCkgc0wgcox +# CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQg +# SXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg +# RVNOOkZGMDYtNEJDMy1COURBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt +# cCBTZXJ2aWNloIIOOTCCBPEwggPZoAMCAQICEzMAAAEUNSdF6rbIbE8AAAAAARQw # DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN -# MTkxMTEzMjE0MDQyWhcNMjEwMjExMjE0MDQyWjCByjELMAkGA1UEBhMCVVMxEzAR -# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p -# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg -# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046MTJCQy1FM0FFLTc0 -# RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G -# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQCHhpfx2GygASmkk36b/lhYA4pR/U -# y13RRupY6dzUpVeHJ9RORDtLhG+AnEeWrJcXj2K1tN0YfdJIqIIFwRwuPlqYRIvM -# GWSoa8g9OfMMoZPZhm06limLuJ+X4QlVHgyJ0Kh2mEB+Tp55jTf5OHhWYdGEnyCX -# GMJcj5MkC9UB0uuudHy+hu5HwvW1oXGcBcQEazrLtzG2t4lm6jwoxYjaDF9/0W4C -# HqapxD/8oPEcGCjnrNmcMc0Xt9aHdngTKIV/TL8UOs5pYTL+X9NaYDO6FFgASvfW -# vkrP42zoxE36pBhAWax8UhT67Km4+2Xrz+FN9RMukAOt+Lg1lKsGo2fHAgMBAAGj -# ggEbMIIBFzAdBgNVHQ4EFgQUgm2ixcxt3F/nuAwdE6nddtJe9BwwHwYDVR0jBBgw +# MTkxMDIzMjMxOTM3WhcNMjEwMTIxMjMxOTM3WjCByjELMAkGA1UEBhMCVVMxCzAJ +# BgNVBAgTAldBMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg +# Q29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlv +# bnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046RkYwNi00QkMzLUI5 +# REExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G +# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdvi0k88S1dkCr0Rb9Vgwts1CaVvWj +# i4j8Z6oJteo97xmiVPQbsXEbI7B8SEULpdsTxnLpWlk0lfGayBLb6mqwYyqS+e1i +# Skkl6pOdFuh00sfjHmOGhKhww2Tyx4NpoHBnAc/qbL4YATCnVrywYDOzs27m67Mv +# lKLiL9KHovfG1r7FHzyp1tbKQhctJWk8QEwSPUZGZt5MDTpd1Dh1z5zVQ2gz2A5I +# TBvVMWOoNY3L6co/9NVg4FoGrU9CT45rbX8d2x+DRXLSluVNn5CYse/fEhRVrZO6 +# UiMKYMfTFsNWk5gf/0Bfr5IMCpfKdAltdzcMjqG2+OfDwURGNJmbfIz/AgMBAAGj +# ggEbMIIBFzAdBgNVHQ4EFgQUUFSPcOb+hJN3LEanWWXcI4uJPAIwHwYDVR0jBBgw # FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov # L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB # XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx # MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN -# BgkqhkiG9w0BAQsFAAOCAQEAmchnoJ9VlIo1/w0OQTqq3GJb4BtOtNb3fIW1JlU5 -# x80+QOP2JCzR+wHy+eha4OfeSbrBaI4+XKVv7ZWbX9DBYX2NJjpTMgEw1H80Fhyq -# ghJPMXp/mQbhkb6UpCQ4KldVlsvA1e18P7xft6Y7miM+ZYm+GIZztMkQizn0hAGV -# MnZ6hWDIA8Fa/1ZwxHMiHlzAYPA7JYpvVnfpnYJIfx0mue9BI40SsQWNiTrQ7tTI -# qd9M5IlPZ/Gy7ApXDTJWrw+qYDjL5ylN+v6uGsC+FXOfAzS4B1xj3KDpz/DRao82 -# W4Gb5ILAKBWsvbi+M7l+TjPguE++tEXAcEJYwDsW+bBiTzCCBnEwggRZoAMCAQIC +# BgkqhkiG9w0BAQsFAAOCAQEAGSKMNfc4B8frM9Abi+4YqtynPH8Q8GppZluhR0AH +# 3mPEUPfiKWGM4nxWqr9VgJIFmgCh5hm/ssthGNHpnwVDWHe387yhXMIFFafhZJqf +# FnOk02md5bK6sNVQTdgq1pW/E7lEIaWFTE+O8WkNYg+hZEunA5G+zfam+dO1gE0g +# eM303kGkS5PsbGRdnhqxddE+0S/+qhgC6d2Nvu0NYU3zc9WF5wp7esRcYCCJz+OD +# TrPecbLtawY0u7EwelI+eUx76jFg8+Er7x+USdAPDhHeGLItI0nDf9zyxFrzvChq +# aNnbbHFK8kkCqVZb+570CBJTP6HPUblA/QN8rqhnplTnGjCCBnEwggRZoAMCAQIC # CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp @@ -221,36 +221,36 @@ Update-TypeData -AppendPath (Join-Path (Get-Item $PSScriptRoot).Parent.FullName # gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn # QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp # 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT -# X4/edIhJEqGCAs4wggI3AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG -# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj -# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP -# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjoxMkJDLUUzQUUtNzRF -# QjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG -# BSsOAwIaAxUAr8ajO2jqA+vCGdK+EdBXUKpju2mggYMwgYCkfjB8MQswCQYDVQQG +# X4/edIhJEqGCAsswggI0AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzELMAkG +# A1UECBMCV0ExEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD +# b3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9u +# cyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGRjA2LTRCQzMtQjlE +# QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG +# BSsOAwIaAxUA4ATkl0QTu3uFAmVR+pqOPC6L4GeggYMwgYCkfjB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg -# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOIoE88wIhgPMjAy -# MDAzMjcxMzU1MjdaGA8yMDIwMDMyODEzNTUyN1owdzA9BgorBgEEAYRZCgQBMS8w -# LTAKAgUA4igTzwIBADAKAgEAAgIgpAIB/zAHAgEAAgIRtjAKAgUA4illTwIBADA2 -# BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIB -# AAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEwDM0BvS/L/8WhwXUcbZD4T8HogirGW -# gMbeL1sVy8SSaQ0jJ98GR3litOWb9x5U8+7WJvkzfCYBcH4wIVf7xfvkehRraPhL -# pDi0TuNHylq4bXv0UTscIdCibCsALoCQVs67tCW26kwktOQZYxTaCwuKrprBsGNw -# mtdGMzhiBGMCMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m -# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB -# IDIwMTACEzMAAAEh97GBmyNE1wwAAAAAASEwDQYJYIZIAWUDBAIBBQCgggFKMBoG -# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgDuo5ZMDp -# ycrQ25hJU7cStUmeC47nc4hxfxGdTytZZIUwgfoGCyqGSIb3DQEJEAIvMYHqMIHn -# MIHkMIG9BCD+EWyTV+m7ADABlfBFNTu+ajQt8d5kp47taXho+rTnYDCBmDCBgKR+ -# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS -# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT -# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABIfexgZsjRNcMAAAA -# AAEhMCIEIMJ3k4TwisiFyHnxd7/E7rDYLUGxwbV5EcAiEGPpNcu5MA0GCSqGSIb3 -# DQEBCwUABIIBAG2s0G4PzdQiMBS6okAQ6P+nUWqbFWD2melO6e03xrA41OYX88Bp -# 6uXk8LkXbvbORBBaIjYAwHwQ99rrCD8KTYRFRYdai5nl/t17rCoOVOurvp8haDE0 -# icsSi97F2dAaFbHsd7mI9AyGsnFtE6rBQa2mjCkSRqUkI3zPYk8EYyAazjdoZUQL -# Q3xEeT2nYARLzO4mT6tTNTN4eocFqluCVzNocDRdP5ASrzbDCFhImOagjqr3IN53 -# xGZogPpPa2EfwP72K+H9DkdPSJlnFGcqdpieYR5o13It6GJqkbPWyNDNJ0sk2Gze -# 3RkgJks7gu5R83yIZee525Ww36wDIudTOsQ= +# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOJ5angwIhgPMjAy +# MDA1MjgwNjM4NDhaGA8yMDIwMDUyOTA2Mzg0OFowdDA6BgorBgEEAYRZCgQBMSww +# KjAKAgUA4nlqeAIBADAHAgEAAgIK1TAHAgEAAgIRsTAKAgUA4nq7+AIBADA2Bgor +# BgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAID +# AYagMA0GCSqGSIb3DQEBBQUAA4GBABwFm0eXycqRfMePixoa1hhsN/r7IrH99F9W +# LXEMfVJUc4tT+cFj1sv0WlR2gTghoTnLpX2ygygH0NuXQZwa9nluP9+X1q9jvS+T +# C+kCGa29l4rd4gyLsgVbuK7cqj4Z5OsLSYPCIffa5vJ2kp3vejOGKvFQKWcIT0nU +# g5yTF0DnMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD +# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw +# MTACEzMAAAEUNSdF6rbIbE8AAAAAARQwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqG +# SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgQMgJLtxjbTsb +# 0Wn4LmdF4XpGfyeP4+d6F/0G5ZgNeGIwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHk +# MIG9BCBMEX+t50VMGPQQXEsFWfGBi8gat6mIS7jV9Lz5rc3rOjCBmDCBgKR+MHwx +# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt +# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABFDUnReq2yGxPAAAAAAEU +# MCIEIOmTT4+egSoVMVgSLJFNe+N6QV4tf0yXd8AdmQrqT1XAMA0GCSqGSIb3DQEB +# CwUABIIBAHs7bizq/5z/Q7AWwW33bnyRnqgCuo+3aYAogjpHLA3w/DWhDTDhBSxj +# vpPUySpnz73u9jR54vmLNeaidHtO+KEhxqpcPzEikHn36DsOeO70qdaG39UCHN1V +# dP+uDTuqU3h2S7Fr6iSgvDTI9hmzz/jIt3YuCan/NRB/7yfjd+PWpCndeeEkUXLS +# UqXYne23+XdN7J3x/7yHWug2LAICxNCo0aqW+lJ5zqptCFwJHoSonw3oEibSnb/9 +# zz9d6DtJW4d5MTId+6PoHRm8V9sKT62j5tl9u9c2oJqx7LqgXd7iZY5xn9fyOrYO +# +IG7L+Tbxu8TWBrdPjDHM77QhIlqnj8= # SIG # End signature block diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/[Content_Types].xml b/powershell/resources/modules/Az.Accounts/1.8.1/[Content_Types].xml similarity index 100% rename from powershell/resources/modules/Az.Accounts/1.7.4/[Content_Types].xml rename to powershell/resources/modules/Az.Accounts/1.8.1/[Content_Types].xml diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/_rels/.rels b/powershell/resources/modules/Az.Accounts/1.8.1/_rels/.rels similarity index 66% rename from powershell/resources/modules/Az.Accounts/1.7.4/_rels/.rels rename to powershell/resources/modules/Az.Accounts/1.8.1/_rels/.rels index d61033548dc..432c371c6a8 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/_rels/.rels +++ b/powershell/resources/modules/Az.Accounts/1.8.1/_rels/.rels @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/package/services/metadata/core-properties/14a2e5dcca424832934ab543719a1374.psmdcp b/powershell/resources/modules/Az.Accounts/1.8.1/package/services/metadata/core-properties/b4e383786e734eb49545960a9feff173.psmdcp similarity index 99% rename from powershell/resources/modules/Az.Accounts/1.7.4/package/services/metadata/core-properties/14a2e5dcca424832934ab543719a1374.psmdcp rename to powershell/resources/modules/Az.Accounts/1.8.1/package/services/metadata/core-properties/b4e383786e734eb49545960a9feff173.psmdcp index 05abc90cf66..550e773818d 100644 --- a/powershell/resources/modules/Az.Accounts/1.7.4/package/services/metadata/core-properties/14a2e5dcca424832934ab543719a1374.psmdcp +++ b/powershell/resources/modules/Az.Accounts/1.8.1/package/services/metadata/core-properties/b4e383786e734eb49545960a9feff173.psmdcp @@ -5,7 +5,7 @@ For more information on account credential management, please visit the following: https://docs.microsoft.com/powershell/azure/authenticate-azureps Az.Accounts - 1.7.4 + 1.8.1 Azure ResourceManager ARM Accounts Authentication Environment Subscription PSModule PSIncludes_Cmdlet PSCmdlet_Disable-AzDataCollection PSCmdlet_Disable-AzContextAutosave PSCmdlet_Enable-AzDataCollection PSCmdlet_Enable-AzContextAutosave PSCmdlet_Remove-AzEnvironment PSCmdlet_Get-AzEnvironment PSCmdlet_Set-AzEnvironment PSCmdlet_Add-AzEnvironment PSCmdlet_Get-AzSubscription PSCmdlet_Connect-AzAccount PSCmdlet_Get-AzContext PSCmdlet_Set-AzContext PSCmdlet_Import-AzContext PSCmdlet_Save-AzContext PSCmdlet_Get-AzTenant PSCmdlet_Send-Feedback PSCmdlet_Resolve-AzError PSCmdlet_Select-AzContext PSCmdlet_Rename-AzContext PSCmdlet_Remove-AzContext PSCmdlet_Clear-AzContext PSCmdlet_Disconnect-AzAccount PSCmdlet_Get-AzContextAutosaveSetting PSCmdlet_Set-AzDefault PSCmdlet_Get-AzDefault PSCmdlet_Clear-AzDefault PSCmdlet_Register-AzModule PSCmdlet_Enable-AzureRmAlias PSCmdlet_Disable-AzureRmAlias PSCmdlet_Uninstall-AzureRm PSCmdlet_Get-AzProfile PSCmdlet_Select-AzProfile PSCommand_Disable-AzDataCollection PSCommand_Disable-AzContextAutosave PSCommand_Enable-AzDataCollection PSCommand_Enable-AzContextAutosave PSCommand_Remove-AzEnvironment PSCommand_Get-AzEnvironment PSCommand_Set-AzEnvironment PSCommand_Add-AzEnvironment PSCommand_Get-AzSubscription PSCommand_Connect-AzAccount PSCommand_Get-AzContext PSCommand_Set-AzContext PSCommand_Import-AzContext PSCommand_Save-AzContext PSCommand_Get-AzTenant PSCommand_Send-Feedback PSCommand_Resolve-AzError PSCommand_Select-AzContext PSCommand_Rename-AzContext PSCommand_Remove-AzContext PSCommand_Clear-AzContext PSCommand_Disconnect-AzAccount PSCommand_Get-AzContextAutosaveSetting PSCommand_Set-AzDefault PSCommand_Get-AzDefault PSCommand_Clear-AzDefault PSCommand_Register-AzModule PSCommand_Enable-AzureRmAlias PSCommand_Disable-AzureRmAlias PSCommand_Uninstall-AzureRm PSCommand_Get-AzProfile PSCommand_Select-AzProfile PSCommand_Add-AzAccount PSCommand_Login-AzAccount PSCommand_Remove-AzAccount PSCommand_Logout-AzAccount PSCommand_Select-AzSubscription PSCommand_Resolve-Error PSCommand_Save-AzProfile PSCommand_Get-AzDomain NuGet, Version=3.4.4.1321, Culture=neutral, PublicKeyToken=31bf3856ad364e35;Microsoft Windows NT 6.2.9200.0;.NET Framework 4.5 \ No newline at end of file diff --git a/powershell/resources/runtime/csharp/pipeline/ISendAsync.cs b/powershell/resources/runtime/csharp/pipeline/ISendAsync.cs index 98696e712e6..fb0cc28b940 100644 --- a/powershell/resources/runtime/csharp/pipeline/ISendAsync.cs +++ b/powershell/resources/runtime/csharp/pipeline/ISendAsync.cs @@ -252,12 +252,19 @@ internal static HttpRequestMessage Clone(this HttpRequestMessage original, Syste { clone.Properties.Add(prop); } - + foreach (KeyValuePair> header in original.Headers) - { + { + /* + **temporarily skip cloning telemetry related headers** clone.Headers.TryAddWithoutValidation(header.Key, header.Value); + */ + if (!"x-ms-unique-id".Equals(header.Key) && !"x-ms-client-request-id".Equals(header.Key) && !"CommandName".Equals(header.Key) && !"FullCommandName".Equals(header.Key) && !"ParameterSetName".Equals(header.Key) && !"User-Agent".Equals(header.Key)) + { + clone.Headers.TryAddWithoutValidation(header.Key, header.Value); + } } - + return clone; } @@ -286,4 +293,4 @@ internal static async Task CloneWithContent(this HttpRequest return clone; } } -} \ No newline at end of file +} diff --git a/tests-upgrade/AutoRestUpgradeTest.ps1 b/tests-upgrade/AutoRestUpgradeTest.ps1 index 66c2e796052..3b5f512175d 100644 --- a/tests-upgrade/AutoRestUpgradeTest.ps1 +++ b/tests-upgrade/AutoRestUpgradeTest.ps1 @@ -83,7 +83,7 @@ function GenerateCode() { #generate source code Write-Host -ForegroundColor Green 'M3' - $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.386 --output-folder:.\generate\m3 --Debug | Out-string + $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.400 --output-folder:.\generate\m3 --Debug | Out-string #generate target code Write-Host -ForegroundColor Green 'M4' $GenerateTargetResult = autorest-beta --use:..\..\ --output-folder:.\generate\m4 --Debug | Out-string @@ -94,7 +94,7 @@ function GenerateCode() }elseif($SourceVersion) { Write-Host -ForegroundColor Green 'M3' - $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.386 --output-folder:.\generate\m3 --Debug | Out-string + $GenerateSourceResult = autorest-beta --use:@autorest/powershell@2.1.400 --output-folder:.\generate\m3 --Debug | Out-string if(!$GenerateSourceResult.Contains('Generation Complete')) { $GenerateResult = $false From b8406cd37c511b9d4664d50750c7aabf3ec8666b Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Tue, 13 Oct 2020 13:34:08 +0800 Subject: [PATCH 58/61] Upgrade rush and pnpm (#697) --- rush.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rush.json b/rush.json index 95df31762d2..a0f9d82a4b3 100644 --- a/rush.json +++ b/rush.json @@ -15,7 +15,7 @@ * path segment in the "$schema" field for all your Rush config files. This will ensure * correct error-underlining and tab-completion for editors such as VS Code. */ - "rushVersion": "5.12.0", + "rushVersion": "5.34.3", /** * The next field selects which package manager should be installed and determines its version. * Rush installs its own local copy of the package manager to ensure that your build process @@ -24,7 +24,7 @@ * Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation * for details about these alternatives. */ - "pnpmVersion": "2.15.1", + "pnpmVersion": "5.9.0", /** * Options that are only used when the PNPM package manager is selected */ @@ -101,4 +101,4 @@ "shouldPublish": true } ] -} \ No newline at end of file +} From 8205373a3ca17214b14378383db309ca20f54bf3 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 16 Oct 2020 12:51:23 +0800 Subject: [PATCH 59/61] Clean m3 related steps from the pipeline (#699) * Clean m3 related steps from the pipeline * clean m3 plugins and update related tests accordingly * clean code used by m3 generator * Remove the prefix New * Remove New from types --- common/config/rush/pnpm-lock.yaml | 3152 +++++++++++++++++ common/scripts/install-run-rush.js | 27 +- common/scripts/install-run.js | 349 +- powershell/autorest-configuration.md | 52 +- powershell/cmdlets/class.ts | 1232 +------ powershell/cmdlets/namespace.ts | 30 +- powershell/enums/namespace.ts | 111 +- powershell/generators/csproj.ts | 3 +- powershell/generators/gitattributes.ts | 4 +- powershell/generators/gitignore.ts | 4 +- powershell/generators/nuspec.ts | 4 +- powershell/generators/psm1.custom.ts | 4 +- powershell/generators/psm1.internal.ts | 4 +- powershell/generators/psm1.ts | 4 +- powershell/generators/readme.ts | 4 +- powershell/generators/script-cmdlet.ts | 5 +- powershell/internal/project.ts | 217 +- powershell/internal/state.ts | 31 +- powershell/llcsharp/enums/enum.ts | 171 +- powershell/llcsharp/enums/json-serializer.ts | 48 - powershell/llcsharp/enums/namespace.ts | 4 +- powershell/llcsharp/exports.ts | 2 +- powershell/llcsharp/generator.ts | 30 +- powershell/llcsharp/model/interface.ts | 161 +- .../llcsharp/model/model-class-dictionary.ts | 110 +- powershell/llcsharp/model/model-class-json.ts | 224 +- .../llcsharp/model/model-class-serializer.ts | 199 +- powershell/llcsharp/model/model-class-xml.ts | 174 - powershell/llcsharp/model/model-class.ts | 515 +-- powershell/llcsharp/model/namespace.ts | 170 +- powershell/llcsharp/model/property.ts | 73 +- powershell/llcsharp/operation/api-class.ts | 57 +- powershell/llcsharp/operation/method.ts | 739 +--- powershell/llcsharp/operation/namespace.ts | 6 +- powershell/llcsharp/operation/parameter.ts | 148 +- powershell/llcsharp/project.ts | 85 +- powershell/llcsharp/schema/Uuid.ts | 19 +- powershell/llcsharp/schema/array.ts | 252 +- powershell/llcsharp/schema/binary.ts | 78 +- powershell/llcsharp/schema/boolean.ts | 21 +- powershell/llcsharp/schema/byte-array.ts | 106 +- powershell/llcsharp/schema/char.ts | 35 +- powershell/llcsharp/schema/date-time.ts | 184 +- powershell/llcsharp/schema/date.ts | 10 +- powershell/llcsharp/schema/duration.ts | 62 +- powershell/llcsharp/schema/enum.ts | 24 +- .../schema/extended-type-declaration.ts | 49 +- powershell/llcsharp/schema/integer.ts | 39 +- powershell/llcsharp/schema/object.ts | 166 +- powershell/llcsharp/schema/primitive.ts | 187 +- powershell/llcsharp/schema/schema-resolver.ts | 208 +- powershell/llcsharp/schema/string.ts | 194 +- powershell/main.ts | 21 +- powershell/models/model-extensions.ts | 244 +- powershell/module/module-class.ts | 285 +- powershell/module/module-namespace.ts | 23 +- powershell/plugins/add-azure-completers-v2.ts | 6 +- powershell/plugins/add-azure-completers.ts | 47 - powershell/plugins/create-commands-v2.ts | 7 +- powershell/plugins/create-commands.ts | 454 --- powershell/plugins/cs-namer-v2.ts | 13 +- powershell/plugins/cs-namer.ts | 245 -- powershell/plugins/llcsharp-v2.ts | 5 +- powershell/plugins/llcsharp.ts | 77 - powershell/plugins/modifiers-v2.ts | 7 +- powershell/plugins/modifiers.ts | 701 ---- .../plugin-create-inline-properties.ts | 6 +- powershell/plugins/plugin-tweak-m4-model.ts | 6 +- .../plugins/plugin-tweak-model-azure-v2.ts | 6 +- .../plugins/plugin-tweak-model-azure.ts | 175 - powershell/plugins/plugin-tweak-model.ts | 10 +- powershell/plugins/powershell-v2.ts | 7 +- powershell/plugins/powershell.ts | 82 - powershell/plugins/ps-namer-v2.ts | 6 +- powershell/plugins/ps-namer.ts | 201 -- powershell/test/noun-cleaning.ts | 2 +- powershell/test/operationId-inferring.ts | 3 +- powershell/test/test-service-name.ts | 2 +- powershell/utils/PwshModel.ts | 1 - powershell/utils/model-state.ts | 6 +- powershell/utils/schema.ts | 14 +- 81 files changed, 3731 insertions(+), 8718 deletions(-) create mode 100644 common/config/rush/pnpm-lock.yaml delete mode 100644 powershell/llcsharp/enums/json-serializer.ts delete mode 100644 powershell/llcsharp/model/model-class-xml.ts delete mode 100644 powershell/plugins/add-azure-completers.ts delete mode 100644 powershell/plugins/create-commands.ts delete mode 100644 powershell/plugins/cs-namer.ts delete mode 100644 powershell/plugins/llcsharp.ts delete mode 100644 powershell/plugins/modifiers.ts delete mode 100644 powershell/plugins/plugin-tweak-model-azure.ts delete mode 100644 powershell/plugins/powershell.ts delete mode 100644 powershell/plugins/ps-namer.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml new file mode 100644 index 00000000000..197ca8b039a --- /dev/null +++ b/common/config/rush/pnpm-lock.yaml @@ -0,0 +1,3152 @@ +dependencies: + '@autorest/autorest': 3.0.6187 + '@azure-tools/async-io': 3.0.252 + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/codegen-csharp': 3.0.262 + '@azure-tools/codemodel': 4.13.348 + '@azure-tools/codemodel-v3': 3.1.264 + '@azure-tools/linq': 3.1.261 + '@azure-tools/tasks': 3.0.252 + '@microsoft.azure/autorest.testserver': 2.9.9 + '@rush-temp/powershell': 'file:projects/powershell.tgz' + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': 2.0.0_b7c2671679a3bd4e1f52a3d3da16606f + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: 3.7.5 + xmlbuilder: 10.1.1 +lockfileVersion: 5.1 +packages: + /@autorest/autorest/3.0.6187: + dev: false + engines: + node: '>=10.13.0' + hasBin: true + requiresBuild: true + resolution: + integrity: sha512-BUTLfV6GufjgcSp0ysB1wdhMIG8RGQMiY4ZQnP76fHcR2KZW0QinnEAR99mMy7BVOdXiurWkNW7rilEJfKhXWg== + /@azure-tools/async-io/3.0.252: + dependencies: + '@azure-tools/tasks': 3.0.252 + proper-lockfile: 2.0.1 + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-RpoaEWGwpdp4FR9YKgnSkvwhdeR1gIzRFFOBotOyd3ow8FMfRIvMZ/eHar2iM3OXUnRKbHnv1M6oapdZah1JWw== + /@azure-tools/autorest-extension-base/3.1.266: + dependencies: + '@azure-tools/codegen': 2.5.290 + js-yaml: 3.13.1 + vscode-jsonrpc: 3.6.2 + dev: false + resolution: + integrity: sha512-3DdIcHWXwVaX1otoNS38xLIUhjcyy/7jWwDMulAfAQ0PXp6H98uoUxVVsjz42FFalH6mm0K5Wwn1kx0Izx0Nlg== + /@azure-tools/codegen-csharp/3.0.262: + dependencies: + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-hNEmbvlEY87AmmVoDRyYEZDG4iHwfYx6G9B7M8n0JvdwyOHn/gb4qUb1ULaPmbFWxMnVFzW070ab61/1VpYVog== + /@azure-tools/codegen/2.5.290: + dependencies: + '@azure-tools/async-io': 3.0.252 + '@azure-tools/linq': 3.1.261 + js-yaml: 3.13.1 + semver: 5.7.1 + dev: false + resolution: + integrity: sha512-D9TuBY9YE+CE/EpbMaB3oVJq1xp7koIAQGlFrRNTLPgKNMelqkWK8HLnYSk810HL0rJFQjJE/BLx5lQsOjMYRQ== + /@azure-tools/codemodel-v3/3.1.264: + dependencies: + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-Zh/as7gux7ifD3J7JUHwRW/e7DrG7rSJBpIyysGZEHbhErxsiPeLTZsS5pDpzwXD3CsEA2hDxrNSDFpVNXNqog== + /@azure-tools/codemodel/4.13.348: + dependencies: + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-/5tjloDiPLNdqBdNN1PHudqMQlgCb+8o6L/8Pd3nYHc20cnbg3y3c23N5xpsGqmwwhJhCRrrW2XKrJeP55i09Q== + /@azure-tools/linq/3.1.261: + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-SRYWE2SUYXBdqGoQYjBvvFtZKHLaYvL4HJwDKOp5PA0OCm5f3gLNVsXSwgzLzh4CiYjt0vsRiQy5AB4p7b8Ogg== + /@azure-tools/tasks/3.0.252: + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-VF63L3nKogeXoChEcDHPUr325JFTvSM1qhw5yZ/VMwSvC5zp2Ri7MPEixK/mni4cQJnFMuqDp+6M1vkPh8ZRRA== + /@babel/code-frame/7.10.4: + dependencies: + '@babel/highlight': 7.10.4 + dev: false + resolution: + integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + /@babel/helper-validator-identifier/7.10.4: + dev: false + resolution: + integrity: sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + /@babel/highlight/7.10.4: + dependencies: + '@babel/helper-validator-identifier': 7.10.4 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: false + resolution: + integrity: sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + /@microsoft.azure/autorest.testserver/2.9.9: + dependencies: + azure-storage: 2.10.3 + body-parser: 1.19.0 + busboy: 0.3.1 + chalk: 3.0.0 + cookie-parser: 1.4.5 + cors: 2.8.5 + debug: 3.2.6 + express: 4.17.1 + morgan: 1.10.0 + pug: 2.0.4 + request: 2.88.2 + request-promise-native: 1.0.9_request@2.88.2 + serve-favicon: 2.5.0 + socket.io: 2.3.0 + socket.io-client: 2.3.1 + underscore: 1.11.0 + wiremock: 2.25.0 + xml2js: 0.4.23 + dev: false + hasBin: true + resolution: + integrity: sha512-XPdWxb4jgSPmKKWgLjCHDEE9+Lc1QMbZZ2dJEd+RtdlATI1HOaE4j72keP2wmMF0acTWN85fngd5EFPCgN4CeA== + /@types/babel-types/7.0.9: + dev: false + resolution: + integrity: sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA== + /@types/babylon/6.16.5: + dependencies: + '@types/babel-types': 7.0.9 + dev: false + resolution: + integrity: sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w== + /@types/eslint-visitor-keys/1.0.0: + dev: false + resolution: + integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + /@types/js-yaml/3.12.1: + dev: false + resolution: + integrity: sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA== + /@types/json-schema/7.0.6: + dev: false + resolution: + integrity: sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + /@types/mocha/5.2.5: + dev: false + resolution: + integrity: sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww== + /@types/node/12.7.2: + dev: false + resolution: + integrity: sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== + /@types/xmlbuilder/0.0.34: + dev: false + resolution: + integrity: sha512-yVsHfYqJblSEg3DvUhGndpCZBZz2GiGVmqMa04fbGro2xzxRj85Q7MQ4os+MaXmKcpCDD42MXuxUWfoUKTuVdQ== + /@typescript-eslint/eslint-plugin/2.0.0_b7c2671679a3bd4e1f52a3d3da16606f: + dependencies: + '@typescript-eslint/experimental-utils': 2.0.0_eslint@6.2.2 + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + eslint-utils: 1.4.3 + functional-red-black-tree: 1.0.1 + regexpp: 2.0.1 + tsutils: 3.17.1_typescript@3.7.5 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + '@typescript-eslint/parser': ^2.0.0-alpha.0 + eslint: ^5.0.0 || ^6.0.0 + typescript: '*' + resolution: + integrity: sha512-Mo45nxTTELODdl7CgpZKJISvLb+Fu64OOO2ZFc2x8sYSnUpFrBUW3H+H/ZGYmEkfnL6VkdtOSxgdt+Av79j0sA== + /@typescript-eslint/experimental-utils/2.0.0_eslint@6.2.2: + dependencies: + '@types/json-schema': 7.0.6 + '@typescript-eslint/typescript-estree': 2.0.0 + eslint: 6.2.2 + eslint-scope: 4.0.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: '*' + resolution: + integrity: sha512-XGJG6GNBXIEx/mN4eTRypN/EUmsd0VhVGQ1AG+WTgdvjHl0G8vHhVBHrd/5oI6RRYBRnedNymSYWW1HAdivtmg== + /@typescript-eslint/parser/2.0.0_eslint@6.2.2: + dependencies: + '@types/eslint-visitor-keys': 1.0.0 + '@typescript-eslint/experimental-utils': 2.0.0_eslint@6.2.2 + '@typescript-eslint/typescript-estree': 2.0.0 + eslint: 6.2.2 + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 + resolution: + integrity: sha512-ibyMBMr0383ZKserIsp67+WnNVoM402HKkxqXGlxEZsXtnGGurbnY90pBO3e0nBUM7chEEOcxUhgw9aPq7fEBA== + /@typescript-eslint/typescript-estree/2.0.0: + dependencies: + lodash.unescape: 4.0.1 + semver: 6.3.0 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + resolution: + integrity: sha512-NXbmzA3vWrSgavymlzMWNecgNOuiMMp62MO3kI7awZRLRcsA1QrYWo6q08m++uuAGVbXH/prZi2y1AWuhSu63w== + /accepts/1.3.7: + dependencies: + mime-types: 2.1.27 + negotiator: 0.6.2 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + /acorn-globals/3.1.0: + dependencies: + acorn: 4.0.13 + dev: false + resolution: + integrity: sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= + /acorn-jsx/5.3.1_acorn@7.4.1: + dependencies: + acorn: 7.4.1 + dev: false + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + resolution: + integrity: sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + /acorn/3.3.0: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha1-ReN/s56No/JbruP/U2niu18iAXo= + /acorn/4.0.13: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + /acorn/7.4.1: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + /after/0.8.2: + dev: false + resolution: + integrity: sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + /ajv/6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.0 + dev: false + resolution: + integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + /align-text/0.1.4: + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= + /ansi-escapes/3.2.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + /ansi-regex/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + /ansi-regex/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + /ansi-regex/4.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + /ansi-styles/3.2.1: + dependencies: + color-convert: 1.9.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + /ansi-styles/4.3.0: + dependencies: + color-convert: 2.0.1 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + /argparse/1.0.10: + dependencies: + sprintf-js: 1.0.3 + dev: false + resolution: + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + /array-flatten/1.1.1: + dev: false + resolution: + integrity: sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + /arraybuffer.slice/0.0.7: + dev: false + resolution: + integrity: sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== + /asap/2.0.6: + dev: false + resolution: + integrity: sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + /asn1/0.2.4: + dependencies: + safer-buffer: 2.1.2 + dev: false + resolution: + integrity: sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + /assert-plus/1.0.0: + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + /astral-regex/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + /async-limiter/1.0.1: + dev: false + resolution: + integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + /asynckit/0.4.0: + dev: false + resolution: + integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k= + /aws-sign2/0.7.0: + dev: false + resolution: + integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + /aws4/1.10.1: + dev: false + resolution: + integrity: sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== + /azure-storage/2.10.3: + dependencies: + browserify-mime: 1.2.9 + extend: 3.0.2 + json-edm-parser: 0.1.2 + md5.js: 1.3.4 + readable-stream: 2.0.6 + request: 2.88.2 + underscore: 1.8.3 + uuid: 3.4.0 + validator: 9.4.1 + xml2js: 0.2.8 + xmlbuilder: 9.0.7 + dev: false + engines: + node: '>= 0.8.26' + resolution: + integrity: sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ== + /babel-runtime/6.26.0: + dependencies: + core-js: 2.6.11 + regenerator-runtime: 0.11.1 + dev: false + resolution: + integrity: sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + /babel-types/6.26.0: + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.17.20 + to-fast-properties: 1.0.3 + dev: false + resolution: + integrity: sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + /babylon/6.18.0: + dev: false + hasBin: true + resolution: + integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + /backo2/1.0.2: + dev: false + resolution: + integrity: sha1-MasayLEpNjRj41s+u2n038+6eUc= + /balanced-match/1.0.0: + dev: false + resolution: + integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + /base64-arraybuffer/0.1.4: + dev: false + engines: + node: '>= 0.6.0' + resolution: + integrity: sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + /base64-arraybuffer/0.1.5: + dev: false + engines: + node: '>= 0.6.0' + resolution: + integrity: sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + /base64id/2.0.0: + dev: false + engines: + node: ^4.5.0 || >= 5.9 + resolution: + integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + /basic-auth/2.0.1: + dependencies: + safe-buffer: 5.1.2 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + /bcrypt-pbkdf/1.0.2: + dependencies: + tweetnacl: 0.14.5 + dev: false + resolution: + integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + /better-assert/1.0.2: + dependencies: + callsite: 1.0.0 + dev: false + resolution: + integrity: sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + /blob/0.0.5: + dev: false + resolution: + integrity: sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== + /body-parser/1.19.0: + dependencies: + bytes: 3.1.0 + content-type: 1.0.4 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + /brace-expansion/1.1.11: + dependencies: + balanced-match: 1.0.0 + concat-map: 0.0.1 + dev: false + resolution: + integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + /browser-stdout/1.3.1: + dev: false + resolution: + integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + /browserify-mime/1.2.9: + dev: false + resolution: + integrity: sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8= + /buffer-from/1.1.1: + dev: false + resolution: + integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + /busboy/0.3.1: + dependencies: + dicer: 0.3.0 + dev: false + engines: + node: '>=4.5.0' + resolution: + integrity: sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw== + /bytes/3.1.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + /callsite/1.0.0: + dev: false + resolution: + integrity: sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + /callsites/3.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + /camelcase/1.2.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + /camelcase/4.1.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + /caseless/0.12.0: + dev: false + resolution: + integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + /center-align/0.1.3: + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qg0yYptu6XIgBBHL1EYckHvCt60= + /chalk/2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + /chalk/3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + /character-parser/2.2.0: + dependencies: + is-regex: 1.1.1 + dev: false + resolution: + integrity: sha1-x84o821LzZdE5f/CxfzeHHMmH8A= + /chardet/0.7.0: + dev: false + resolution: + integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + /clean-css/4.2.3: + dependencies: + source-map: 0.6.1 + dev: false + engines: + node: '>= 4.0' + resolution: + integrity: sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== + /cli-cursor/2.1.0: + dependencies: + restore-cursor: 2.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + /cli-width/2.2.1: + dev: false + resolution: + integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + /cliui/2.1.0: + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: false + resolution: + integrity: sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= + /cliui/4.1.0: + dependencies: + string-width: 2.1.1 + strip-ansi: 4.0.0 + wrap-ansi: 2.1.0 + dev: false + resolution: + integrity: sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + /code-point-at/1.1.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + /color-convert/1.9.3: + dependencies: + color-name: 1.1.3 + dev: false + resolution: + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + /color-convert/2.0.1: + dependencies: + color-name: 1.1.4 + dev: false + engines: + node: '>=7.0.0' + resolution: + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + /color-name/1.1.3: + dev: false + resolution: + integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + /color-name/1.1.4: + dev: false + resolution: + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + /combined-stream/1.0.8: + dependencies: + delayed-stream: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + /commander/2.15.1: + dev: false + resolution: + integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + /component-bind/1.0.0: + dev: false + resolution: + integrity: sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + /component-emitter/1.2.1: + dev: false + resolution: + integrity: sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + /component-emitter/1.3.0: + dev: false + resolution: + integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + /component-inherit/0.0.3: + dev: false + resolution: + integrity: sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + /concat-map/0.0.1: + dev: false + resolution: + integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + /constantinople/3.1.2: + dependencies: + '@types/babel-types': 7.0.9 + '@types/babylon': 6.16.5 + babel-types: 6.26.0 + babylon: 6.18.0 + dev: false + resolution: + integrity: sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw== + /content-disposition/0.5.3: + dependencies: + safe-buffer: 5.1.2 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + /content-type/1.0.4: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + /cookie-parser/1.4.5: + dependencies: + cookie: 0.4.0 + cookie-signature: 1.0.6 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw== + /cookie-signature/1.0.6: + dev: false + resolution: + integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + /cookie/0.3.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + /cookie/0.4.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + /core-js/2.6.11: + deprecated: 'core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.' + dev: false + requiresBuild: true + resolution: + integrity: sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + /core-util-is/1.0.2: + dev: false + resolution: + integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + /cors/2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + /cross-spawn/6.0.5: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: false + engines: + node: '>=4.8' + resolution: + integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + /dashdash/1.14.1: + dependencies: + assert-plus: 1.0.0 + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + /debug/2.6.9: + dependencies: + ms: 2.0.0 + dev: false + resolution: + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + /debug/3.1.0: + dependencies: + ms: 2.0.0 + dev: false + resolution: + integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + /debug/3.2.6: + dependencies: + ms: 2.1.2 + dev: false + resolution: + integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + /debug/4.1.1: + dependencies: + ms: 2.1.2 + dev: false + resolution: + integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + /debug/4.2.0: + dependencies: + ms: 2.1.2 + dev: false + engines: + node: '>=6.0' + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + resolution: + integrity: sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + /decamelize/1.2.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + /deep-is/0.1.3: + dev: false + resolution: + integrity: sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + /delayed-stream/1.0.0: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + /depd/1.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + /depd/2.0.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + /destroy/1.0.4: + dev: false + resolution: + integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + /dicer/0.3.0: + dependencies: + streamsearch: 0.1.2 + dev: false + engines: + node: '>=4.5.0' + resolution: + integrity: sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== + /diff/3.5.0: + dev: false + engines: + node: '>=0.3.1' + resolution: + integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + /doctrine/3.0.0: + dependencies: + esutils: 2.0.3 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + /doctypes/1.1.0: + dev: false + resolution: + integrity: sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= + /ecc-jsbn/0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: false + resolution: + integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + /ee-first/1.1.1: + dev: false + resolution: + integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + /emoji-regex/7.0.3: + dev: false + resolution: + integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + /encodeurl/1.0.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + /end-of-stream/1.4.4: + dependencies: + once: 1.4.0 + dev: false + resolution: + integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + /engine.io-client/3.4.4: + dependencies: + component-emitter: 1.3.0 + component-inherit: 0.0.3 + debug: 3.1.0 + engine.io-parser: 2.2.1 + has-cors: 1.1.0 + indexof: 0.0.1 + parseqs: 0.0.6 + parseuri: 0.0.6 + ws: 6.1.4 + xmlhttprequest-ssl: 1.5.5 + yeast: 0.1.2 + dev: false + resolution: + integrity: sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ== + /engine.io-parser/2.2.1: + dependencies: + after: 0.8.2 + arraybuffer.slice: 0.0.7 + base64-arraybuffer: 0.1.4 + blob: 0.0.5 + has-binary2: 1.0.3 + dev: false + resolution: + integrity: sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== + /engine.io/3.4.2: + dependencies: + accepts: 1.3.7 + base64id: 2.0.0 + cookie: 0.3.1 + debug: 4.1.1 + engine.io-parser: 2.2.1 + ws: 7.3.1 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg== + /escape-html/1.0.3: + dev: false + resolution: + integrity: sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + /escape-string-regexp/1.0.5: + dev: false + engines: + node: '>=0.8.0' + resolution: + integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + /eslint-scope/4.0.3: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + /eslint-scope/5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + /eslint-utils/1.4.3: + dependencies: + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + /eslint-visitor-keys/1.3.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + /eslint/6.2.2: + dependencies: + '@babel/code-frame': 7.10.4 + ajv: 6.12.6 + chalk: 2.4.2 + cross-spawn: 6.0.5 + debug: 4.2.0 + doctrine: 3.0.0 + eslint-scope: 5.1.1 + eslint-utils: 1.4.3 + eslint-visitor-keys: 1.3.0 + espree: 6.2.1 + esquery: 1.3.1 + esutils: 2.0.3 + file-entry-cache: 5.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.1 + globals: 11.12.0 + ignore: 4.0.6 + import-fresh: 3.2.1 + imurmurhash: 0.1.4 + inquirer: 6.5.2 + is-glob: 4.0.1 + js-yaml: 3.13.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.3.0 + lodash: 4.17.20 + minimatch: 3.0.4 + mkdirp: 0.5.5 + natural-compare: 1.4.0 + optionator: 0.8.3 + progress: 2.0.3 + regexpp: 2.0.1 + semver: 6.3.0 + strip-ansi: 5.2.0 + strip-json-comments: 3.1.1 + table: 5.4.6 + text-table: 0.2.0 + v8-compile-cache: 2.1.1 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + hasBin: true + resolution: + integrity: sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw== + /espree/6.2.1: + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.1_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== + /esprima/4.0.1: + dev: false + engines: + node: '>=4' + hasBin: true + resolution: + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + /esquery/1.3.1: + dependencies: + estraverse: 5.2.0 + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + /esrecurse/4.3.0: + dependencies: + estraverse: 5.2.0 + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + /estraverse/4.3.0: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + /estraverse/5.2.0: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + /esutils/2.0.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + /etag/1.8.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + /execa/1.0.0: + dependencies: + cross-spawn: 6.0.5 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.3 + strip-eof: 1.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + /express/4.17.1: + dependencies: + accepts: 1.3.7 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.4 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.6 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + dev: false + engines: + node: '>= 0.10.0' + resolution: + integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + /extend/3.0.2: + dev: false + resolution: + integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + /external-editor/3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + /extsprintf/1.3.0: + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + /fast-deep-equal/3.1.3: + dev: false + resolution: + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + /fast-json-stable-stringify/2.1.0: + dev: false + resolution: + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + /fast-levenshtein/2.0.6: + dev: false + resolution: + integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + /figures/2.0.0: + dependencies: + escape-string-regexp: 1.0.5 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + /file-entry-cache/5.0.1: + dependencies: + flat-cache: 2.0.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + /finalhandler/1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + /find-up/2.1.0: + dependencies: + locate-path: 2.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + /flat-cache/2.0.1: + dependencies: + flatted: 2.0.2 + rimraf: 2.6.3 + write: 1.0.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + /flatted/2.0.2: + dev: false + resolution: + integrity: sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + /forever-agent/0.6.1: + dev: false + resolution: + integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + /form-data/2.3.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.27 + dev: false + engines: + node: '>= 0.12' + resolution: + integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + /forwarded/0.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + /fresh/0.5.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + /fs.realpath/1.0.0: + dev: false + resolution: + integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + /functional-red-black-tree/1.0.1: + dev: false + resolution: + integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + /get-caller-file/1.0.3: + dev: false + resolution: + integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + /get-stream/4.1.0: + dependencies: + pump: 3.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + /getpass/0.1.7: + dependencies: + assert-plus: 1.0.0 + dev: false + resolution: + integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + /glob-parent/5.1.1: + dependencies: + is-glob: 4.0.1 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + /glob/7.1.2: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + resolution: + integrity: sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + /glob/7.1.6: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + resolution: + integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + /globals/11.12.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + /graceful-fs/4.2.4: + dev: false + resolution: + integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + /growl/1.10.5: + dev: false + engines: + node: '>=4.x' + resolution: + integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + /har-schema/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + /har-validator/5.1.5: + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + deprecated: this library is no longer supported + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + /has-binary2/1.0.3: + dependencies: + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== + /has-cors/1.1.0: + dev: false + resolution: + integrity: sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + /has-flag/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + /has-flag/4.0.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + /has-symbols/1.0.1: + dev: false + engines: + node: '>= 0.4' + resolution: + integrity: sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + /hash-base/3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.0 + safe-buffer: 5.2.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + /he/1.1.1: + dev: false + hasBin: true + resolution: + integrity: sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + /http-errors/1.7.2: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + /http-errors/1.7.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + /http-signature/1.2.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.1 + sshpk: 1.16.1 + dev: false + engines: + node: '>=0.8' + npm: '>=1.3.7' + resolution: + integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + /iconv-lite/0.4.24: + dependencies: + safer-buffer: 2.1.2 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + /ignore/4.0.6: + dev: false + engines: + node: '>= 4' + resolution: + integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + /import-fresh/3.2.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + /imurmurhash/0.1.4: + dev: false + engines: + node: '>=0.8.19' + resolution: + integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o= + /indexof/0.0.1: + dev: false + resolution: + integrity: sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + /inflight/1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + resolution: + integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + /inherits/2.0.3: + dev: false + resolution: + integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + /inherits/2.0.4: + dev: false + resolution: + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + /inquirer/6.5.2: + dependencies: + ansi-escapes: 3.2.0 + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-width: 2.2.1 + external-editor: 3.1.0 + figures: 2.0.0 + lodash: 4.17.20 + mute-stream: 0.0.7 + run-async: 2.4.1 + rxjs: 6.6.3 + string-width: 2.1.1 + strip-ansi: 5.2.0 + through: 2.3.8 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + /interpret/1.4.0: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + /invert-kv/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + /ipaddr.js/1.9.1: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + /is-buffer/1.1.6: + dev: false + resolution: + integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + /is-expression/3.0.0: + dependencies: + acorn: 4.0.13 + object-assign: 4.1.1 + dev: false + resolution: + integrity: sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8= + /is-extglob/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + /is-fullwidth-code-point/1.0.0: + dependencies: + number-is-nan: 1.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + /is-fullwidth-code-point/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + /is-glob/4.0.1: + dependencies: + is-extglob: 2.1.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + /is-promise/2.2.2: + dev: false + resolution: + integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + /is-regex/1.1.1: + dependencies: + has-symbols: 1.0.1 + dev: false + engines: + node: '>= 0.4' + resolution: + integrity: sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + /is-stream/1.1.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + /is-typedarray/1.0.0: + dev: false + resolution: + integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + /isarray/1.0.0: + dev: false + resolution: + integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + /isarray/2.0.1: + dev: false + resolution: + integrity: sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + /isexe/2.0.0: + dev: false + resolution: + integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + /isstream/0.1.2: + dev: false + resolution: + integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + /js-stringify/1.0.2: + dev: false + resolution: + integrity: sha1-Fzb939lyTyijaCrcYjCufk6Weds= + /js-tokens/4.0.0: + dev: false + resolution: + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + /js-yaml/3.13.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + hasBin: true + resolution: + integrity: sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + /jsbn/0.1.1: + dev: false + resolution: + integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + /json-edm-parser/0.1.2: + dependencies: + jsonparse: 1.2.0 + dev: false + resolution: + integrity: sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ= + /json-schema-traverse/0.4.1: + dev: false + resolution: + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + /json-schema/0.2.3: + dev: false + resolution: + integrity: sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + /json-stable-stringify-without-jsonify/1.0.1: + dev: false + resolution: + integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + /json-stringify-safe/5.0.1: + dev: false + resolution: + integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + /jsonparse/1.2.0: + dev: false + engines: + '0': node >= 0.2.0 + resolution: + integrity: sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70= + /jsprim/1.4.1: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.2.3 + verror: 1.10.0 + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + /jstransformer/1.0.0: + dependencies: + is-promise: 2.2.2 + promise: 7.3.1 + dev: false + resolution: + integrity: sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= + /kind-of/3.2.2: + dependencies: + is-buffer: 1.1.6 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + /lazy-cache/1.0.4: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-odePw6UEdMuAhF07O24dpJpEbo4= + /lcid/2.0.0: + dependencies: + invert-kv: 2.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + /levn/0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + /locate-path/2.0.0: + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + /lodash.unescape/4.0.1: + dev: false + resolution: + integrity: sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + /lodash/4.17.20: + dev: false + resolution: + integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + /longest/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + /map-age-cleaner/0.1.3: + dependencies: + p-defer: 1.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + /md5.js/1.3.4: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: false + resolution: + integrity: sha1-6b296UogpawYsENA/Fdk1bCdkB0= + /media-typer/0.3.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + /mem/4.3.0: + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 2.1.0 + p-is-promise: 2.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + /merge-descriptors/1.0.1: + dev: false + resolution: + integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + /methods/1.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + /mime-db/1.44.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + /mime-types/2.1.27: + dependencies: + mime-db: 1.44.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + /mime/1.6.0: + dev: false + engines: + node: '>=4' + hasBin: true + resolution: + integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + /mimic-fn/1.2.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + /mimic-fn/2.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + /minimatch/3.0.4: + dependencies: + brace-expansion: 1.1.11 + dev: false + resolution: + integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + /minimist/0.0.8: + dev: false + resolution: + integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + /minimist/1.2.5: + dev: false + resolution: + integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + /mkdirp/0.5.1: + dependencies: + minimist: 0.0.8 + deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) + dev: false + hasBin: true + resolution: + integrity: sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + /mkdirp/0.5.5: + dependencies: + minimist: 1.2.5 + dev: false + hasBin: true + resolution: + integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + /mocha-typescript/1.1.17: + dependencies: + '@types/mocha': 5.2.5 + chalk: 2.4.2 + cross-spawn: 6.0.5 + yargs: 11.1.1 + deprecated: 'mocha-typescript has been deprecated, use @testdeck/mocha instead' + dev: false + hasBin: true + resolution: + integrity: sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA== + /mocha/5.2.0: + dependencies: + browser-stdout: 1.3.1 + commander: 2.15.1 + debug: 3.1.0 + diff: 3.5.0 + escape-string-regexp: 1.0.5 + glob: 7.1.2 + growl: 1.10.5 + he: 1.1.1 + minimatch: 3.0.4 + mkdirp: 0.5.1 + supports-color: 5.4.0 + dev: false + engines: + node: '>= 4.0.0' + hasBin: true + resolution: + integrity: sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + /morgan/1.10.0: + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.0.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + /ms/2.0.0: + dev: false + resolution: + integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + /ms/2.1.1: + dev: false + resolution: + integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + /ms/2.1.2: + dev: false + resolution: + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + /mute-stream/0.0.7: + dev: false + resolution: + integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + /natural-compare/1.4.0: + dev: false + resolution: + integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + /negotiator/0.6.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + /nice-try/1.0.5: + dev: false + resolution: + integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + /npm-run-path/2.0.2: + dependencies: + path-key: 2.0.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + /number-is-nan/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + /oauth-sign/0.9.0: + dev: false + resolution: + integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + /object-assign/4.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + /object-component/0.0.3: + dev: false + resolution: + integrity: sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + /on-finished/2.3.0: + dependencies: + ee-first: 1.1.1 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + /on-headers/1.0.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + /once/1.4.0: + dependencies: + wrappy: 1.0.2 + dev: false + resolution: + integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + /onetime/2.0.1: + dependencies: + mimic-fn: 1.2.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + /optionator/0.8.3: + dependencies: + deep-is: 0.1.3 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.3 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + /os-locale/3.1.0: + dependencies: + execa: 1.0.0 + lcid: 2.0.0 + mem: 4.3.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + /os-tmpdir/1.0.2: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + /p-defer/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + /p-finally/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + /p-is-promise/2.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + /p-limit/1.3.0: + dependencies: + p-try: 1.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + /p-locate/2.0.0: + dependencies: + p-limit: 1.3.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + /p-try/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + /parent-module/1.0.1: + dependencies: + callsites: 3.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + /parseqs/0.0.5: + dependencies: + better-assert: 1.0.2 + dev: false + resolution: + integrity: sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + /parseqs/0.0.6: + dev: false + resolution: + integrity: sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== + /parseuri/0.0.5: + dependencies: + better-assert: 1.0.2 + dev: false + resolution: + integrity: sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + /parseuri/0.0.6: + dev: false + resolution: + integrity: sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== + /parseurl/1.3.3: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + /path-exists/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + /path-is-absolute/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + /path-key/2.0.1: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + /path-parse/1.0.6: + dev: false + resolution: + integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + /path-to-regexp/0.1.7: + dev: false + resolution: + integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + /performance-now/2.1.0: + dev: false + resolution: + integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + /prelude-ls/1.1.2: + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + /process-nextick-args/1.0.7: + dev: false + resolution: + integrity: sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= + /progress/2.0.3: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + /promise/7.3.1: + dependencies: + asap: 2.0.6 + dev: false + resolution: + integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + /proper-lockfile/2.0.1: + dependencies: + graceful-fs: 4.2.4 + retry: 0.10.1 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0= + /proxy-addr/2.0.6: + dependencies: + forwarded: 0.1.2 + ipaddr.js: 1.9.1 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + /psl/1.8.0: + dev: false + resolution: + integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + /pug-attrs/2.0.4: + dependencies: + constantinople: 3.1.2 + js-stringify: 1.0.2 + pug-runtime: 2.0.5 + dev: false + resolution: + integrity: sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ== + /pug-code-gen/2.0.2: + dependencies: + constantinople: 3.1.2 + doctypes: 1.1.0 + js-stringify: 1.0.2 + pug-attrs: 2.0.4 + pug-error: 1.3.3 + pug-runtime: 2.0.5 + void-elements: 2.0.1 + with: 5.1.1 + dev: false + resolution: + integrity: sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw== + /pug-error/1.3.3: + dev: false + resolution: + integrity: sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ== + /pug-filters/3.1.1: + dependencies: + clean-css: 4.2.3 + constantinople: 3.1.2 + jstransformer: 1.0.0 + pug-error: 1.3.3 + pug-walk: 1.1.8 + resolve: 1.17.0 + uglify-js: 2.8.29 + dev: false + resolution: + integrity: sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg== + /pug-lexer/4.1.0: + dependencies: + character-parser: 2.2.0 + is-expression: 3.0.0 + pug-error: 1.3.3 + dev: false + resolution: + integrity: sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA== + /pug-linker/3.0.6: + dependencies: + pug-error: 1.3.3 + pug-walk: 1.1.8 + dev: false + resolution: + integrity: sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg== + /pug-load/2.0.12: + dependencies: + object-assign: 4.1.1 + pug-walk: 1.1.8 + dev: false + resolution: + integrity: sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg== + /pug-parser/5.0.1: + dependencies: + pug-error: 1.3.3 + token-stream: 0.0.1 + dev: false + resolution: + integrity: sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA== + /pug-runtime/2.0.5: + dev: false + resolution: + integrity: sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw== + /pug-strip-comments/1.0.4: + dependencies: + pug-error: 1.3.3 + dev: false + resolution: + integrity: sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw== + /pug-walk/1.1.8: + dev: false + resolution: + integrity: sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA== + /pug/2.0.4: + dependencies: + pug-code-gen: 2.0.2 + pug-filters: 3.1.1 + pug-lexer: 4.1.0 + pug-linker: 3.0.6 + pug-load: 2.0.12 + pug-parser: 5.0.1 + pug-runtime: 2.0.5 + pug-strip-comments: 1.0.4 + dev: false + resolution: + integrity: sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw== + /pump/3.0.0: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + resolution: + integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + /punycode/2.1.1: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + /qs/6.5.2: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + /qs/6.7.0: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + /range-parser/1.2.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + /raw-body/2.4.0: + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + /readable-stream/2.0.6: + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 1.0.7 + string_decoder: 0.10.31 + util-deprecate: 1.0.2 + dev: false + resolution: + integrity: sha1-j5A0HmilPMySh4jaz80Rs265t44= + /readable-stream/3.6.0: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + /rechoir/0.6.2: + dependencies: + resolve: 1.17.0 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + /regenerator-runtime/0.11.1: + dev: false + resolution: + integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + /regexpp/2.0.1: + dev: false + engines: + node: '>=6.5.0' + resolution: + integrity: sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + /repeat-string/1.6.1: + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha1-jcrkcOHIirwtYA//Sndihtp15jc= + /request-promise-core/1.1.4_request@2.88.2: + dependencies: + lodash: 4.17.20 + request: 2.88.2 + dev: false + engines: + node: '>=0.10.0' + peerDependencies: + request: ^2.34 + resolution: + integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + /request-promise-native/1.0.9_request@2.88.2: + dependencies: + request: 2.88.2 + request-promise-core: 1.1.4_request@2.88.2 + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + deprecated: 'request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142' + dev: false + engines: + node: '>=0.12.0' + peerDependencies: + request: ^2.34 + resolution: + integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + /request/2.88.2: + dependencies: + aws-sign2: 0.7.0 + aws4: 1.10.1 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.27 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.2 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + deprecated: 'request has been deprecated, see https://github.com/request/request/issues/3142' + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + /require-directory/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + /require-main-filename/1.0.1: + dev: false + resolution: + integrity: sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + /resolve-from/4.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + /resolve/1.17.0: + dependencies: + path-parse: 1.0.6 + dev: false + resolution: + integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + /restore-cursor/2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + /retry/0.10.1: + dev: false + resolution: + integrity: sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + /right-align/0.1.3: + dependencies: + align-text: 0.1.4 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + /rimraf/2.6.3: + dependencies: + glob: 7.1.6 + dev: false + hasBin: true + resolution: + integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + /run-async/2.4.1: + dev: false + engines: + node: '>=0.12.0' + resolution: + integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + /rxjs/6.6.3: + dependencies: + tslib: 1.14.1 + dev: false + engines: + npm: '>=2.0.0' + resolution: + integrity: sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== + /safe-buffer/5.1.1: + dev: false + resolution: + integrity: sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== + /safe-buffer/5.1.2: + dev: false + resolution: + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + /safe-buffer/5.2.1: + dev: false + resolution: + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + /safer-buffer/2.1.2: + dev: false + resolution: + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + /sax/0.5.8: + dev: false + resolution: + integrity: sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE= + /sax/1.2.4: + dev: false + resolution: + integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + /semver/5.7.1: + dev: false + hasBin: true + resolution: + integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + /semver/6.3.0: + dev: false + hasBin: true + resolution: + integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + /send/0.17.1: + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + /serve-favicon/2.5.0: + dependencies: + etag: 1.8.1 + fresh: 0.5.2 + ms: 2.1.1 + parseurl: 1.3.3 + safe-buffer: 5.1.1 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-k10kDN/g9YBTB/3+ln2IlCosvPA= + /serve-static/1.14.1: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + /set-blocking/2.0.0: + dev: false + resolution: + integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + /setprototypeof/1.1.1: + dev: false + resolution: + integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + /shebang-command/1.2.0: + dependencies: + shebang-regex: 1.0.0 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + /shebang-regex/1.0.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + /shelljs/0.7.8: + dependencies: + glob: 7.1.6 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: false + engines: + node: '>=0.11.0' + hasBin: true + resolution: + integrity: sha1-3svPh0sNHl+3LhSxZKloMEjprLM= + /signal-exit/3.0.3: + dev: false + resolution: + integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + /slice-ansi/2.1.0: + dependencies: + ansi-styles: 3.2.1 + astral-regex: 1.0.0 + is-fullwidth-code-point: 2.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + /socket.io-adapter/1.1.2: + dev: false + resolution: + integrity: sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== + /socket.io-client/2.3.0: + dependencies: + backo2: 1.0.2 + base64-arraybuffer: 0.1.5 + component-bind: 1.0.0 + component-emitter: 1.2.1 + debug: 4.1.1 + engine.io-client: 3.4.4 + has-binary2: 1.0.3 + has-cors: 1.1.0 + indexof: 0.0.1 + object-component: 0.0.3 + parseqs: 0.0.5 + parseuri: 0.0.5 + socket.io-parser: 3.3.1 + to-array: 0.1.4 + dev: false + resolution: + integrity: sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== + /socket.io-client/2.3.1: + dependencies: + backo2: 1.0.2 + component-bind: 1.0.0 + component-emitter: 1.3.0 + debug: 3.1.0 + engine.io-client: 3.4.4 + has-binary2: 1.0.3 + indexof: 0.0.1 + parseqs: 0.0.6 + parseuri: 0.0.6 + socket.io-parser: 3.3.1 + to-array: 0.1.4 + dev: false + resolution: + integrity: sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ== + /socket.io-parser/3.3.1: + dependencies: + component-emitter: 1.3.0 + debug: 3.1.0 + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ== + /socket.io-parser/3.4.1: + dependencies: + component-emitter: 1.2.1 + debug: 4.1.1 + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A== + /socket.io/2.3.0: + dependencies: + debug: 4.1.1 + engine.io: 3.4.2 + has-binary2: 1.0.3 + socket.io-adapter: 1.1.2 + socket.io-client: 2.3.0 + socket.io-parser: 3.4.1 + dev: false + resolution: + integrity: sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg== + /source-map-support/0.5.13: + dependencies: + buffer-from: 1.1.1 + source-map: 0.6.1 + dev: false + resolution: + integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + /source-map/0.5.7: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + /source-map/0.6.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + /sprintf-js/1.0.3: + dev: false + resolution: + integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + /sshpk/1.16.1: + dependencies: + asn1: 0.2.4 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: false + engines: + node: '>=0.10.0' + hasBin: true + resolution: + integrity: sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + /statuses/1.5.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + /stealthy-require/1.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + /streamsearch/0.1.2: + dev: false + engines: + node: '>=0.8.0' + resolution: + integrity: sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= + /string-width/1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + /string-width/2.1.1: + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + /string-width/3.1.0: + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + /string_decoder/0.10.31: + dev: false + resolution: + integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + /string_decoder/1.3.0: + dependencies: + safe-buffer: 5.2.1 + dev: false + resolution: + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + /strip-ansi/3.0.1: + dependencies: + ansi-regex: 2.1.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + /strip-ansi/4.0.0: + dependencies: + ansi-regex: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-qEeQIusaw2iocTibY1JixQXuNo8= + /strip-ansi/5.2.0: + dependencies: + ansi-regex: 4.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + /strip-eof/1.0.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + /strip-json-comments/3.1.1: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + /supports-color/5.4.0: + dependencies: + has-flag: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + /supports-color/5.5.0: + dependencies: + has-flag: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + /supports-color/7.2.0: + dependencies: + has-flag: 4.0.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + /table/5.4.6: + dependencies: + ajv: 6.12.6 + lodash: 4.17.20 + slice-ansi: 2.1.0 + string-width: 3.1.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + /text-table/0.2.0: + dev: false + resolution: + integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + /through/2.3.8: + dev: false + resolution: + integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + /tmp/0.0.33: + dependencies: + os-tmpdir: 1.0.2 + dev: false + engines: + node: '>=0.6.0' + resolution: + integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + /to-array/0.1.4: + dev: false + resolution: + integrity: sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + /to-fast-properties/1.0.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + /toidentifier/1.0.0: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + /token-stream/0.0.1: + dev: false + resolution: + integrity: sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= + /tough-cookie/2.5.0: + dependencies: + psl: 1.8.0 + punycode: 2.1.1 + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + /tslib/1.14.1: + dev: false + resolution: + integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + /tsutils/3.17.1_typescript@3.7.5: + dependencies: + tslib: 1.14.1 + typescript: 3.7.5 + dev: false + engines: + node: '>= 6' + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + resolution: + integrity: sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + /tunnel-agent/0.6.0: + dependencies: + safe-buffer: 5.2.1 + dev: false + resolution: + integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + /tweetnacl/0.14.5: + dev: false + resolution: + integrity: sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + /type-check/0.3.2: + dependencies: + prelude-ls: 1.1.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + /type-is/1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.27 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + /typescript/3.7.5: + dev: false + engines: + node: '>=4.2.0' + hasBin: true + resolution: + integrity: sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + /uglify-js/2.8.29: + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + dev: false + engines: + node: '>=0.8.0' + hasBin: true + optionalDependencies: + uglify-to-browserify: 1.0.2 + resolution: + integrity: sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + /uglify-to-browserify/1.0.2: + dev: false + optional: true + resolution: + integrity: sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + /underscore/1.11.0: + dev: false + resolution: + integrity: sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw== + /underscore/1.8.3: + dev: false + resolution: + integrity: sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= + /unpipe/1.0.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + /uri-js/4.4.0: + dependencies: + punycode: 2.1.1 + dev: false + resolution: + integrity: sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + /util-deprecate/1.0.2: + dev: false + resolution: + integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + /utils-merge/1.0.1: + dev: false + engines: + node: '>= 0.4.0' + resolution: + integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + /uuid/3.4.0: + dev: false + hasBin: true + resolution: + integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + /v8-compile-cache/2.1.1: + dev: false + resolution: + integrity: sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + /validator/9.4.1: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA== + /vary/1.1.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + /verror/1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + /void-elements/2.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + /vscode-jsonrpc/3.6.2: + dev: false + engines: + node: '>=4.0.0 || >=6.0.0' + resolution: + integrity: sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA== + /which-module/2.0.0: + dev: false + resolution: + integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + /which/1.3.1: + dependencies: + isexe: 2.0.0 + dev: false + hasBin: true + resolution: + integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + /window-size/0.1.0: + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + /wiremock/2.25.0: + dependencies: + shelljs: 0.7.8 + dev: false + hasBin: true + resolution: + integrity: sha512-F7i9ikOENfz7QnhvDFJGFFVkmSq3+wySLFiNLB5NAThRCw0xdU0FimkAHLP6MLEnqxvg1/O7JEaTg+PAaX24+w== + /with/5.1.1: + dependencies: + acorn: 3.3.0 + acorn-globals: 3.1.0 + dev: false + resolution: + integrity: sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4= + /word-wrap/1.2.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + /wordwrap/0.0.2: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + /wrap-ansi/2.1.0: + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + /wrappy/1.0.2: + dev: false + resolution: + integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + /write/1.0.3: + dependencies: + mkdirp: 0.5.5 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + /ws/6.1.4: + dependencies: + async-limiter: 1.0.1 + dev: false + resolution: + integrity: sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + /ws/7.3.1: + dev: false + engines: + node: '>=8.3.0' + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + resolution: + integrity: sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== + /xml2js/0.2.8: + dependencies: + sax: 0.5.8 + dev: false + resolution: + integrity: sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I= + /xml2js/0.4.23: + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + /xmlbuilder/10.1.1: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg== + /xmlbuilder/11.0.1: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + /xmlbuilder/9.0.7: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + /xmlhttprequest-ssl/1.5.5: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= + /y18n/3.2.1: + dev: false + resolution: + integrity: sha1-bRX7qITAhnnA136I53WegR4H+kE= + /yargs-parser/9.0.2: + dependencies: + camelcase: 4.1.0 + dev: false + resolution: + integrity: sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + /yargs/11.1.1: + dependencies: + cliui: 4.1.0 + decamelize: 1.2.0 + find-up: 2.1.0 + get-caller-file: 1.0.3 + os-locale: 3.1.0 + require-directory: 2.1.1 + require-main-filename: 1.0.1 + set-blocking: 2.0.0 + string-width: 2.1.1 + which-module: 2.0.0 + y18n: 3.2.1 + yargs-parser: 9.0.2 + dev: false + resolution: + integrity: sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== + /yargs/3.10.0: + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: false + resolution: + integrity: sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + /yeast/0.1.2: + dev: false + resolution: + integrity: sha1-AI4G2AlDIMNy28L47XagymyKxBk= + 'file:projects/powershell.tgz': + dependencies: + '@autorest/autorest': 3.0.6187 + '@azure-tools/async-io': 3.0.252 + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/codegen-csharp': 3.0.262 + '@azure-tools/codemodel': 4.13.348 + '@azure-tools/codemodel-v3': 3.1.264 + '@azure-tools/linq': 3.1.261 + '@azure-tools/tasks': 3.0.252 + '@microsoft.azure/autorest.testserver': 2.9.9 + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': 2.0.0_b7c2671679a3bd4e1f52a3d3da16606f + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: 3.7.5 + xmlbuilder: 10.1.1 + dev: false + name: '@rush-temp/powershell' + resolution: + integrity: sha512-p6zFKQmmQo1rntIeAg/ELKH+i12IV+ZcTM9J3luYZeV7zc1mZ3A+DReEuxshx+3oR0WyOCw9jUgTm0hGHJQXWA== + tarball: 'file:projects/powershell.tgz' + version: 0.0.0 +specifiers: + '@autorest/autorest': ~3.0.6118 + '@azure-tools/async-io': ~3.0.0 + '@azure-tools/autorest-extension-base': ~3.1.0 + '@azure-tools/codegen': ^2.5.276 + '@azure-tools/codegen-csharp': ~3.0.0 + '@azure-tools/codemodel': ~4.13.342 + '@azure-tools/codemodel-v3': ~3.1.0 + '@azure-tools/linq': ~3.1.0 + '@azure-tools/tasks': ~3.0.0 + '@microsoft.azure/autorest.testserver': ~2.9.3 + '@rush-temp/powershell': 'file:./projects/powershell.tgz' + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': ~2.0.0 + '@typescript-eslint/parser': ~2.0.0 + eslint: ~6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: ~3.7.0-beta + xmlbuilder: 10.1.1 diff --git a/common/scripts/install-run-rush.js b/common/scripts/install-run-rush.js index 7fc381d5640..71ca9fe4676 100644 --- a/common/scripts/install-run-rush.js +++ b/common/scripts/install-run-rush.js @@ -1,6 +1,25 @@ "use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // @@ -12,8 +31,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run-rush.js install // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const path = require("path"); -const fs = require("fs"); +const path = __importStar(require("path")); +const fs = __importStar(require("fs")); const install_run_1 = require("./install-run"); const PACKAGE_NAME = '@microsoft/rush'; const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; @@ -34,12 +53,12 @@ function _getRushVersion() { } catch (e) { throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + - 'The \'rushVersion\' field is either not assigned in rush.json or was specified ' + + "The 'rushVersion' field is either not assigned in rush.json or was specified " + 'using an unexpected syntax.'); } } function _run() { - const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ ...packageBinArgs /* [build, --to, myproject] */] = process.argv; + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv; // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the // appropriate binary inside the rush package to run const scriptName = path.basename(scriptPath); diff --git a/common/scripts/install-run.js b/common/scripts/install-run.js index 9c43223f7cc..86912c7ccdd 100644 --- a/common/scripts/install-run.js +++ b/common/scripts/install-run.js @@ -1,7 +1,27 @@ "use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); +exports.runWithErrorAndStatusCode = exports.installAndRun = exports.findRushJsonFolder = exports.getNpmPath = exports.RUSH_JSON_FILENAME = void 0; // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // // This script is intended for usage in an automated build environment where a Node tool may not have @@ -12,10 +32,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const childProcess = require("child_process"); -const fs = require("fs"); -const os = require("os"); -const path = require("path"); +const childProcess = __importStar(require("child_process")); +const fs = __importStar(require("fs")); +const os = __importStar(require("os")); +const path = __importStar(require("path")); exports.RUSH_JSON_FILENAME = 'rush.json'; const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; const INSTALLED_FLAG_FILENAME = 'installed.flag'; @@ -46,6 +66,151 @@ function _parsePackageSpecifier(rawPackageSpecifier) { } return { name, version }; } +/** + * As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims + * unusable lines from the .npmrc file. + * + * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in + * the .npmrc file to provide different authentication tokens for different registry. + * However, if the environment variable is undefined, it expands to an empty string, which + * produces a valid-looking mapping with an invalid URL that causes an error. Instead, + * we'd prefer to skip that line and continue looking in other places such as the user's + * home directory. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities.copyAndTrimNpmrcFile() + */ +function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) { + console.log(`Copying ${sourceNpmrcPath} --> ${targetNpmrcPath}`); // Verbose + let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); + npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); + const resultLines = []; + // This finds environment variable tokens that look like "${VAR_NAME}" + const expansionRegExp = /\$\{([^\}]+)\}/g; + // Comment lines start with "#" or ";" + const commentRegExp = /^\s*[#;]/; + // Trim out lines that reference environment variables that aren't defined + for (const line of npmrcFileLines) { + let lineShouldBeTrimmed = false; + // Ignore comment lines + if (!commentRegExp.test(line)) { + const environmentVariables = line.match(expansionRegExp); + if (environmentVariables) { + for (const token of environmentVariables) { + // Remove the leading "${" and the trailing "}" from the token + const environmentVariableName = token.substring(2, token.length - 1); + // Is the environment variable defined? + if (!process.env[environmentVariableName]) { + // No, so trim this line + lineShouldBeTrimmed = true; + break; + } + } + } + } + if (lineShouldBeTrimmed) { + // Example output: + // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" + resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); + } + else { + resultLines.push(line); + } + } + fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); +} +/** + * syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file. + * If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() + */ +function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish) { + const sourceNpmrcPath = path.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); + const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); + try { + if (fs.existsSync(sourceNpmrcPath)) { + _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath); + } + else if (fs.existsSync(targetNpmrcPath)) { + // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target + console.log(`Deleting ${targetNpmrcPath}`); // Verbose + fs.unlinkSync(targetNpmrcPath); + } + } + catch (e) { + throw new Error(`Error syncing .npmrc file: ${e}`); + } +} +let _npmPath = undefined; +/** + * Get the absolute path to the npm executable + */ +function getNpmPath() { + if (!_npmPath) { + try { + if (os.platform() === 'win32') { + // We're on Windows + const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); + const lines = whereOutput.split(os.EOL).filter((line) => !!line); + // take the last result, we are looking for a .cmd command + // see https://github.com/microsoft/rushstack/issues/759 + _npmPath = lines[lines.length - 1]; + } + else { + // We aren't on Windows - assume we're on *NIX or Darwin + _npmPath = childProcess.execSync('command -v npm', { stdio: [] }).toString(); + } + } + catch (e) { + throw new Error(`Unable to determine the path to the NPM tool: ${e}`); + } + _npmPath = _npmPath.trim(); + if (!fs.existsSync(_npmPath)) { + throw new Error('The NPM executable does not exist'); + } + } + return _npmPath; +} +exports.getNpmPath = getNpmPath; +function _ensureFolder(folderPath) { + if (!fs.existsSync(folderPath)) { + const parentDir = path.dirname(folderPath); + _ensureFolder(parentDir); + fs.mkdirSync(folderPath); + } +} +/** + * Create missing directories under the specified base directory, and return the resolved directory. + * + * Does not support "." or ".." path segments. + * Assumes the baseFolder exists. + */ +function _ensureAndJoinPath(baseFolder, ...pathSegments) { + let joinedPath = baseFolder; + try { + for (let pathSegment of pathSegments) { + pathSegment = pathSegment.replace(/[\\\/]/g, '+'); + joinedPath = path.join(joinedPath, pathSegment); + if (!fs.existsSync(joinedPath)) { + fs.mkdirSync(joinedPath); + } + } + } + catch (e) { + throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); + } + return joinedPath; +} +function _getRushTempFolder(rushCommonFolder) { + const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; + if (rushTempFolder !== undefined) { + _ensureFolder(rushTempFolder); + return rushTempFolder; + } + else { + return _ensureAndJoinPath(rushCommonFolder, 'temp'); + } +} /** * Resolve a package specifier to a static version */ @@ -95,37 +260,6 @@ function _resolvePackageVersion(rushCommonFolder, { name, version }) { } } } -let _npmPath = undefined; -/** - * Get the absolute path to the npm executable - */ -function getNpmPath() { - if (!_npmPath) { - try { - if (os.platform() === 'win32') { - // We're on Windows - const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); - const lines = whereOutput.split(os.EOL).filter((line) => !!line); - // take the last result, we are looking for a .cmd command - // see https://github.com/Microsoft/web-build-tools/issues/759 - _npmPath = lines[lines.length - 1]; - } - else { - // We aren't on Windows - assume we're on *NIX or Darwin - _npmPath = childProcess.execSync('which npm', { stdio: [] }).toString(); - } - } - catch (e) { - throw new Error(`Unable to determine the path to the NPM tool: ${e}`); - } - _npmPath = _npmPath.trim(); - if (!fs.existsSync(_npmPath)) { - throw new Error('The NPM executable does not exist'); - } - } - return _npmPath; -} -exports.getNpmPath = getNpmPath; let _rushJsonFolder; /** * Find the absolute path to the folder containing rush.json @@ -151,86 +285,6 @@ function findRushJsonFolder() { return _rushJsonFolder; } exports.findRushJsonFolder = findRushJsonFolder; -/** - * Create missing directories under the specified base directory, and return the resolved directory. - * - * Does not support "." or ".." path segments. - * Assumes the baseFolder exists. - */ -function _ensureAndJoinPath(baseFolder, ...pathSegments) { - let joinedPath = baseFolder; - try { - for (let pathSegment of pathSegments) { - pathSegment = pathSegment.replace(/[\\\/]/g, '+'); - joinedPath = path.join(joinedPath, pathSegment); - if (!fs.existsSync(joinedPath)) { - fs.mkdirSync(joinedPath); - } - } - } - catch (e) { - throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); - } - return joinedPath; -} -/** - * As a workaround, _syncNpmrc() copies the .npmrc file to the target folder, and also trims - * unusable lines from the .npmrc file. If the source .npmrc file not exist, then _syncNpmrc() - * will delete an .npmrc that is found in the target folder. - * - * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in - * the .npmrc file to provide different authentication tokens for different registry. - * However, if the environment variable is undefined, it expands to an empty string, which - * produces a valid-looking mapping with an invalid URL that causes an error. Instead, - * we'd prefer to skip that line and continue looking in other places such as the user's - * home directory. - * - * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() - */ -function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder) { - const sourceNpmrcPath = path.join(sourceNpmrcFolder, '.npmrc'); - const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); - try { - if (fs.existsSync(sourceNpmrcPath)) { - let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); - npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); - const resultLines = []; - // Trim out lines that reference environment variables that aren't defined - for (const line of npmrcFileLines) { - // This finds environment variable tokens that look like "${VAR_NAME}" - const regex = /\$\{([^\}]+)\}/g; - const environmentVariables = line.match(regex); - let lineShouldBeTrimmed = false; - if (environmentVariables) { - for (const token of environmentVariables) { - // Remove the leading "${" and the trailing "}" from the token - const environmentVariableName = token.substring(2, token.length - 1); - if (!process.env[environmentVariableName]) { - lineShouldBeTrimmed = true; - break; - } - } - } - if (lineShouldBeTrimmed) { - // Example output: - // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" - resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); - } - else { - resultLines.push(line); - } - } - fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); - } - else if (fs.existsSync(targetNpmrcPath)) { - // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target - fs.unlinkSync(targetNpmrcPath); - } - } - catch (e) { - throw new Error(`Error syncing .npmrc file: ${e}`); - } -} /** * Detects if the package in the specified directory is installed */ @@ -265,8 +319,8 @@ function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { } const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); if (fs.existsSync(nodeModulesFolder)) { - const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler', `install-run-${Date.now().toString()}`); - fs.renameSync(nodeModulesFolder, rushRecyclerFolder); + const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler'); + fs.renameSync(nodeModulesFolder, path.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`)); } } catch (e) { @@ -276,14 +330,14 @@ function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { function _createPackageJson(packageInstallFolder, name, version) { try { const packageJsonContents = { - 'name': 'ci-rush', - 'version': '0.0.0', - 'dependencies': { + name: 'ci-rush', + version: '0.0.0', + dependencies: { [name]: version }, - 'description': 'DON\'T WARN', - 'repository': 'DON\'T WARN', - 'license': 'MIT' + description: "DON'T WARN", + repository: "DON'T WARN", + license: 'MIT' }; const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME); fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); @@ -318,7 +372,7 @@ function _installPackage(packageInstallFolder, name, version) { */ function _getBinPath(packageInstallFolder, binName) { const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); - const resolvedBinName = (os.platform() === 'win32') ? `${binName}.cmd` : binName; + const resolvedBinName = os.platform() === 'win32' ? `${binName}.cmd` : binName; return path.resolve(binFolderPath, resolvedBinName); } /** @@ -333,23 +387,6 @@ function _writeFlagFile(packageInstallFolder) { throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`); } } -function _getRushTempFolder(rushCommonFolder) { - const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; - if (rushTempFolder !== undefined) { - _ensureFolder(rushTempFolder); - return rushTempFolder; - } - else { - return _ensureAndJoinPath(rushCommonFolder, 'temp'); - } -} -function _ensureFolder(folderPath) { - if (!fs.existsSync(folderPath)) { - const parentDir = path.dirname(folderPath); - _ensureFolder(parentDir); - fs.mkdirSync(folderPath); - } -} function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) { const rushJsonFolder = findRushJsonFolder(); const rushCommonFolder = path.join(rushJsonFolder, 'common'); @@ -368,12 +405,28 @@ function installAndRun(packageName, packageVersion, packageBinName, packageBinAr const statusMessageLine = new Array(statusMessage.length + 1).join('-'); console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL); const binPath = _getBinPath(packageInstallFolder, packageBinName); - const result = childProcess.spawnSync(binPath, packageBinArgs, { - stdio: 'inherit', - cwd: process.cwd(), - env: process.env - }); - return result.status; + const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + // Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to + // assign via the process.env proxy to ensure that we append to the right PATH key. + const originalEnvPath = process.env.PATH || ''; + let result; + try { + process.env.PATH = [binFolderPath, originalEnvPath].join(path.delimiter); + result = childProcess.spawnSync(binPath, packageBinArgs, { + stdio: 'inherit', + cwd: process.cwd(), + env: process.env + }); + } + finally { + process.env.PATH = originalEnvPath; + } + if (result.status !== null) { + return result.status; + } + else { + throw result.error || new Error('An unknown error occurred.'); + } } exports.installAndRun = installAndRun; function runWithErrorAndStatusCode(fn) { @@ -388,7 +441,7 @@ function runWithErrorAndStatusCode(fn) { } exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode; function _run() { - const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ rawPackageSpecifier, /* qrcode@^1.2.0 */ packageBinName, /* qrcode */ ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; if (!nodePath) { throw new Error('Unexpected exception: could not detect node path'); } diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 2c9dd6aacab..d6b1cf3530a 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -16,9 +16,8 @@ modelerfour: > if the modeler is loaded already, use that one, otherwise grab it. -``` yaml +``` yaml !isLoaded('@autorest/modelerfour') use-extension: - "@autorest/remodeler" : "~2.1.0" "@autorest/modelerfour": "4.15.414" # will use highest 2.0.x @@ -105,24 +104,6 @@ declare-directive: # Pipeline Configuration ``` yaml pipeline: -# --- extension remodeler --- - - # "Shake the tree", and normalize the model - remodeler: - input: openapi-document/multi-api/identity # the plugin where we get inputs from - - # allow developer to do transformations on the code model. - remodeler/new-transform: - input: remodeler - - # Make some interpretations about what some things in the model mean - tweakcodemodel: - input: remodeler/new-transform - - # Specific things for Azure - tweakcodemodelazure: - input: tweakcodemodel - # --- extension powershell based on modelerfour # Fix the code model gap between m3 and m4 @@ -159,44 +140,15 @@ pipeline: powershell-v2: input: add-azure-completers-v2 -# --- extension powershell --- - - # creates high-level commands - create-commands: - input: tweakcodemodelazure # brings the code-model-v3 with it. - - create-virtual-properties: - input: create-commands - - # Choose names for everything in c# - csnamer: - input: create-virtual-properties # and the generated c# files - - # ensures that names/descriptions are properly set for powershell - psnamer: - input: csnamer - - modifiers: - input: psnamer - - add-azure-completers: - input: modifiers - - # creates powershell cmdlets for high-level commands. (leverages llc# code) - powershell: - input: add-azure-completers # and the generated c# files # --- extension llcsharp --- # generates c# files for http-operations - llcsharp: - input: modifiers - llcsharp/text-transform: input: llcsharp-v2 scope: scope-here powershell/text-transform: - input: powershell-v2 + input: powershell-v2 scope: scope-here llcsharp/emitter: diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index efe286423d3..5ede09c12ba 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -13,9 +13,9 @@ import { Access, Attribute, BackedProperty, Catch, Class, ClassType, Constructor, dotnet, Else, Expression, Finally, ForEach, If, LambdaProperty, LiteralExpression, LocalVariable, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Property, Return, Statements, BlockStatement, StringExpression, Switch, System, TerminalCase, toExpression, Try, Using, valueOf, Field, IsNull, Or, ExpressionOrLiteral, TerminalDefaultCase, xmlize, TypeDeclaration, And, IsNotNull, PartialMethod, Case } from '@azure-tools/codegen-csharp'; -import { ClientRuntime, EventListener, Schema, ArrayOf, NewArrayOf, EnumImplementation, NewEnumImplementation } from '../llcsharp/exports'; +import { ClientRuntime, EventListener, Schema, ArrayOf, EnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; -import { State, NewState } from '../internal/state'; +import { State } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; import { IParameter } from '@azure-tools/codemodel-v3/dist/code-model/components'; import { IParameter as NewIParameter } from '../utils/components'; @@ -300,1216 +300,6 @@ export class CmdletClass extends Class { private bodyParameter?: Variable; private bodyParameterInfo?: { type: TypeDeclaration; valueType: TypeDeclaration }; private apProp?: Property; - private operation: command.CommandOperation; - private debugMode?: boolean; - private variantName: string; - private isViaIdentity: boolean; - private hasStreamOutput: boolean; - private outFileParameter?: Property; - - constructor(namespace: Namespace, operation: command.CommandOperation, state: State, objectInitializer?: DeepPartial) { - // generate the 'variant' part of the name - const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; - const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; - - const name = `${operation.details.csharp.verb}${variantName}`; - super(namespace, name, PSCmdlet); - this.dropBodyParameter = operation.details.csharp.dropBodyParameter ? true : false; - this.apply(objectInitializer); - this.operation = operation; - this.state = state; - this.thingsToSerialize = []; - this.variantName = variantName; - this.hasStreamOutput = false; - - this.interfaces.push(ClientRuntime.IEventListener); - this.eventListener = new EventListener(new LiteralExpression(`((${ClientRuntime.IEventListener})this)`), true); - - this.isViaIdentity = variantName.indexOf('ViaIdentity') > 0; - - } - - async init() { - - // basic stuff - this.addCommonStuff(); - - this.description = escapeString(this.operation.details.csharp.description); - const $this = this; - - this.add(new Method('BeginProcessing', dotnet.Void, { - override: Modifier.Override, - access: Access.Protected, - description: `(overrides the default BeginProcessing method in ${PSCmdlet})`, - *body() { - yield 'Module.Instance.SetProxyConfiguration(Proxy, ProxyCredential, ProxyUseDefaultCredentials);'; - yield If($this.$('Break'), `${ClientRuntime.AttachDebugger}.Break();`); - - yield $this.eventListener.syncSignal(Events.CmdletBeginProcessing); - } - })); - - // construct the class - this.addClassAttributes(this.operation, this.variantName); - if (this.hasStreamOutput) { - this.outFileParameter = this.add(new Property('OutFile', System.String, { attributes: [], description: 'Path to write output file to.' })); - this.outFileParameter.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = true', 'HelpMessage = "Path to write output file to"'] })); - this.outFileParameter.add(new Attribute(ValidateNotNull)); - this.outFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - } - - this.addPowershellParameters(this.operation); - - // implement IEventListener - this.implementIEventListener(); - - // add constructors - this.implementConstructors(); - - // processRecord - this.implementProcessRecord(this.operation); - - this.implementProcessRecordAsync(this.operation); - this.debugMode = await this.state.getValue('debug', false); - - // json serialization - this.implementSerialization(this.operation); - - for (const prop of this.properties) { - if (prop.name === 'Host') { - prop['new'] = Modifier.New; - } - } - - return this; - } - - public get headerComment(): string { - const header = super.headerComment; - let ops = ''; - - for (const httpOperation of values(this.operation.callGraph)) { - ops = `${ops}\n[OpenAPI] ${httpOperation.operationId}=>${httpOperation.method.toUpperCase()}:"${httpOperation.path}"`; - if (this.debugMode) { - const m = (httpOperation.extensions && httpOperation.extensions['x-ms-metadata']) || (httpOperation.pathExtensions ? httpOperation.pathExtensions['x-ms-metadata'] : undefined); - if (m) { - ops = `${ops}\n [METADATA]\n${serialize(m)}`; - } - - ops = `${ops}\n [DETAILS]`; - ops = `${ops}\n verb: ${this.operation.details.csharp.verb}`; - ops = `${ops}\n subjectPrefix: ${this.operation.details.csharp.subjectPrefix}`; - ops = `${ops}\n subject: ${this.operation.details.csharp.subject}`; - ops = `${ops}\n variant: ${this.operation.details.csharp.name}`; - } - } - - return ops ? `${header}\n${docComment(xmlize('remarks', ops))}` : header; - } - - private addCommonStuff() { - - // add a private copy of invocation information for our own uses. - const privateInvocationInfo = this.add(new Field('__invocationInfo', InvocationInfo, { description: 'A copy of the Invocation Info (necessary to allow asJob to clone this cmdlet)', access: Access.Private })); - this.invocationInfo = new Property('InvocationInformation', InvocationInfo, { description: 'Accessor for our copy of the InvocationInfo.' }); - this.invocationInfo.get = toExpression(`${privateInvocationInfo.value} = ${privateInvocationInfo.value} ?? this.MyInvocation `); - this.invocationInfo.set = new Statements(privateInvocationInfo.assign('value')); - this.add(this.invocationInfo); - - if (this.state.project.azure) { - this.correlationId = this.add(new Field('__correlationId', dotnet.String, { initialValue: 'System.Guid.NewGuid().ToString()', description: 'A unique id generatd for the this cmdlet when it is instantiated.', access: Access.Private })); - this.processRecordId = this.add(new Field('__processRecordId', dotnet.String, { description: 'A unique id generatd for the this cmdlet when ProcessRecord() is called.', access: Access.Private })); - } - - // pipeline property - this.add(new Property('Pipeline', ClientRuntime.HttpPipeline, { getAccess: Access.Private, setAccess: Access.Private, description: `The instance of the that the remote call will use.` })); - - // client API property (gs01: fill this in correctly) - const clientAPI = new ClassType(this.state.model.details.csharp.namespace, this.state.model.details.csharp.name); - this.add(new LambdaProperty('Client', clientAPI, new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.ClientAPI`), { description: 'The reference to the client API class.' })); - - this.add(new Method('StopProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Interrupts currently running code within the command.' })).add(function* () { - yield `((${ClientRuntime.IEventListener})this).Cancel();`; - yield 'base.StopProcessing();'; - }); - - const $this = this; - this.add(new Method('EndProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Performs clean-up after the command execution' })).add(function* () { - // gs01: remember what you were doing here to make it so these can be parallelized... - yield ''; - yield $this.eventListener.syncSignal(Events.CmdletEndProcessing); - }); - - // debugging - const brk = this.add(new Property('Break', SwitchParameter, { attributes: [], description: 'Wait for .NET debugger to attach' })); - brk.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Wait for .NET debugger to attach"'] })); - brk.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - // Cmdlet Parameters for pipeline manipulations. - const prepend = this.add(new Property('HttpPipelinePrepend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be prepended to the front of the pipeline' })); - prepend.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be prepended to the front of the pipeline"'] })); - prepend.add(new Attribute(ValidateNotNull)); - prepend.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const append = this.add(new Property('HttpPipelineAppend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be appended to the front of the pipeline' })); - append.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be appended to the front of the pipeline"'] })); - append.add(new Attribute(ValidateNotNull)); - append.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const proxyCredential = this.add(new Property('ProxyCredential', PSCredential, { attributes: [], description: 'Credentials for a proxy server to use for the remote call' })); - proxyCredential.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Credentials for a proxy server to use for the remote call"'] })); - proxyCredential.add(new Attribute(ValidateNotNull)); - proxyCredential.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const useDefaultCreds = this.add(new Property('ProxyUseDefaultCredentials ', SwitchParameter, { attributes: [], description: 'Use the default credentials for the proxy' })); - useDefaultCreds.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Use the default credentials for the proxy"'] })); - useDefaultCreds.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const proxyUri = this.add(new Property('Proxy', System.Uri, { attributes: [], description: 'The URI for the proxy server to use' })); - proxyUri.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "The URI for the proxy server to use"'] })); - proxyUri.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - if (this.state.project.azure) { - this.defaultProfile = this.add(new Property('DefaultProfile', PSObject, { description: 'The credentials, account, tenant, and subscription used for communication with Azure' })); - this.defaultProfile.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "The credentials, account, tenant, and subscription used for communication with Azure."'] })); - this.defaultProfile.add(new Attribute(ValidateNotNull)); - this.defaultProfile.add(new Attribute(Alias, { parameters: ['"AzureRMContext"', '"AzureCredential"'] })); - this.defaultProfile.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Azure`] })); - } - } - - private isWritableCmdlet(operation: command.CommandOperation): boolean { - switch (operation.callGraph[0].method.toLowerCase()) { - case 'put': - case 'post': - case 'delete': - case 'patch': - return true; - } - return false; - } - - private implementProcessRecord(operation: command.CommandOperation) { - const $this = this; - const writable = this.isWritableCmdlet(operation); - - this.add(new Method('ProcessRecord', undefined, { access: Access.Protected, override: Modifier.Override, description: 'Performs execution of the command.' })).add(function* () { - yield $this.eventListener.syncSignal(Events.CmdletProcessRecordStart); - if ($this.state.project.azure) { - yield $this.processRecordId.assign('System.Guid.NewGuid().ToString()'); - } - yield Try(function* () { - yield '// work'; - const normal = new Statements(function* () { - const acr = new LocalVariable('asyncCommandRuntime', dotnet.Var, { initializer: AsyncCommandRuntime.new(dotnet.This, $this.cancellationToken) }); - yield Using(acr.declarationExpression, function* () { - yield `${acr}.Wait( ProcessRecordAsync(),${$this.cancellationToken});`; - }); - }); - - if (operation.asjob) { - const asjob = $this.add(new Property('AsJob', SwitchParameter, { description: 'when specified, runs this cmdlet as a PowerShell job' })); - asjob.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command as a job"'] })); - asjob.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const nowait = $this.add(new Property('NoWait', SwitchParameter, { description: 'when specified, will make the remote call, and return an AsyncOperationResponse, letting the remote operation continue asynchronously.' })); - nowait.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command asynchronously"'] })); - nowait.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - } - - const work: OneOrMoreStatements = operation.asjob ? function* () { - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("AsJob")', function* () { - // clone the cmdlet instance, since the instance can be reused and overwrite data. - const instance = new LocalVariable('instance', dotnet.Var, { initializer: 'this.Clone()' }); - yield instance.declarationStatement; - - // create the job (which will set the CommandRuntime of the clone to the AsyncJob itself) - const job = new LocalVariable('job', dotnet.Var, { initializer: AsyncJob.new(instance, 'this.MyInvocation.Line, this.MyInvocation.MyCommand.Name, this._cancellationTokenSource.Token', 'this._cancellationTokenSource.Cancel') }); - yield job.declarationStatement; - - // add the job to the repository - yield `JobRepository.Add(${job});`; - - // invoke the cmdlet's PRA - const task = new LocalVariable('task', dotnet.Var, { initializer: `${instance}.ProcessRecordAsync()` }); - yield task.declarationStatement; - - // have the AsyncJob monitor the lifetime of the Task - yield `${job}.Monitor(${task});`; - - // return the job to the user now. - yield `WriteObject(${job});`; - - }); - yield Else(normal); - } : normal; - - if (writable) { - yield If(`ShouldProcess($"Call remote '${operation.callGraph[0].details.csharp.name}' operation")`, work); - } else { - yield work; - } - }); - const aggregateException = new Parameter('aggregateException', System.AggregateException); - yield Catch(aggregateException, function* () { - yield '// unroll the inner exceptions to get the root cause'; - yield ForEach('innerException', new LiteralExpression(`${aggregateException.use}.Flatten().InnerExceptions`), function* () { - yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression('$"{innerException.GetType().Name} - {innerException.Message} : {innerException.StackTrace}"')); - yield '// Write exception out to error channel.'; - yield `WriteError( new ${ErrorRecord}(innerException,string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; - }); - }); - const exception = new Parameter('exception', System.Exception); - yield Catch(exception, function* () { - yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression(`$"{${exception.use}.GetType().Name} - {${exception.use}.Message} : {${exception.use}.StackTrace}"`)); - yield '// Write exception out to error channel.'; - yield `WriteError( new ${ErrorRecord}(${exception.use},string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; - }, { when: new LiteralExpression('(exception as System.Management.Automation.PipelineStoppedException)== null || (exception as System.Management.Automation.PipelineStoppedException).InnerException != null') }); - - yield Finally(function* () { - yield $this.eventListener.syncSignalNoCheck(Events.CmdletProcessRecordEnd); - }); - }); - - } - - private implementProcessRecordAsync(operation: command.CommandOperation) { - const $this = this; - const PAR = this.add(new Method('ProcessRecordAsync', System.Threading.Tasks.Task(), { - access: Access.Protected, async: Modifier.Async, - description: 'Performs execution of the command, working asynchronously if required.', - returnsDescription: `A that will be complete when handling of the method is completed.` - })); - - // we don't want to use SynchContext here. - PAR.push(Using('NoSynchronizationContext', '')); - - PAR.add(function* () { - if ($this.apProp && $this.bodyParameter && $this.bodyParameterInfo) { - // yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${$this.bodyParameterInfo.type.declaration},${$this.bodyParameterInfo.valueType.declaration}>(${$this.apProp.value},${$this.bodyParameter.Cast($this.bodyParameterInfo.type)});`; - let vt = $this.bodyParameterInfo.valueType.declaration; - if (vt.endsWith('SwitchParameter')) { - vt = 'bool'; - } - yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${vt}>(${$this.apProp.value},${$this.bodyParameter}.AdditionalProperties);`; - } - - // construct the call to the operation - yield $this.eventListener.signal(Events.CmdletProcessRecordAsyncStart); - - yield $this.eventListener.signal(Events.CmdletGetPipeline); - - const pipeline = $this.$('Pipeline'); - - if ($this.state.project.azure) { - yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, ${$this.correlationId}, ${$this.processRecordId}, this.ParameterSetName)`)); - } else { - yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, this.ParameterSetName)`)); - } - - yield If(IsNotNull($this.$('HttpPipelinePrepend')), pipeline.invokeMethod('Prepend', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelinePrepend')}) ?? ${$this.$('HttpPipelinePrepend')}`))); - yield If(IsNotNull($this.$('HttpPipelineAppend')), pipeline.invokeMethod('Append', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelineAppend')}) ?? ${$this.$('HttpPipelineAppend')}`))); - - yield '// get the client instance'; - const apiCall = operation.callGraph[0]; - - // find each parameter to the method, and find out where the value is going to come from. - const operationParameters = - values(apiCall.parameters). - // filter out constants and path parameters when using piping for identity - where(each => !(each.details.csharp.constantValue) /* && (!$this.isViaIdentity || each.in !== ParameterLocation.Path) */). - - select(p => { - return { - name: p.details.csharp.name, - param: values($this.properties). - where(each => each.metadata.parameterDefinition). - first(each => each.metadata.parameterDefinition.details.csharp.uid === p.details.csharp.uid), - isPathParam: $this.isViaIdentity && p.in === ParameterLocation.Path - }; - - }). - select(each => { - if (each.param) { - - const httpParam = ((each.param.metadata.parameterDefinition)); - if (httpParam.required) { - return { - name: each.param, - expression: each.param, - isPathParam: each.isPathParam - }; - } - - const httpParamTD = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((httpParam.schema), httpParam.required, $this.state); - return { - name: each.param, - expression: toExpression(`this.InvocationInformation.BoundParameters.ContainsKey("${each.param.value}") ? ${each.param.value} : ${httpParamTD.defaultOfType}`), - isPathParam: each.isPathParam - }; - - } - - return { name: each.name, expression: dotnet.Null, isPathParam: each.isPathParam }; - }).toArray(); - - // is there a body parameter we should include? - if ($this.bodyParameter) { - operationParameters.push({ name: 'body', expression: $this.bodyParameter, isPathParam: false }); - } - - // create the response handlers - const responses = [...values(apiCall.responses).selectMany(each => each)]; - - const callbackMethods = values(responses).toArray().map(each => new LiteralExpression(each.details.csharp.name)); - - // make callback methods - for (const each of values(responses)) { - - const parameters = new Array(); - parameters.push(new Parameter('responseMessage', System.Net.Http.HttpResponseMessage, { description: `the raw response message as an ${System.Net.Http.HttpResponseMessage}.` })); - - if (each.details.csharp.responseType) { - parameters.push(new Parameter('response', System.Threading.Tasks.Task({ declaration: each.details.csharp.responseType }), { description: `the body result as a from the remote call` })); - } - if (each.details.csharp.headerType) { - parameters.push(new Parameter('headers', System.Threading.Tasks.Task({ declaration: each.details.csharp.headerType }), { description: `the header result as a from the remote call` })); - } - - const override = `override${pascalCase(each.details.csharp.name)}`; - const returnNow = new Parameter('returnNow', System.Threading.Tasks.Task(dotnet.Bool), { modifier: ParameterModifier.Ref, description: `/// Determines if the rest of the ${each.details.csharp.name} method should be processed, or if the method should return immediately (set to true to skip further processing )` }); - const overrideResponseMethod = new PartialMethod(override, dotnet.Void, { - parameters: [...parameters, returnNow], - description: `${override} will be called before the regular ${each.details.csharp.name} has been processed, allowing customization of what happens on that response. Implement this method in a partial class to enable this behavior`, - returnsDescription: `A that will be complete when handling of the method is completed.` - }); - $this.add(overrideResponseMethod); - - const responseMethod = new Method(`${each.details.csharp.name}`, System.Threading.Tasks.Task(), { - access: Access.Private, - parameters, - async: Modifier.Async, - description: each.details.csharp.description, - returnsDescription: `A that will be complete when handling of the method is completed.` - }); - responseMethod.push(Using('NoSynchronizationContext', '')); - - - responseMethod.add(function* () { - const skip = Local('_returnNow', `${System.Threading.Tasks.Task(dotnet.Bool).declaration}.FromResult(${dotnet.False})`); - yield skip.declarationStatement; - yield `${overrideResponseMethod.invoke(...parameters, `ref ${skip.value}`)};`; - yield `// if ${override} has returned true, then return right away.`; - yield If(And(IsNotNull(skip), `await ${skip}`), Return()); - - if (each.details.csharp.isErrorResponse) { - // this should write an error to the error channel. - yield `// Error Response : ${each.responseCode}`; - - - const unexpected = function* () { - yield '// Unrecognized Response. Create an error record based on what we have.'; - const ex = (each.details.csharp.responseType) ? - Local('ex', `new ${ClientRuntime.name}.RestException<${each.details.csharp.responseType}>(responseMessage, await response)`) : - Local('ex', `new ${ClientRuntime.name}.RestException(responseMessage)`); - - yield ex.declarationStatement; - - yield `WriteError( new global::System.Management.Automation.ErrorRecord(${ex.value}, ${ex.value}.Code, global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ex.value}.Message) { RecommendedAction = ${ex.value}.Action } -});`; - }; - if (each.schema) { - // the schema should be the error information. - // this supports both { error { message, code} } and { message, code} - - let props = getAllPublicVirtualProperties(each.schema.details.csharp.virtualProperties); - const errorProperty = values(props).first(p => p.property.details.csharp.name === 'error'); - let ep = ''; - if (errorProperty) { - props = getAllPublicVirtualProperties(errorProperty.property.schema.details.csharp.virtualProperties); - ep = `${errorProperty.name}?.`; - } - - const codeProp = props.find(p => p.name.toLowerCase().indexOf('code') > -1); // first property with 'code' - const messageProp = props.find(p => p.name.toLowerCase().indexOf('message') > -1); // first property with 'message' - const actionProp = props.find(p => p.name.toLowerCase().indexOf('action') > -1); // first property with 'action' - - if (codeProp && messageProp) { - const lcode = new LocalVariable('code', dotnet.Var, { initializer: `(await response)?.${ep}${codeProp.name}` }); - const lmessage = new LocalVariable('message', dotnet.Var, { initializer: `(await response)?.${ep}${messageProp.name}` }); - const laction = actionProp ? new LocalVariable('action', dotnet.Var, { initializer: `(await response)?.${ep}${actionProp.name} ?? ${System.String.Empty}` }) : undefined; - yield lcode; - yield lmessage; - yield laction; - - yield If(Or(IsNull(lcode), (IsNull(lmessage))), unexpected); - yield Else(`WriteError( new global::System.Management.Automation.ErrorRecord(new global::System.Exception($"[{${lcode}}] : {${lmessage}}"), ${lcode}?.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${lmessage}) { RecommendedAction = ${laction || System.String.Empty} } -});` - - ); - return; - } else { - yield unexpected; - return; - } - } else { - yield unexpected; - return; - } - } - - yield `// ${each.details.csharp.name} - response for ${each.responseCode} / ${values(each.mimeTypes).join('/')}`; - if (each.schema) { - const schema = each.schema; - - if (apiCall.details.csharp.pageable) { - const pageable = apiCall.details.csharp.pageable; - yield '// response should be returning an array of some kind. +Pageable'; - yield `// ${pageable.responseType} / ${pageable.itemName || ''} / ${pageable.nextLinkName || ''}`; - switch (pageable.responseType) { - // the result is (or works like a x-ms-pageable) - case 'pageable': - case 'nested-array': { - const valueProperty = schema.properties[pageable.itemName]; - const nextLinkProperty = schema.properties[pageable.nextLinkName]; - if (valueProperty && nextLinkProperty) { - // it's pageable! - const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('await response') }); - yield result.declarationStatement; - // write out the current contents - const vp = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - if (vp) { - yield `WriteObject(${result.value}.${vp.name},true);`; - } - const nl = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, nextLinkProperty.serializedName); - if (nl) { - const nextLinkName = `${result.value}.${nl.name}`; - yield (If(`${nextLinkName} != null`, - If('responseMessage.RequestMessage is System.Net.Http.HttpRequestMessage requestMessage ', function* () { - yield `requestMessage = requestMessage.Clone(new global::System.Uri( ${nextLinkName} ),${ClientRuntime.Method.Get} );`; - yield $this.eventListener.signal(Events.FollowingNextLink); - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}_Call`, ...[toExpression('requestMessage'), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - }) - )); - } - return; - } else if (valueProperty) { - // it's just a nested array - const p = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - if (p) { - yield `WriteObject((await response).${p.name}, true);`; - } - return; - } - } - break; - - // it's just an array, - case 'array': - // just write-object(enumerate) with the output - yield 'WriteObject(await response, true);'; - return; - } - // ok, let's see if the response type - } - const props = getAllPublicVirtualProperties(schema.details.csharp.virtualProperties); - const outValue = (length(props) === 1) ? `(await response).${props[0].name}` : '(await response)'; - - - // we expect to get back some data from this call. - - const rType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(schema, true, $this.state); - yield `// (await response) // should be ${rType.declaration}`; - if ($this.hasStreamOutput && $this.outFileParameter) { - const outfile = $this.outFileParameter; - const provider = Local('provider'); - provider.initializer = undefined; - const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(${outfile.value}, out ${provider.declarationExpression})`); - yield paths.declarationStatement; - yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid output path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); - yield If(`${paths.value}.Count > 1`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple output paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); - - if (rType.declaration === System.IO.Stream.declaration) { - // this is a stream output. write to outfile - const stream = Local('stream', 'await response'); - yield Using(stream.declarationExpression, function* () { - const fileStream = Local('fileStream', `global::System.IO.File.OpenWrite(${paths.value}[0])`); - yield Using(fileStream.declarationExpression, `await ${stream.value}.CopyToAsync(${fileStream.value});`); - }); - } else { - // assuming byte array output (via outValue) - yield `global::System.IO.File.WriteAllBytes(${paths.value}[0],${outValue});`; - } - - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { - // no return type. Let's just return ... true? - yield 'WriteObject(true);'; - }); - return; - } - - // let's just return the result object (or unwrapped result object) - yield `WriteObject(${outValue});`; - return; - } - - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { - // no return type. Let's just return ... true? - yield 'WriteObject(true);'; - }); - }); - $this.add(responseMethod); - } - - yield Try(function* () { - // make the call. - - const actualCall = function* () { - yield $this.eventListener.signal(Events.CmdletBeforeAPICall); - const idOpParams = operationParameters.filter(each => !each.isPathParam); - const idschema = values($this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - - - if ($this.isViaIdentity) { - const identityFromPathParams = function* () { - yield '// try to call with PATH parameters from Input Object'; - - if (idschema) { - const allVPs = getAllPublicVirtualProperties(idschema.details.csharp.virtualProperties); - const props = [...values(idschema.properties)]; - - const idOpParams = operationParameters.map(each => { - const pascalName = pascalCase(`${each.name}`); - - if (!each.isPathParam) { - return { - name: undefined, - value: valueOf(each.expression) - }; - } - const match = props.find(p => pascalCase(p.serializedName) === pascalName); - if (match) { - - const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType; - // match up vp name - const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName); - if (vp) { - return { - name: `InputObject.${vp.name}`, - value: `InputObject.${vp.name} ?? ${defaultOfType}` - }; - } - // fall back! - - console.error(`Unable to match identity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalCase(match.details.csharp.name)}').`); - return { - name: `InputObject.${pascalCase(match.details.csharp.name)}`, - value: `InputObject.${pascalCase(match.details.csharp.name)} ?? ${defaultOfType}` - }; - } - console.error(`Unable to match idenity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalName}')`); - return { - name: `InputObject.${pascalName}`, - value: `InputObject.${pascalName}` - }; - }); - for (const opParam of idOpParams) { - if (opParam.name) { - yield If(IsNull(opParam.name), `ThrowTerminatingError( new ${ErrorRecord}(new global::System.Exception("InputObject has null value for ${opParam.name}"),string.Empty, ${ErrorCategory('InvalidArgument')}, InputObject) );`); - } - } - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...idOpParams.map(each => toExpression(each.value)), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - - } - }; - - if (idschema && values(idschema.properties).first(each => each.details.csharp.uid === 'universal-parameter:resource identity')) { - yield If('InputObject?.Id != null', `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}ViaIdentity`, ...[toExpression('InputObject.Id'), ...idOpParams.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`); - yield Else(identityFromPathParams); - } else { - yield identityFromPathParams; - } - } else { - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...operationParameters.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - } - yield $this.eventListener.signal(Events.CmdletAfterAPICall); - }; - - if ($this.state.project.azure && operationParameters.find(each => each.expression && each.expression.value === 'SubscriptionId') && $this.operation.details.csharp.verb.toLowerCase() === 'get') { - yield 'foreach( var SubscriptionId in this.SubscriptionId )'; - yield BlockStatement(actualCall); - } else { - yield actualCall; - } - }); - const ure = new Parameter('urexception', { declaration: `${ClientRuntime.fullName}.UndeclaredResponseException` }); - yield Catch(ure, function* () { - yield `WriteError(new global::System.Management.Automation.ErrorRecord(${ure.value}, ${ure.value}.StatusCode.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(',')}}) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ure.value}.Message) { RecommendedAction = ${ure.value}.Action } -});`; - }); - yield Finally(function* () { - yield $this.eventListener.signalNoCheck(Events.CmdletProcessRecordAsyncEnd); - }); - }); - } - - private implementSerialization(operation: command.CommandOperation) { - const $this = this; - // clone - if (operation.asjob) { - const clone = this.add(new Method('Clone', this, { - description: 'Creates a duplicate instance of this cmdlet (via JSON serialization).', - returnsDescription: `a duplicate instance of ${this.name}`, - })); - - clone.add(function* () { - const i = new LocalVariable('clone', dotnet.Var, { - initializer: $this.new() - }); - yield i.declarationStatement; - - if ($this.state.project.azure) { - for (const f of [$this.correlationId, $this.processRecordId, $this.defaultProfile]) { - yield `${i.value}.${f} = this.${f};`; - } - } - for (const f of [$this.invocationInfo, 'Proxy', 'Pipeline', 'AsJob', 'Break', 'ProxyCredential', 'ProxyUseDefaultCredentials', 'HttpPipelinePrepend', 'HttpPipelineAppend',]) { - yield `${i.value}.${f} = this.${f};`; - } - - for (const f of $this.thingsToSerialize) { - yield `${i.value}.${f} = this.${f};`; - } - - // _name = this._name, - //_parametersBody = this._parametersBody, - //_resourceGroupName = this._resourceGroupName, - //_subscriptionId = this._subscriptionId, - - yield Return(i); - }); - } - } - - private implementConstructors() { - // default constructor - this.add(new Constructor(this, { description: `Intializes a new instance of the cmdlet class.` })); - } - - private implementIEventListener() { - const $this = this; - const cts = this.add(new Field('_cancellationTokenSource', System.Threading.CancellationTokenSource, { - access: Access.Private, - initialValue: new LiteralExpression(`new ${System.Threading.CancellationTokenSource.declaration}()`), - description: `The for this operation.` - })); - this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Token`, System.Threading.CancellationToken, new LiteralExpression(`${cts.value}.Token`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation token.' })); - this.cancellationToken = toExpression(`((${ClientRuntime.IEventListener})this).Token`); - this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Cancel`, System.Action(), new LiteralExpression(`${cts.value}.Cancel`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation delegate. Stops the cmdlet when called.' })); - - const id = new Parameter('id', dotnet.String, { description: 'The message id' }); - const token = new Parameter('token', System.Threading.CancellationToken, { description: 'The message cancellation token. When this call is cancelled, this should be true' }); - const messageData = new Parameter('messageData', System.Func(ClientRuntime.EventData), { description: 'Detailed message data for the message event.' }); - const signalMethod = this.add(new Method(`${ClientRuntime.IEventListener}.Signal`, System.Threading.Tasks.Task(), { - async: Modifier.Async, - parameters: [id, token, messageData], - access: Access.Default, - description: 'Handles/Dispatches events during the call to the REST service.', - returnsDescription: `A that will be complete when handling of the message is completed.` - })); - signalMethod.push(Using('NoSynchronizationContext', '')); - - signalMethod.add(function* () { - yield If(`${token.value}.IsCancellationRequested`, Return()); - - // if the - - const sw = Switch(id, [ - TerminalCase(Events.Verbose.value, function* () { - yield `WriteVerbose($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - - TerminalCase(Events.Warning.value, function* () { - yield `WriteWarning($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - TerminalCase(Events.Information.value, function* () { - if ($this.operation.asjob) { - yield '// When an operation supports asjob, Information messages must go thru verbose.'; - yield `WriteVerbose($"INFORMATION: {(messageData().Message ?? ${System.String.Empty})}");`; - } - else { - const data = new LocalVariable('data', dotnet.Var, { initializer: new LiteralExpression(`${messageData.use}()`) }); - yield data.declarationStatement; - yield 'WriteInformation(data, new[] { data.Message });'; - } - yield Return(); - - }), - TerminalCase(Events.Debug.value, function* () { - yield `WriteDebug($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - TerminalCase(Events.Error.value, function* () { - yield 'WriteError(new global::System.Management.Automation.ErrorRecord( new global::System.Exception(messageData().Message), string.Empty, global::System.Management.Automation.ErrorCategory.NotSpecified, null ) );'; - yield Return(); - }), - ]); - - if ($this.operation.asjob) { - // if we support -AsJob, we support -NoWait - sw.add(Case(Events.DelayBeforePolling.value, function* () { - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("NoWait")', function* () { - yield 'var data = messageData();'; - yield 'if (data.ResponseMessage is System.Net.Http.HttpResponseMessage response)'; - yield '{'; - yield ' var asyncOperation = response.GetFirstHeader(@"Azure-AsyncOperation");'; - yield ' var location = response.GetFirstHeader(@"Location");'; - yield ' var uri = global::System.String.IsNullOrEmpty(asyncOperation) ? global::System.String.IsNullOrEmpty(location) ? response.RequestMessage.RequestUri.AbsoluteUri : location : asyncOperation;'; - yield ` WriteObject(new ${ClientRuntime}.PowerShell.AsyncOperationResponse { Target = uri });`; - - yield ' // do nothing more. '; - yield ' data.Cancel();'; - yield ' return;'; - yield '}'; - }); - })); - } - - // the whole switch statement - yield sw; - - if ($this.state.project.azure) { - // in azure mode, we signal the AzAccount module with every event that makes it here. - yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`; - yield If(`${token.value}.IsCancellationRequested`, Return()); - } else { - // In Non-Azure Modes, emit the Signal method without coorelation and processrecordid - yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`; - yield If(`${token.value}.IsCancellationRequested`, Return()); - } - yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`; - // any handling of the signal on our side... - }); - } - - private addPowershellParameters(operation: command.CommandOperation) { - const vps = operation.details.csharp.virtualParameters || { - body: [], - operation: [], - }; - - for (const parameter of values(operation.parameters)) { - // these are the parameters that this command expects - const td = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema, true, this.state); - - if (parameter.details.csharp.constantValue) { - // this parameter has a constant value -- SKIP IT - continue; - } - - if (parameter.details.csharp.fromHost) { - // the parameter is expected to be gotten from the host.(ie, Az.Accounts) - - const hostParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { - metadata: { - parameterDefinition: parameter.details.csharp.httpParameter - }, - description: parameter.details.csharp.description, - })); - this.thingsToSerialize.push(hostParameter); - // in the BeginProcessing, we should tell it to go get the value for this property from the common module - this.$('BeginProcessing').add(hostParameter.assignPrivate(new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.GetParameter(this.MyInvocation, ${this.correlationId.value}, "${parameter.name}") as string`))); - continue; - } - const $this = this; - - if (parameter.details.csharp.apiversion) { - // Api-version parameters for azure are a custom implementation - this.add(new Property(parameter.details.csharp.name, td, { - getAccess: Access.Internal, - setAccess: Access.Private, - metadata: { - parameterDefinition: parameter.details.csharp.httpParameter - }, - description: parameter.details.csharp.description, - *get() { - const metadata = operation.extensions['x-ms-metadata']; - const profiles = >metadata.profiles || new Dictionary(); - - yield Switch(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Profile`, function* () { - for (const { key: profileName, value: apiVersion } of items(profiles)) { - yield TerminalCase(`"${profileName}"`, Return(`"${apiVersion}"`)); - } - yield TerminalDefaultCase(Return(`"${metadata.apiVersions[0]}"`)); - }); - } - })); - continue; - } - - if (this.dropBodyParameter && parameter.details.csharp.isBodyParameter) { - // we're supposed to use parameters for the body parameter instead of a big object - const expandedBodyParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { - description: parameter.details.csharp.description, - - initializer: (parameter.schema.type === JsonType.Array) ? 'null' : `new ${parameter.schema.details.csharp.fullname}()`, - setAccess: Access.Private, - getAccess: Access.Private, - })); - this.thingsToSerialize.push(expandedBodyParameter); - - for (const vParam of vps.body) { - const vSchema = vParam.schema; - const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); - - // we need to know if the actual underlying property is actually nullable. - const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, (vParam.origin).property.details.csharp.required, this.state).isNullable; - - const cmdletParameter = new Property(vParam.name, propertyType, { - get: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ - // get: toExpression(`null == ${expandedBodyParameter.value}.${vParam.origin.name} ? ${propertyType.defaultOfType} : (${propertyType.declaration}) ${expandedBodyParameter.value}.${vParam.origin.name}`), - set: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), - new: PropertiesRequiringNew.has(vParam.name) ? Modifier.New : Modifier.None - }); - - if (vParam.schema.details.csharp.byReference) { - // this parameter's schema is marked as 'by-reference' which means we should - // tag it with an ExportAs attribute for the I*Reference type. - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.details.csharp.referenceInterface})`] })); - } - - if (vParam.schema.type === JsonType.Array) { - if (vParam.schema.items && vParam.schema.items.details.csharp.byReference) { - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.items.details.csharp.referenceInterface}[])`] })); - } - cmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); - } - - if (vSchema.additionalProperties) { - // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // if it's a standalone dictionary, we can just use hashtable instead - if (length(vSchema.properties) === 0) { - // it's a pure dictionary - // add an attribute for changing the exported type. - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - } else { - // it's a hybrid. We need to add an additional property that puts its items into the target container - - } - - } - - const desc = (vParam.description || '.').replace(/[\r?\n]/gm, ''); - cmdletParameter.description = desc; - - // check if this parameter is a byte array, which would indicate that it should really be a file input - if (cmdletParameter.type.declaration === dotnet.Binary.declaration) { - // set the generated parameter to internal - cmdletParameter.setAccess = Access.Internal; - cmdletParameter.getAccess = Access.Internal; - - // create a InputFileXXX for the parameter - const ifname = vParam.name.toLowerCase() === 'value' ? 'InputFile' : pascalCase([vParam.name, 'Input', 'File']); - - const inputFileParameter = new Property(ifname, dotnet.String, { - // get: toExpression(`${expandedBodyParameter.value}.${vParam.origin.name}${vParam.required ? '' : ` ?? ${propertyType.defaultOfType}`}`), - set: function* () { - const provider = Local('provider'); - provider.initializer = undefined; - const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(value, out ${provider.declarationExpression})`); - yield paths.declarationStatement; - yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid input path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); - yield If(`${paths.value}.Count > 1`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple input paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); - yield cmdletParameter.assign(`global::System.IO.File.ReadAllBytes(${paths.value}[0])`); - }, - description: `Input File for ${cmdletParameter.name} (${escapeString(desc)})` - }); - - inputFileParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "Input File for ${cmdletParameter.name} (${escapeString(desc || '.')})"`)] })); - inputFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - - $this.add(inputFileParameter); - } else { - cmdletParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(desc || '.')}"`)] })); - cmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - addInfoAttribute(cmdletParameter, propertyType, !!vParam.required, false, desc, (vParam.origin).property.serializedName); - addCompleterInfo(cmdletParameter, vParam); - addDefaultInfo(cmdletParameter, vParam); - } - - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; - if (isEnum || hasEnum) { - cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); - } - // add aliases if there is any - if (length(vParam.alias) > 0) { - cmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); - } - - this.add(cmdletParameter); - } - - if (parameter.schema.additionalProperties) { - // if there is an additional properties on this type - // add a hashtable parameter for additionalProperties - let apPropName = ''; - const options = ['AdditionalProperties', 'MoreProperties', 'ExtendedProperties', 'Properties']; - for (const n of options) { - if (this.properties.find(each => each.name === n)) { - continue; - } - apPropName = n; - break; - } - - this.apProp = this.add(new Property(apPropName, System.Collections.Hashtable)); - this.apProp.add(new Attribute(ParameterAttribute, { - parameters: ['Mandatory = false', 'HelpMessage = "Additional Parameters"'] - })); - this.bodyParameterInfo = { - type: { - declaration: parameter.schema.details.csharp.fullname - }, - valueType: parameter.schema.additionalProperties === true ? System.Object : this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema.additionalProperties, true, this.state) - }; - } - - this.bodyParameter = expandedBodyParameter; - continue; - } - } - - if (this.isViaIdentity) { - // add in the pipeline parameter for the identity - - const idschema = values(this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state); - const idParam = this.add(new BackedProperty('InputObject', idtd, { - description: 'Identity Parameter' - })); - const parameters = [new LiteralExpression('Mandatory = true'), new LiteralExpression('HelpMessage = "Identity Parameter"'), new LiteralExpression('ValueFromPipeline = true')]; - idParam.add(new Attribute(ParameterAttribute, { parameters })); - idParam.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Path`] })); - } - for (const vParam of values(vps.operation)) { - const vSchema = vParam.schema; - const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); - - - const origin = vParam.origin; - - const regularCmdletParameter = (this.state.project.azure && vParam.name === 'SubscriptionId' && operation.details.csharp.verb.toLowerCase() === 'get') ? - - // special case for subscription id - this.add(new BackedProperty(vParam.name, dotnet.StringArray, { - metadata: { - parameterDefinition: origin.details.csharp.httpParameter - }, - description: vParam.description - })) : - - // everything else - this.add(new BackedProperty(vParam.name, propertyType, { - metadata: { - parameterDefinition: origin.details.csharp.httpParameter - }, - description: vParam.description - })); - - if (vSchema.additionalProperties) { - // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // if it's a standalone dictionary, we can just use hashtable instead - if (length(vSchema.properties) === 0) { - // it's a pure dictionary - // change the property type to hashtable. - // add an attribute to change the exported type. - regularCmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - } else { - // it's a hybrid. We need to add an additional property that puts its items into the target container - - } - - } - - this.thingsToSerialize.push(regularCmdletParameter); - - const parameters = [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(vParam.description) || '.'}"`)]; - if (origin.details.csharp.isBodyParameter) { - parameters.push(new LiteralExpression('ValueFromPipeline = true')); - this.bodyParameter = regularCmdletParameter; - } - regularCmdletParameter.add(new Attribute(ParameterAttribute, { parameters })); - if (vParam.schema.type === JsonType.Array) { - regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); - } - - addInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); - addCompleterInfo(regularCmdletParameter, vParam); - addDefaultInfo(regularCmdletParameter, vParam); - - // add aliases if there is any - if (length(vParam.alias) > 0) { - regularCmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); - } - - const httpParam = origin.details.csharp.httpParameter; - const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; - - const cat = values(operation.callGraph[0].parameters). - where(each => !(each.details.csharp.constantValue)). - first(each => each.details.csharp.uid === uid); - - if (cat) { - regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase(cat.in)}`] })); - } - - - if (origin.details.csharp.completer) { - // add the completer to this class and tag this parameter with the completer. - // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); - } - - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; - if (isEnum || hasEnum) { - regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); - } - } - const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); - if (ifmatch) { - //no sure why there is an empty block - } - - } - - private addClassAttributes(operation: command.CommandOperation, variantName: string) { - const cmdletAttribParams: Array = [ - category[operation.details.csharp.verb] ? verbEnum(category[operation.details.csharp.verb], operation.details.csharp.verb) : `"${operation.details.csharp.verb}"`, - new StringExpression(variantName) - ]; - - if (this.isWritableCmdlet(operation)) { - cmdletAttribParams.push('SupportsShouldProcess = true'); - } - - if (operation.details.csharp.hidden) { - this.add(new Attribute(InternalExportAttribute)); - const noun = `${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; - const cmdletName = `${operation.details.csharp.verb}-${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; - this.state.message({ Channel: Channel.Debug, Text: `[DIRECTIVE] Applied 'hidden' directive to ${cmdletName}. Added attribute ${InternalExportAttribute.declaration} to cmdlet.` }); - } - - this.add(new Attribute(CmdletAttribute, { parameters: cmdletAttribParams })); - - // add alias attribute if there is any aliases for this cmdlet - if (length(operation.details.csharp.alias) > 0) { - this.add(new Attribute(Alias, { parameters: operation.details.csharp.alias.map((x: string) => '"' + x + '"') })); - } - - let shouldAddPassThru = false; - // set to hold the output types - const outputTypes = new Set(); - for (const httpOperation of values(operation.callGraph)) { - const pageableInfo = httpOperation.details.csharp.pageable; - for (const item of items(httpOperation.responses).where(each => each.key !== 'default')) { - for (const schema of values(item.value).selectNonNullable(each => each.schema)) { - const props = getAllProperties(schema); - - // does the target type just wrap a single output? - const resultSchema = length(props) !== 1 ? schema : props[0].schema; - - // make sure return type for boolean stays boolean! - if (resultSchema.type === JsonType.Boolean) { - outputTypes.add(`typeof(${dotnet.Bool})`); - } else { - const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state); - - if (typeDeclaration.declaration === System.IO.Stream.declaration || typeDeclaration.declaration === dotnet.Binary.declaration) { - // if this is a stream, skip the output type. - this.hasStreamOutput = true; - shouldAddPassThru = true; - outputTypes.add(`typeof(${dotnet.Bool})`); - } else { - - let type = ''; - if (typeDeclaration instanceof ArrayOf) { - type = typeDeclaration.elementTypeDeclaration; - } else if (!(typeDeclaration.schema instanceof NewSchema) && pageableInfo && pageableInfo.responseType === 'pageable') { - if (typeDeclaration === undefined || typeDeclaration.schema.properties[pageableInfo.itemName] === undefined) { - throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); - } - const nestedSchema = typeDeclaration.schema.properties[pageableInfo.itemName].schema; - const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); - type = (nestedTypeDeclaration).elementTypeDeclaration; - } else { - type = typeDeclaration.declaration; - } - // check if this is a stream output - if (type) { - outputTypes.add(`typeof(${type})`); - } - } - } - } - } - } - - // if any response does not return, - // the cmdlet should have a PassThru parameter - shouldAddPassThru = shouldAddPassThru || values(operation.callGraph) - .selectMany(httpOperation => items(httpOperation.responses)) - .selectMany(responsesItem => responsesItem.value) - .any(value => value.schema === undefined); - if (outputTypes.size === 0) { - outputTypes.add(`typeof(${dotnet.Bool})`); - } - - this.add(new Attribute(OutputTypeAttribute, { parameters: [...outputTypes] })); - if (shouldAddPassThru) { - const passThru = this.add(new Property('PassThru', SwitchParameter, { description: 'When specified, forces the cmdlet return a \'bool\' given that there isn\'t a return type by default.' })); - passThru.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Returns true when the command succeeds"'] })); - passThru.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - } - - this.add(new Attribute(DescriptionAttribute, { parameters: [new StringExpression(this.description)] })); - this.add(new Attribute(GeneratedAttribute)); - if (operation.extensions && operation.extensions['x-ms-metadata'] && operation.extensions['x-ms-metadata'].profiles) { - const profileNames = Object.keys(operation.extensions && operation.extensions['x-ms-metadata'].profiles); - // wrap profile names - profileNames.forEach((element, index) => { - profileNames[index] = `"${element}"`; - }); - - this.add(new Attribute(ProfileAttribute, { parameters: [...profileNames] })); - } - } -} - -export class NewCmdletClass extends Class { - private cancellationToken!: Expression; - public state: NewState; - private readonly eventListener: EventListener; - private readonly dropBodyParameter: boolean; - private invocationInfo!: Property; - correlationId!: Field; - processRecordId!: Field; - defaultProfile!: Property; - private readonly thingsToSerialize: Array; - private bodyParameter?: Variable; - private bodyParameterInfo?: { type: TypeDeclaration; valueType: TypeDeclaration }; - private apProp?: Property; private operation: CommandOperation; private debugMode?: boolean; private variantName: string; @@ -1517,7 +307,7 @@ export class NewCmdletClass extends Class { private hasStreamOutput: boolean; private outFileParameter?: Property; - constructor(namespace: Namespace, operation: CommandOperation, state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, operation: CommandOperation, state: State, objectInitializer?: DeepPartial) { // generate the 'variant' part of the name const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; @@ -2476,10 +1266,10 @@ export class NewCmdletClass extends Class { addDefaultInfo(cmdletParameter, vParam); } - const isEnum = propertyType instanceof NewEnumImplementation;; - const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const isEnum = propertyType instanceof EnumImplementation;; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { - cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } // add aliases if there is any if (length(vParam.alias) > 0) { @@ -2621,10 +1411,10 @@ export class NewCmdletClass extends Class { // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); } - const isEnum = propertyType instanceof NewEnumImplementation; - const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const isEnum = propertyType instanceof EnumImplementation; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { - regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } } const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); @@ -2688,7 +1478,7 @@ export class NewCmdletClass extends Class { } else { let type = ''; - if (typeDeclaration instanceof NewArrayOf) { + if (typeDeclaration instanceof ArrayOf) { type = typeDeclaration.elementTypeDeclaration; } else if (pageableInfo && pageableInfo.responseType === 'pageable') { if (typeDeclaration === undefined || (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName) === undefined) { @@ -2698,7 +1488,7 @@ export class NewCmdletClass extends Class { } const nestedSchema = (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName)?.schema; const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); - type = (nestedTypeDeclaration).elementTypeDeclaration; + type = (nestedTypeDeclaration).elementTypeDeclaration; } else { type = typeDeclaration.declaration; } diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index 0be43177733..52a2c80d80c 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -5,8 +5,8 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; -import { CmdletClass, NewCmdletClass } from './class'; +import { State } from '../internal/state'; +import { CmdletClass } from './class'; import { DeepPartial } from '@azure-tools/codegen'; export class CmdletNamespace extends Namespace { @@ -33,30 +33,4 @@ export class CmdletNamespace extends Namespace { } return this; } -} - -export class NewCmdletNamespace extends Namespace { - inputModels = new Array(); - public get outputFolder(): string { - return this.state.project.cmdletFolder; - } - - constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { - super('Cmdlets', parent); - this.apply(objectInitializer); - } - - async init() { - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // generate cmdlet classes on top of the SDK - for (const { key: index, value: operation } of items(this.state.model.commands.operations)) { - // skip ViaIdentity for set-* cmdlets. - if (this.state.project.azure && operation.details.csharp.verb === 'Set' && operation.details.csharp.name.indexOf('ViaIdentity') > 0) { - continue; - } - this.addClass(await new NewCmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); - } - return this; - } } \ No newline at end of file diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index 63d3ff41670..d704c7b2378 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -5,7 +5,7 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { EnumDetails } from '@azure-tools/codemodel-v3'; import { If, Parameter, Method, Namespace, System, Struct, Attribute, Class, dotnet, LambdaMethod, LiteralExpression, Modifier } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../internal/state'; +import { State } from '../internal/state'; import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, TypeConverterAttribute, PSTypeConverter } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -20,115 +20,6 @@ export class EnumNamespace extends Namespace { constructor(parent: Namespace, public state: State, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); - - const enumInfos = values(state.model.schemas) - .where(each => each.details.csharp.enum !== undefined && !each.details.csharp.skip) - .select(each => ({ details: each.details.csharp.enum, description: each.details.csharp.description })) - .toArray(); - - const done = new Set(); - - - for (const enumInfo of enumInfos) { - if (done.has(enumInfo.details.name)) { - continue; - } - - done.add(enumInfo.details.name); - - if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) { - continue; - } - - // generate a typeconverter for the enum class too. - - const enumValues = values(enumInfo.details.values).select(v => v.value).toArray(); - const enumClass = new Struct(this, enumInfo.details.name, undefined, { - interfaces: [IArgumentCompleter], - partial: true, - description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`, - fileName: `${enumInfo.details.name}.Completer` - }); - const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' }); - const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' }); - const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' }); - const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' }); - const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' }); - const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters]; - - enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () { - for (const enumValue of enumValues) { - yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`, - `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`); - } - }); - - - // generate a typeconverter for the enum class too. - - const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, { - interfaces: [PSTypeConverter], - partial: true, - description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`, - fileName: `${enumInfo.details.name}.TypeConverter` - }); - - converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - - converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - - converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })); - - converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], description: 'NotImplemented -- this will return null', - returnsDescription: 'will always return null.' - })); - - enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - - } - } -} -export class NewEnumNamespace extends Namespace { - public get outputFolder(): string { - return join(this.state.project.apiFolder, 'Support'); - } - - constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { - super('Support', parent); - this.apply(objectInitializer); //const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] const enumInfos = [...state.model.schemas.sealedChoices ?? []] .filter((choice) => !choice.language.csharp?.skip) diff --git a/powershell/generators/csproj.ts b/powershell/generators/csproj.ts index 0d14a60d7da..9f19683dbff 100644 --- a/powershell/generators/csproj.ts +++ b/powershell/generators/csproj.ts @@ -4,12 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Project } from '../internal/project'; -import { NewProject } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateCsproj(project: Project | NewProject) { +export async function generateCsproj(project: Project) { const release = project.azure ? ` true true MSSharedLibKey.snk diff --git a/powershell/generators/gitattributes.ts b/powershell/generators/gitattributes.ts index 764cdd68dd0..e3467fba6c4 100644 --- a/powershell/generators/gitattributes.ts +++ b/powershell/generators/gitattributes.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; -export async function generateGitAttributes(project: Project | NewProject) { +export async function generateGitAttributes(project: Project) { project.state.writeFile(project.gitAttributes, '* text=auto', undefined, 'source-file-other'); } \ No newline at end of file diff --git a/powershell/generators/gitignore.ts b/powershell/generators/gitignore.ts index 84764c3f372..f8e7cf3ee98 100644 --- a/powershell/generators/gitignore.ts +++ b/powershell/generators/gitignore.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; -export async function generateGitIgnore(project: Project | NewProject) { +export async function generateGitIgnore(project: Project) { project.state.writeFile(project.gitIgnore, `bin obj .vs diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index ac810323dae..7e593cedbe0 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateNuspec(project: Project | NewProject) { +export async function generateNuspec(project: Project) { const dependencies = project.azure ? ` diff --git a/powershell/generators/psm1.custom.ts b/powershell/generators/psm1.custom.ts index 61789f414ca..7977240814d 100644 --- a/powershell/generators/psm1.custom.ts +++ b/powershell/generators/psm1.custom.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; -export async function generatePsm1Custom(project: Project | NewProject) { +export async function generatePsm1Custom(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Custom) || ''); const dllPath = relative(project.customFolder, project.dll); const internalPath = relative(project.customFolder, project.psm1Internal); diff --git a/powershell/generators/psm1.internal.ts b/powershell/generators/psm1.internal.ts index d1e0a2e6127..76911b9c45a 100644 --- a/powershell/generators/psm1.internal.ts +++ b/powershell/generators/psm1.internal.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; import { getProfileExportScript } from './psm1'; -export async function generatePsm1Internal(project: Project | NewProject) { +export async function generatePsm1Internal(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Internal) || ''); const dllPath = relative(project.internalFolder, project.dll); psm1.prepend('Generated', ` diff --git a/powershell/generators/psm1.ts b/powershell/generators/psm1.ts index 78f1c22af67..82b0fa54ebb 100644 --- a/powershell/generators/psm1.ts +++ b/powershell/generators/psm1.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; @@ -40,7 +40,7 @@ export function getProfileExportScript(exportFolderScript: string, isAzure: bool `; } -export async function generatePsm1(project: Project | NewProject) { +export async function generatePsm1(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1) || ''); let azureInitialize = ''; if (project.azure) { diff --git a/powershell/generators/readme.ts b/powershell/generators/readme.ts index 384d87b1683..b8563b454f6 100644 --- a/powershell/generators/readme.ts +++ b/powershell/generators/readme.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { MdFile } from '../file-formats/md-file'; -export async function generateReadme(project: Project | NewProject) { +export async function generateReadme(project: Project) { const md = new MdFile(await project.state.readFile(project.readme) || ''); let azureInfo = ''; if (project.azure) { diff --git a/powershell/generators/script-cmdlet.ts b/powershell/generators/script-cmdlet.ts index ac1c25ee248..741a1292cbd 100644 --- a/powershell/generators/script-cmdlet.ts +++ b/powershell/generators/script-cmdlet.ts @@ -4,10 +4,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { serialize, indent, setIndentation, applyOverrides, pascalCase } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { State } from '../internal/state'; import { dotnet, System } from '@azure-tools/codegen-csharp'; import { PSScriptFile } from '../file-formats/psscript-file'; @@ -52,7 +51,7 @@ function getType(type: string) { return type; } -export async function generateScriptCmdlets(project: Project | NewProject) { +export async function generateScriptCmdlets(project: Project) { const commands = await project.state.getValue>('command', []); for (const command of values(commands)) { if (!command.action) { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 2b57a317d87..ca37f32a5a9 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,19 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewBoolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; -import { State, NewState } from './state'; +import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, Boolean, SchemaDefinitionResolver } from '../llcsharp/exports'; +import { State } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { EnumNamespace, NewEnumNamespace } from '../enums/namespace'; -import { ModelExtensionsNamespace, NewModelExtensionsNamespace } from '../models/model-extensions'; +import { EnumNamespace } from '../enums/namespace'; +import { ModelExtensionsNamespace } from '../models/model-extensions'; -import { ModuleNamespace, NewModuleNamespace } from '../module/module-namespace'; -import { CmdletNamespace, NewCmdletNamespace } from '../cmdlets/namespace'; +import { ModuleNamespace } from '../module/module-namespace'; +import { CmdletNamespace } from '../cmdlets/namespace'; import { Host } from '@azure-tools/autorest-extension-base'; -import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, } from '@azure-tools/codemodel-v3'; +import { codemodel, PropertyDetails, exportedModels as T } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { BooleanSchema, ChoiceSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -33,41 +33,17 @@ export interface Metadata { projectUri: string; } -export class PSSwitch extends Boolean { - get declaration(): string { - return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`; - } - -} - -export class PSSchemaResolver extends SchemaDefinitionResolver { - inResolve = false; - resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { - const before = this.inResolve; - try { - if (!this.inResolve) { - this.inResolve = true; - if (schema && schema.type === JsonType.Boolean) { - return new PSSwitch(schema, required); - } - } - return super.resolveTypeDeclaration(schema, required, state); - } finally { - this.inResolve = before; - } - } -} -export class NewPSSwitch extends NewBoolean { +export class NewPSSwitch extends Boolean { get declaration(): string { return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`; } } -export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { +export class PSSchemaResolver extends SchemaDefinitionResolver { inResolve = false; - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { const before = this.inResolve; try { if (!this.inResolve) { @@ -86,6 +62,7 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { } } + export class Project extends codeDomProject { public azure!: boolean; public license!: string; @@ -137,7 +114,7 @@ export class Project extends codeDomProject { public metadata!: Metadata; public state!: State; public helpLinkPrefix!: string; - get model() { return this.state.model; } + get model() { return this.state.model; } constructor(protected service: Host, objectInitializer?: DeepPartial) { super(); @@ -151,166 +128,6 @@ export class Project extends codeDomProject { this.schemaDefinitionResolver = new PSSchemaResolver(); - this.projectNamespace = this.state.model.details.csharp.namespace; - - - this.overrides = { - 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, - 'using Data;': '', - 'using Parser;': '', - 'using Converters;': '', - 'using Internal.Extensions;': '', - - 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, - 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, - 'Microsoft.Rest': `${this.projectNamespace}`, - }; - - // Values - this.moduleVersion = await this.state.getValue('module-version'); - this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || []; - this.accountsVersionMinimum = '1.8.1'; - this.helpLinkPrefix = await this.state.getValue('help-link-prefix'); - this.metadata = await this.state.getValue('metadata'); - this.license = await this.state.getValue('header-text', ''); - - // Flags - this.azure = this.model.details.default.isAzure; - - // Names - this.prefix = this.model.details.default.prefix; - this.serviceName = this.model.details.default.serviceName; - this.subjectPrefix = this.model.details.default.subjectPrefix; - this.moduleName = await this.state.getValue('module-name'); - this.dllName = await this.state.getValue('dll-name'); - - // Folders - this.baseFolder = await this.state.getValue('current-folder'); - this.moduleFolder = await this.state.getValue('module-folder'); - this.cmdletFolder = await this.state.getValue('cmdlet-folder'); - - this.customFolder = await this.state.getValue('custom-cmdlet-folder'); - this.utilsFolder = await this.state.getValue('utils-cmdlet-folder'); - this.internalFolder = await this.state.getValue('internal-cmdlet-folder'); - this.testFolder = await this.state.getValue('test-folder'); - this.runtimeFolder = await this.state.getValue('runtime-folder'); - this.apiFolder = await this.state.getValue('api-folder'); - - this.binFolder = await this.state.getValue('bin-folder'); - this.objFolder = await this.state.getValue('obj-folder'); - this.exportsFolder = await this.state.getValue('exports-folder'); - this.docsFolder = await this.state.getValue('docs-folder'); - this.dependencyModuleFolder = await this.state.getValue('dependency-module-folder'); - this.examplesFolder = await this.state.getValue('examples-folder'); - this.resourcesFolder = await this.state.getValue('resources-folder'); - - // File paths - this.csproj = await this.state.getValue('csproj'); - this.dll = await this.state.getValue('dll'); - this.psd1 = await this.state.getValue('psd1'); - this.psm1 = await this.state.getValue('psm1'); - this.psm1Custom = await this.state.getValue('psm1-custom'); - this.psm1Internal = await this.state.getValue('psm1-internal'); - this.formatPs1xml = await this.state.getValue('format-ps1xml'); - this.nuspec = await this.state.getValue('nuspec'); - this.gitIgnore = `${this.baseFolder}/.gitignore`; - this.gitAttributes = `${this.baseFolder}/.gitattributes`; - this.readme = `${this.baseFolder}/readme.md`; - - // add project namespace - this.serviceNamespace = new ModuleNamespace(this.state); - this.serviceNamespace.header = this.license; - this.addNamespace(this.serviceNamespace); - - this.supportNamespace = new EnumNamespace(this.serviceNamespace, this.state); - this.supportNamespace.header = this.license; - this.addNamespace(this.supportNamespace); - - this.modelsExtensions = new ModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); - this.modelsExtensions.header = this.license; - this.addNamespace(this.modelsExtensions); - - // add cmdlet namespace - this.cmdlets = await new CmdletNamespace(this.serviceNamespace, this.state).init(); - this.cmdlets.header = this.license; - this.addNamespace(this.cmdlets); - - - // abort now if we have any errors. - this.state.checkpoint(); - return this; - } -} - -export class NewProject extends codeDomProject { - public azure!: boolean; - public license!: string; - public cmdletFolder!: string; - - public customFolder!: string; - public utilsFolder!: string; - public internalFolder!: string; - public testFolder!: string; - public runtimeFolder!: string; - public binFolder!: string; - public objFolder!: string; - public exportsFolder!: string; - public docsFolder!: string; - public examplesFolder!: string; - public resourcesFolder!: string; - public serviceName!: string; - public moduleName!: string; - public csproj!: string; - public nuspec!: string; - public gitIgnore!: string; - public gitAttributes!: string; - public readme!: string; - public dllName!: string; - public dll!: string; - public psd1!: string; - public psm1!: string; - public psm1Custom!: string; - public psm1Internal!: string; - public formatPs1xml!: string; - public apiFolder!: string; - public baseFolder!: string; - public moduleFolder!: string; - public schemaDefinitionResolver!: NewSchemaDefinitionResolver; - public moduleVersion!: string; - public profiles!: Array; - - public prefix!: string; - public subjectPrefix!: string; - public projectNamespace!: string; - public overrides!: Dictionary; - public serviceNamespace!: NewModuleNamespace; - public supportNamespace!: NewEnumNamespace; - public cmdlets!: NewCmdletNamespace; - - public modelsExtensions!: NewModelExtensionsNamespace; - public accountsVersionMinimum!: string; - public dependencyModuleFolder!: string; - public metadata!: Metadata; - public state!: NewState; - public helpLinkPrefix!: string; - get model() { return this.state.model; } - - constructor(protected service: Host, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - - - public async init(): Promise { - await super.init(); - this.state = await new NewState(this.service).init(this); - - this.schemaDefinitionResolver = new NewPSSchemaResolver(); - this.projectNamespace = this.state.model.language.csharp?.namespace || ''; @@ -384,20 +201,20 @@ export class NewProject extends codeDomProject { this.readme = `${this.baseFolder}/readme.md`; // add project namespace - this.serviceNamespace = new NewModuleNamespace(this.state); + this.serviceNamespace = new ModuleNamespace(this.state); this.serviceNamespace.header = this.license; this.addNamespace(this.serviceNamespace); - this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); + this.supportNamespace = new EnumNamespace(this.serviceNamespace, this.state); this.supportNamespace.header = this.license; this.addNamespace(this.supportNamespace); - this.modelsExtensions = new NewModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); + this.modelsExtensions = new ModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); this.modelsExtensions.header = this.license; this.addNamespace(this.modelsExtensions); // add cmdlet namespace - this.cmdlets = await new NewCmdletNamespace(this.serviceNamespace, this.state).init(); + this.cmdlets = await new CmdletNamespace(this.serviceNamespace, this.state).init(); this.cmdlets.header = this.license; this.addNamespace(this.cmdlets); diff --git a/powershell/internal/state.ts b/powershell/internal/state.ts index 197c344362f..c5253f50958 100644 --- a/powershell/internal/state.ts +++ b/powershell/internal/state.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codemodel, ModelState } from '@azure-tools/codemodel-v3'; +import { codemodel } from '@azure-tools/codemodel-v3'; import { Host, JsonPath, Session } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from './project'; +import { Project } from './project'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; export interface GeneratorSettings { @@ -24,7 +24,7 @@ export interface GeneratorSettings { apiFolder: string; } -export class State extends ModelState { +export class State extends ModelState { project!: Project; public constructor(service: Host, objectInitializer?: DeepPartial) { @@ -39,29 +39,6 @@ export class State extends ModelState { return await super.init(project); } - path(...childPath: JsonPath) { - // const result = new State(this.service, this); - // result.currentPath = [...this.currentPath, ...childPath]; - // return result; - return this; - } -} - -export class NewState extends NewModelState { - project!: NewProject; - - public constructor(service: Host, objectInitializer?: DeepPartial) { - super(service); - this.apply(objectInitializer); - } - - async init(project?: NewProject) { - if (project) { - this.project = project; - } - return await super.init(project); - } - path(...childPath: JsonPath) { // const result = new State(this.service, this); // result.currentPath = [...this.currentPath, ...childPath]; diff --git a/powershell/llcsharp/enums/enum.ts b/powershell/llcsharp/enums/enum.ts index 8f4303e708c..c7de14f5ecc 100644 --- a/powershell/llcsharp/enums/enum.ts +++ b/powershell/llcsharp/enums/enum.ts @@ -20,178 +20,15 @@ import { Property } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Struct } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; -import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; +import { EnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema } from '@azure-tools/codemodel'; export class EnumClass extends Struct implements EnhancedTypeDeclaration { implementation: EnumImplementation; - get schema(): Schema { - return this.implementation.schema; - } - get convertObjectMethod() { - return this.implementation.convertObjectMethod; - } - - get defaultOfType() { - return toExpression('null /* enum value */'); - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.implementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.implementation.deserializeFromNode(mediaType, node, defaultValue); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.implementation.deserializeFromString(mediaType, content, defaultValue); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.implementation.deserializeFromResponse(mediaType, content, defaultValue); - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.implementation.serializeToNode(mediaType, value, serializedName, mode); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.implementation.serializeToContent(mediaType, value, mode); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.implementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.implementation.isXmlAttribute; - } - - get isNullable(): boolean { - return this.implementation.isNullable; - } - - get isRequired(): boolean { - return this.implementation.isRequired; - } - - constructor(schemaWithFeatures: EnumImplementation, state: State, objectInitializer?: DeepPartial) { - if (!schemaWithFeatures.schema.details.csharp.enum) { - throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.details.csharp.name}`); - } - - super(state.project.supportNamespace, schemaWithFeatures.schema.details.csharp.enum.name, undefined, { - interfaces: [new Interface(new Namespace('System'), 'IEquatable', { - genericParameters: [`${schemaWithFeatures.schema.details.csharp.enum.name}`] - })], - }); - this.description = schemaWithFeatures.schema.details.csharp.description; - this.implementation = schemaWithFeatures; - this.partial = true; - - this.apply(objectInitializer); - - // add known enum values - for (const evalue of schemaWithFeatures.schema.details.csharp.enum.values) { - this.addField(new Field(evalue.name, this, { initialValue: new StringExpression(evalue.value), static: Modifier.Static, description: evalue.description })); - } - - // add backingField - const backingField = this.add(new Property('_value', dotnet.String, { - getAccess: Access.Private, - setAccess: Access.Private, - description: `the value for an instance of the Enum.` - })); - - // add private constructor - const p = new Parameter('underlyingValue', dotnet.String, { description: 'the value to create an instance for.' }); - const ctor = this.addMethod(new Constructor(this, { - access: Access.Private, - parameters: [p], - description: `Creates an instance of the ` - })).add(`this.${backingField.value} = ${p.value};`); - - // add toString Method - this.addMethod(new Method('ToString', dotnet.String, { - override: Modifier.Override, - description: `Returns string representation for ${this.name}`, - returnsDescription: 'A string for this value.' - })).add(`return this.${backingField.value};`); - - // add Equals Method(thistype) - this.addMethod(new Method('Equals', dotnet.Bool, { - description: `Compares values of enum type ${this.name}`, - parameters: [new Parameter('e', this, { description: 'the value to compare against this instance.' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add(`return ${backingField.value}.Equals(e.${backingField.value});`); - - // add Equals Method(object) - this.addMethod(new Method('Equals', dotnet.Bool, { - override: Modifier.Override, - description: `Compares values of enum type ${this.name} (override for Object)`, - parameters: [new Parameter('obj', dotnet.Object, { description: 'the value to compare against this instance.' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add(`return obj is ${this.name} && Equals((${this.name})obj);`); - - // add implicit operator(string) - this.addMethod(new Operator(`implicit operator ${this.name}`, { - static: Modifier.Static, - description: `Implicit operator to convert string to ${this.name}`, - parameters: [new Parameter('value', dotnet.String, { description: `the value to convert to an instance of .` })] - })).add(`return new ${this.name}(value);`); - - // add static creation - this.addMethod(new Method('CreateFrom', dotnet.Object, { - static: Modifier.Static, - access: Access.Internal, - description: `Conversion from arbitrary object to ${this.name}`, - parameters: [new Parameter('value', dotnet.Object, { description: `the value to convert to an instance of .` })] - })).add(`return new ${this.name}(System.Convert.ToString(value));`); - - // add implicit operator(thistype) - this.addMethod(new Operator('implicit operator string', { - static: Modifier.Static, - description: `Implicit operator to convert ${this.name} to string`, - parameters: [new Parameter('e', this, { description: `the value to convert to an instance of .` })] - })).add(`return e.${backingField.value};`); - - // add operator == - this.addMethod(new Method('operator ==', dotnet.Bool, { - static: Modifier.Static, - description: `Overriding == operator for enum ${this.name}`, - parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add('return e2.Equals(e1);'); - - // add opeator != - this.addMethod(new Method('operator !=', dotnet.Bool, { - static: Modifier.Static, - description: `Overriding != operator for enum ${this.name}`, - parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], - returnsDescription: 'true if the two instances are not equal to the same value' - })).add('return !e2.Equals(e1);'); - - // add getHashCode - this.addMethod(new Method('GetHashCode', dotnet.Int, { - override: Modifier.Override, - description: `Returns hashCode for enum ${this.name}`, - returnsDescription: 'The hashCode of the value' - })).add(`return this.${backingField.value}.GetHashCode();`); - } - - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.implementation.validateValue(eventListener, property); - } - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.implementation.validatePresence(eventListener, property); - } -} - -export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { - implementation: NewEnumImplementation; get schema(): NewSchema { return this.implementation.schema; } @@ -241,7 +78,7 @@ export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { return this.implementation.isRequired; } - constructor(schemaWithFeatures: NewEnumImplementation, state: NewState, objectInitializer?: DeepPartial) { + constructor(schemaWithFeatures: EnumImplementation, state: State, objectInitializer?: DeepPartial) { if (!schemaWithFeatures.schema.language.csharp?.enum) { throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.language.csharp?.name}`); } diff --git a/powershell/llcsharp/enums/json-serializer.ts b/powershell/llcsharp/enums/json-serializer.ts deleted file mode 100644 index 991df60b157..00000000000 --- a/powershell/llcsharp/enums/json-serializer.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Modifier } from '@azure-tools/codegen-csharp'; -import { Class } from '@azure-tools/codegen-csharp'; -import { Method } from '@azure-tools/codegen-csharp'; - -import { items } from '@azure-tools/linq'; -import { dotnet } from '@azure-tools/codegen-csharp'; -import { Namespace } from '@azure-tools/codegen-csharp'; -import { Parameter } from '@azure-tools/codegen-csharp'; -import { ClientRuntime } from '../clientruntime'; -import { State } from '../generator'; -import { DeepPartial } from '@azure-tools/codegen'; - -export class JsonSerializerClass extends Class { - - constructor(namespace: Namespace, protected state: State, objectInitializer?: DeepPartial) { - super(namespace, 'JsonSerialization'); - this.apply(objectInitializer); - - this.partial = true; - this.isStatic = true; - - const tojson = this.addMethod(new Method('ToJson', ClientRuntime.JsonNode, { static: Modifier.Static })); - const objP = tojson.addParameter(new Parameter('obj', dotnet.ThisObject)); - const container = tojson.addParameter(new Parameter('container', ClientRuntime.JsonObject, { defaultInitializer: dotnet.Null })); - tojson.add('return null;'); - - const schemas = state.model.schemas; - - // iterate thru all the models - // each model should have a class and an interface. - // if the class has a discriminator value, tell the parent model that it has children - for (const { key: index, value: schema } of items(schemas)) { - const state = this.state.path('components', 'schemas', index); - if (schema.details.csharp && schema.details.csharp.classImplementation) { - // must be a class. - // const implData: CSharpSchemaDetails = schema.details.csharp; - } - - schema.details; - const x = state.project.modelsNamespace.resolveTypeDeclaration(schema, true, state); - } - } -} diff --git a/powershell/llcsharp/enums/namespace.ts b/powershell/llcsharp/enums/namespace.ts index e8a9ec52d42..90e9a014d64 100644 --- a/powershell/llcsharp/enums/namespace.ts +++ b/powershell/llcsharp/enums/namespace.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Namespace } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../generator'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class SupportNamespace extends Namespace { - constructor(parent: Namespace, private state: State | NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: State, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/exports.ts b/powershell/llcsharp/exports.ts index af1d4562506..f9d66798e8b 100644 --- a/powershell/llcsharp/exports.ts +++ b/powershell/llcsharp/exports.ts @@ -13,4 +13,4 @@ export * from './schema/schema-resolver'; export * from './schema/extended-type-declaration'; export * from './model/model-class-serializer'; export * from './schema/enum'; -export { Boolean, NewBoolean } from './schema/boolean'; +export { Boolean } from './schema/boolean'; diff --git a/powershell/llcsharp/generator.ts b/powershell/llcsharp/generator.ts index 644e9409f45..b24d9690c6d 100644 --- a/powershell/llcsharp/generator.ts +++ b/powershell/llcsharp/generator.ts @@ -3,18 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ModelState } from '@azure-tools/codemodel-v3'; import { codeModelSchema } from '@azure-tools/codemodel'; import { Model } from './code-model'; import { Host, JsonPath, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from './project'; +import { Project } from './project'; import { Dictionary } from '@azure-tools/linq'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; -export class State extends ModelState { +export class State extends ModelState { project!: Project; public constructor(service: Host, objectInitializer?: DeepPartial) { @@ -23,29 +22,6 @@ export class State extends ModelState { } async init(project?: Project) { - if (project) { - this.project = project; - } - return await super.init(project); - } - - path(...childPath: JsonPath) { - // const result = new State(this.service, this); - // result.currentPath = [...this.currentPath, ...childPath]; - //return result; - return this; - } -} - -export class NewState extends NewModelState { - project!: NewProject; - - public constructor(service: Host, objectInitializer?: DeepPartial) { - super(service); - this.apply(objectInitializer); - } - - async init(project?: NewProject) { if (project) { this.project = project; } diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index dd7f399a09c..e8be1b36e50 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -9,9 +9,9 @@ import { Expression, ExpressionOrLiteral, Interface, Namespace, OneOrMoreStateme import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, Language, ObjectSchema } from '@azure-tools/codemodel'; -import { State, NewState } from '../generator'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ModelClass, NewModelClass } from './model-class'; +import { State } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; @@ -124,159 +124,8 @@ export function newAddInfoAttribute(targetProperty: Property, pType: TypeDeclara } -export class ModelInterface extends Interface implements EnhancedTypeDeclaration { - get schema(): Schema { - return this.classImplementation.schema; - } - - get defaultOfType() { - return this.classImplementation.defaultOfType; - } - - get convertObjectMethod() { - return this.classImplementation.convertObjectMethod; - } - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.classImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.classImplementation.deserializeFromNode(mediaType, node, defaultValue); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.classImplementation.deserializeFromString(mediaType, content, defaultValue); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.classImplementation.deserializeFromResponse(mediaType, content, defaultValue); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.classImplementation.serializeToContent(mediaType, value, mode); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.classImplementation.serializeToNode(mediaType, value, serializedName, mode); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.classImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.classImplementation.isXmlAttribute; - } - - public isNullable = true; - - get isRequired(): boolean { - return this.classImplementation.isRequired; - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.classImplementation.validatePresence(eventListener, property); - } - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.classImplementation.validateValue(eventListener, property); - } - get hasHeaderProperties(): boolean { - // disabled - // return this.classImplementation.hasHeaderProperties; - return false; - } - constructor(parent: TypeContainer, interfaceName: string, public classImplementation: ModelClass, public state: State, objectInitializer?: DeepPartial) { - super(parent, interfaceName); - this.partial = true; - this.apply(objectInitializer); - } - - get isInternal(): boolean { - return this.accessModifier === Access.Internal; - } - - init() { - (this).init = () => { }; // only allow a single init! - - const implData = (this.schema.details.csharp = this.schema.details.csharp || {}); - //implData.interfaceImplementation = this; - this.description = `${this.schema.details.csharp.description}`; - - const virtualProperties = this.schema.details.csharp.virtualProperties || { - owned: [], - inherited: [], - inlined: [] - }; - if (this.schema.details.csharp.virtualProperties) { - - for (const virtualProperty of values(virtualProperties.owned)) { - if (virtualProperty.private && !this.isInternal) { - continue; - } - - const modelProperty = virtualProperty.property; - - const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); - - const isRequired = !!modelProperty.details.csharp.required; - const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - description: modelProperty.details.csharp.description, - setAccess: internalSet ? Access.Internal : Access.Public - })); - - this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); - - if (!this.isInternal && modelProperty.details.csharp.constantValue !== undefined) { - p.setAccess = Access.Internal; - } - } - - for (const virtualProperty of values(virtualProperties.inlined)) { - - // don't publicly expose the 'private' properties. - if (virtualProperty.private && !this.isInternal) { - continue; - } - - const modelProperty = virtualProperty.property; - const isRequired = !!modelProperty.details.csharp.required; - const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - - const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); - - const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - description: modelProperty.details.csharp.description, - setAccess: internalSet ? Access.Internal : Access.Public - })); - this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); - - } - } - - if (!this.isInternal) { - // mark it as json serializable - if (!this.schema.details.csharp.isHeaderModel) { - if (this.state.project.jsonSerialization) { - this.interfaces.push(ClientRuntime.IJsonSerializable); - } - if (this.state.project.xmlSerialization) { - this.interfaces.push(ClientRuntime.IXmlSerializable); - } - } - } - return this; - } - - addInfoAttribute(p: Property, pType: TypeDeclaration, isRequired: boolean, internalSet: boolean, description: string, serializedName: string) { - if (!this.isInternal) { - return addInfoAttribute(p, pType, isRequired, internalSet, description, serializedName); - } - } -} - -export class NewModelInterface extends Interface implements NewEnhancedTypeDeclaration { +export class ModelInterface extends Interface implements EnhancedTypeDeclaration { get schema(): NewSchema { return this.classImplementation.schema; } @@ -338,7 +187,7 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla // return this.classImplementation.hasHeaderProperties; return false; } - constructor(parent: TypeContainer, interfaceName: string, public classImplementation: NewModelClass, public state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: TypeContainer, interfaceName: string, public classImplementation: ModelClass, public state: State, objectInitializer?: DeepPartial) { super(parent, interfaceName); this.partial = true; this.apply(objectInitializer); diff --git a/powershell/llcsharp/model/model-class-dictionary.ts b/powershell/llcsharp/model/model-class-dictionary.ts index 330cdd2f3e9..3b43e522eba 100644 --- a/powershell/llcsharp/model/model-class-dictionary.ts +++ b/powershell/llcsharp/model/model-class-dictionary.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Field, System, Property, toExpression, dotnet, Parameter, ParameterModifier, Method, Class, TypeDeclaration, Indexer, Access, Variable, Expression, If, And, ForEach, LocalVariable, ImplicitCastOperator } from '@azure-tools/codegen-csharp'; -import { ModelClass, NewModelClass } from './model-class'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; import { getAllVirtualProperties } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; @@ -21,112 +21,6 @@ export class DictionaryImplementation extends Class { this.apply(objectInitializer); } - init(valueType?: TypeDeclaration, accessViaMember?: Expression) { - if (valueType && accessViaMember) { - this.valueType = valueType; - this.implementIDictionary(this, '', System.String, valueType, accessViaMember); - - } - else { - if (this.schema.additionalProperties) { - this.ownsDictionary = true; - this.valueType = this.schema.additionalProperties === true ? System.Object : this.state.project.modelsNamespace.resolveTypeDeclaration(this.schema.additionalProperties, true, this.state); - this.modelClass.modelInterface.interfaces.push(this.implementIDictionary(this, 'additionalProperties', System.String, this.valueType)); - } - } - - return this; - } - - addSerialization() { - if (this.modelClass.jsonSerializer) { - // add serializer methods. - // this.modelClass.jsonSerializer - - - } - } - - implementIDictionary(targetClass: Class, name: string, keyType: TypeDeclaration, valueType: TypeDeclaration, accessViaMember?: Expression) { - const containerInterfaceType = { declaration: `${ClientRuntime}.IAssociativeArray<${valueType.declaration}>`, allProperties: [] }; - const dictionaryInterfaceType = System.Collections.Generic.IDictionary(keyType, valueType); - const itemType = System.Collections.Generic.KeyValuePair(keyType, valueType); - - // add the interface to the list of interfaces for the class - targetClass.interfaces.push(containerInterfaceType); - - // the backing field - const dictionaryType = System.Collections.Generic.Dictionary(keyType, valueType); - - accessViaMember = accessViaMember || targetClass.add(new Field(`__${name}`, dictionaryType, { access: Access.Protected, initialValue: dictionaryType.new() })); - - const indexer = targetClass.add(new Indexer(keyType, valueType, { get: toExpression(`${accessViaMember}[index]`), set: toExpression(`${accessViaMember}[index] = value`) })); - - // the parameters used in methods. - - const pKey = new Parameter('key', keyType); - const pValue = new Parameter('value', valueType); - const pOutValue = new Parameter('value', valueType, { modifier: ParameterModifier.Out }); - - targetClass.add(new Property(`${containerInterfaceType.declaration}.Keys`, System.Collections.Generic.IEnumerable(keyType), { get: toExpression(`${accessViaMember}.Keys`), getAccess: Access.Explicit })); - targetClass.add(new Property(`${containerInterfaceType.declaration}.Values`, System.Collections.Generic.IEnumerable(valueType), { get: toExpression(`${accessViaMember}.Values`), getAccess: Access.Explicit })); - targetClass.add(new Property(`${containerInterfaceType.declaration}.Count`, dotnet.Int, { get: toExpression(`${accessViaMember}.Count`), getAccess: Access.Explicit })); - if (name) { - targetClass.add(new ImplicitCastOperator(dictionaryType, targetClass, `source.${accessViaMember}`)); - targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}`), getAccess: Access.Explicit })); - } else { - targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}.AdditionalProperties`), getAccess: Access.Explicit })); - } - targetClass.add(new Method('Add', dotnet.Void, { parameters: [pKey, pValue], body: toExpression(`${accessViaMember}.Add( ${pKey}, ${pValue})`), access: Access.Public })); - targetClass.add(new Method('Clear', dotnet.Void, { body: toExpression(`${accessViaMember}.Clear()`), access: Access.Public })); - - targetClass.add(new Method('ContainsKey', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.ContainsKey( ${pKey})`), access: Access.Public })); - - targetClass.add(new Method('Remove', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.Remove( ${pKey})`), access: Access.Public })); - - targetClass.add(new Method('TryGetValue', dotnet.Bool, { parameters: [pKey, pOutValue], body: toExpression(`${accessViaMember}.TryGetValue( ${pKey}, out ${pOutValue})`), access: Access.Public })); - - const all = getAllVirtualProperties(this.schema.details.csharp.virtualProperties); - const exclusions = all.map(each => `"${each.name}"`).join(','); - - // add a CopyFrom that takes an IDictionary or PSObject and copies the values into this dictionary - for (const pDictType of [System.Collections.IDictionary, { declaration: 'global::System.Management.Automation.PSObject' }]) { - const pDict = new Parameter('source', pDictType); - targetClass.add(new Method('CopyFrom', dotnet.Void, { - parameters: [pDict], body: function* () { - yield If(pDict.IsNotNull, function* () { - - yield ForEach('property', ` Microsoft.Rest.ClientRuntime.PowerShell.TypeConverterExtensions.GetFilteredProperties(${pDict.value}, ${System.Collections.Generic.HashSet(System.String).new()} { ${exclusions} } )`, function* () { - - yield If(And('null != property.Key', 'null != property.Value'), function* () { - yield `this.${accessViaMember}.Add(property.Key.ToString(), global::System.Management.Automation.LanguagePrimitives.ConvertTo<${valueType.declaration}>( property.Value));`; - }); - }); - }); - } - })); - } - - // return dictionaryInterfaceType; - return containerInterfaceType; - } - - public get fileName(): string { - return `${super.fileName}.dictionary`; - } -} - -export class NewDictionaryImplementation extends Class { - private get state() { return this.modelClass.state; } - private get schema() { return this.modelClass.schema; } - public valueType!: TypeDeclaration | NewEnhancedTypeDeclaration; - public ownsDictionary = false; - - constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - } - init(valueType?: TypeDeclaration, accessViaMember?: Expression) { if (valueType && accessViaMember) { this.valueType = valueType; diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 5af56bcfe27..d4043908424 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -24,13 +24,13 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { ModelClass, NewModelClass } from './model-class'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; -import { NewModelInterface } from './interface'; +import { ModelInterface } from './interface'; + export class JsonSerializableClass extends Class { private btj!: Method; @@ -64,218 +64,6 @@ export class JsonSerializableClass extends Class { })); - const serializeStatements = new Statements(); - const deserializeStatements = new Statements(); - this.excludes = ''; - - if (this.modelClass.dictionaryImpl) { - const vType = this.modelClass.dictionaryImpl.valueType; - // we have to ensure that all the known wire-names are excluded on deserialization. - const exclusions = new Parameter('exclusions', System.Collections.Generic.HashSet(dotnet.String), { defaultInitializer: dotnet.Null }); - deserializerConstructor.parameters.push(exclusions); - - this.excludes = [...values(getAllProperties(this.modelClass.schema)).select(each => each.serializedName).select(each => new StringExpression(each))].join(); - this.excludes = this.excludes ? `,${System.Collections.Generic.HashSet(dotnet.String).new()}{ ${this.excludes} }` : ''; - - const ap = `((${ClientRuntime}.IAssociativeArray<${vType.declaration}>)this).AdditionalProperties`; - - if (this.modelClass.dictionaryImpl.ownsDictionary) { - // we have to implement the deserializer for it. - - serializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.ToJson( ${ap}, ${container});`)); - - if (vType === System.Object) { - // wildcard style - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); - - } else if (vType instanceof ObjectImplementation) { - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${this.modelClass.fullName}.FromJson(j) ,${exclusions.value} );`)); - } else { - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, null ,${exclusions.value} );`)); - } - } - } - - - for (const each of values(modelClass.backingFields)) { - serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - const sch = (each.typeDeclaration).schema; - if (!(sch instanceof NewSchema) && (sch.additionalProperties)) { - deserializeStatements.add(`${each.field.value} = new ${each.className}(json${this.excludes});`); - } else { - deserializeStatements.add(`${each.field.value} = new ${each.className}(json);`); - } - } - - pushTempVar(); - for (const prop of values(modelClass.ownedProperties)) { - if (prop.details.csharp.HeaderProperty === 'Header') { - continue; - } - const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Json, prop.valuePrivate, container, prop.serializedName, mode); - - if (prop.details.csharp.readOnly) { - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); - } else { - serializeStatements.add(serializeStatement); - } - deserializeStatements.add(prop.assignPrivate((prop.type).deserializeFromContainerMember(KnownMediaType.Json, jsonParameter, prop.serializedName, prop))); - } - popTempVar(); - - const $this = this; - - // generate the implementation for toJson - toJsonMethod.add(function* () { - yield `${container} = ${container} ?? new ${ClientRuntime.JsonObject.declaration}();`; - yield EOL; - - yield 'bool returnNow = false;'; - yield `${$this.btj.name}(ref ${container}, ref returnNow);`; - - yield If(toExpression('returnNow'), `return ${container};`); - - // get serialization statements - yield serializeStatements; - - yield `${$this.atj.name}(ref ${container});`; - yield Return(container); - }); - - // and let's fill in the deserializer constructor statements now. - deserializerConstructor.add(function* () { - yield 'bool returnNow = false;'; - yield `${$this.bfj.name}(json, ref returnNow);`; - yield If(toExpression('returnNow'), 'return;'); - - yield deserializeStatements; - yield `${$this.afj.name}(json);`; - }); - } - - public get definition(): string { - const $this = this.modelClass; - // gotta write this just before we write out the class, since we had to wait until everyone had reported to their parents. - const d = this.modelClass.discriminators; - const isp = this.modelClass.isPolymorphic; - // create the FromJson method - const node = new Parameter('node', ClientRuntime.JsonNode, { description: `a to deserialize from.` }); - const fromJson = this.addMethod(new Method('FromJson', this.modelClass.modelInterface, { - parameters: [node], static: Modifier.Static, - description: `Deserializes a into an instance of ${this.modelClass.modelInterface}.`, - returnsDescription: `an instance of ${this.modelClass.modelInterface}.` - })); - - if (isp) { - fromJson.description = fromJson.description + `\n Note: the ${this.modelClass.modelInterface} interface is polymorphic, and the precise model class that will get deserialized is determined at runtime based on the payload.`; - } - const $excludes = this.excludes; - fromJson.add(function* () { - - const json = IsDeclaration(node, ClientRuntime.JsonObject, 'json'); - - if (isp) { - yield If(Not(json.check), Return(dotnet.Null)); - yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; - /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ - - if ($this.schema.discriminator) { - yield Switch(toExpression(`json.StringProperty("${$this.schema.discriminator.propertyName}")`), function* () { - for (const { key, value } of items(d)) { - yield TerminalCase(`"${key}"`, function* () { - yield Return(value.new(json)); - }); - } - }); - } - yield Return($this.new(json, toExpression($excludes.substring(1)))); - } else { - // just tell it to create the instance (providing that it's a JSonObject) - yield Return(Ternery(json.check, $this.new(json), dotnet.Null)); - } - }); - - return super.definition; - } - - public get fileName(): string { - return `${super.fileName}.json`; - } - - protected addPartialMethods() { - // add partial methods for future customization - this.btj = this.addMethod(new PartialMethod('BeforeToJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }), - ], - description: `BeforeToJson will be called before the json serialization has commenced, allowing complete customization of the object before it is serialized. - If you wish to disable the default serialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.atj = this.addMethod(new PartialMethod('AfterToJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), - ], - description: `AfterToJson will be called after the json erialization has finished, allowing customization of the before it is returned. Implement this method in a partial class to enable this behavior ` - })); - - this.bfj = this.addMethod(new PartialMethod('BeforeFromJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the deserialization should be processed, or if the method should return instantly.' }), - ], - description: `BeforeFromJson will be called before the json deserialization has commenced, allowing complete customization of the object before it is deserialized. - If you wish to disable the default deserialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afj = this.addMethod(new PartialMethod('AfterFromJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), - ], - description: 'AfterFromJson will be called after the json deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ' - })); - } -} - -export class NewJsonSerializableClass extends Class { - private btj!: Method; - private atj!: Method; - private bfj!: Method; - private afj!: Method; - private excludes: string; - - constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - this.partial = true; - this.description = modelClass.description; - this.addPartialMethods(); - - // set up the declaration for the toJson method. - const container = new Parameter('container', ClientRuntime.JsonObject, { description: `The container to serialize this object into. If the caller passes in null, a new instance will be created and returned to the caller.` }); - const mode = new Parameter('serializationMode', ClientRuntime.SerializationMode, { description: `Allows the caller to choose the depth of the serialization. See .` }); - - const toJsonMethod = this.addMethod(new Method('ToJson', ClientRuntime.JsonNode, { - parameters: [container, mode], - description: `Serializes this instance of into a .`, - returnsDescription: `a serialized instance of as a .` - })); - - // setup the declaration for the json deserializer constructor - const jsonParameter = new Parameter('json', ClientRuntime.JsonObject, { description: `A ${ClientRuntime.JsonObject} instance to deserialize from.` }); - const deserializerConstructor = this.addMethod(new Constructor(this, { - parameters: [jsonParameter], access: Access.Internal, - description: `Deserializes a ${ClientRuntime.JsonObject} into a new instance of .` - })); - - const serializeStatements = new Statements(); const deserializeStatements = new Statements(); this.excludes = ''; @@ -300,7 +88,7 @@ export class NewJsonSerializableClass extends Class { // wildcard style deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); - } else if (vType instanceof NewModelInterface) { + } else if (vType instanceof ModelInterface) { // use the class of the dictionary value to deserialize values deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${vType.classImplementation.fullName}.FromJson(j) ,${exclusions.value} );`)); } else { @@ -312,7 +100,7 @@ export class NewJsonSerializableClass extends Class { for (const each of values(modelClass.backingFields)) { serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - const sch = (each.typeDeclaration).schema; + const sch = (each.typeDeclaration).schema; const dictSchema = sch.type === SchemaType.Dictionary ? sch : sch.type === SchemaType.Object ? (sch).parents?.immediate.find((s) => s.type === SchemaType.Dictionary) : undefined; diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index 9ba766976a4..28caac5c536 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -23,57 +23,19 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { ModelClass } from './model-class'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; -import { getVirtualPropertyName, NewGetVirtualPropertyName } from './model-class'; +import { getVirtualPropertyName } from './model-class'; import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; -export class SerializationPartialClass extends Initializer { - constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, protected resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - - protected get virtualProperties() { - return this.schema.details.csharp.virtualProperties || { - owned: [], - inherited: [], - inlined: [] - }; - } - protected get allVirtualProperties() { - const vp = this.virtualProperties; - // return [...vp.owned, ...vp.inherited, ...vp.inlined]; - return values(vp.owned, vp.inherited, vp.inlined).toArray(); - } - - protected contentParameter = new Parameter('content', this.serializationType, { description: `The ${this.serializationType.declaration} content that should be used.` }); - protected refContainerParameter = new Parameter('container', this.serializationType, { modifier: ParameterModifier.Ref, description: `The ${this.serializationType.declaration} container that the serialization result will be placed in.` }); - protected returnNowParameter = new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }); - - protected get typeCref() { - return ``; - } - protected get thisCref() { - return ``; - } - - protected get interfaceCref() { - return ``; - } - -} - -export class NewSerializationPartialClass extends Initializer { - constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { +export class SerializationPartialClass extends Initializer { + constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } @@ -108,116 +70,11 @@ export class NewSerializationPartialClass extends Initializer { } } -export class DeserializerPartialClass extends SerializationPartialClass { - private beforeDeserialize!: Method; - private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); - this.apply(objectInitializer); - } - - async init() { - // add partial methods for extensibility - this.addPartialMethods(); - this.addDeserializerConstructor(); - this.addDeserializerMethod(); - } - - protected addDeserializerConstructor() { - const $this = this; - - const deserializerConstructor = this.targetClass.addMethod(new Constructor(this.targetClass, { - parameters: [this.contentParameter], access: Access.Internal, - description: `Deserializes a ${this.typeCref} into a new instance of ${this.thisCref}.` - })); - - deserializerConstructor.add(function* () { - const returnNow = new LocalVariable('returnNow', dotnet.Bool, { initializer: dotnet.False }); - yield returnNow.declarationStatement; - - yield `${$this.beforeDeserialize.name}(${$this.contentParameter}, ref ${returnNow.value});`; - yield If(returnNow, 'return;'); - yield $this.deserializeStatements; - if ($this.hasAadditionalProperties($this.schema)) { - // this type has an additional properties dictionary - yield '// this type is a dictionary; copy elements from source to here.'; - yield `CopyFrom(${$this.contentParameter.value});`; - } - - yield `${$this.afterDeserialize.name}(${$this.contentParameter});`; - }); - } - - private hasAadditionalProperties(aSchema: Schema): boolean { - if (aSchema.additionalProperties) { - return true; - } else - for (const each of values(aSchema.allOf)) { - const r = this.hasAadditionalProperties(each); - if (r) { - return r; - } - } - return false; - } - - get deserializeStatements() { - const $this = this; - - return function* () { - yield '// actually deserialize '; - - for (const virtualProperty of values($this.allVirtualProperties)) { - // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; - const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.details.default.required); - - const cvt = type.convertObjectMethod; - const t = `((${virtualProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - const tt = type ? `(${type.declaration})` : ''; - - yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; - } - }; - } - - protected addDeserializerMethod() { - const $this = this; - - const deserialzeMethod = this.targetClass.addMethod(new Method(`DeserializeFrom${this.serializationFormat}`, this.targetInterface, { - parameters: [this.contentParameter], static: Modifier.Static, - description: `Deserializes a ${this.typeCref} into an instance of ${this.thisCref}.`, - returnsDescription: `an instance of ${this.interfaceCref}.` - })); - - deserialzeMethod.add(function* () { - yield Return($this.targetClass.new($this.contentParameter)); - }); - - } - - protected addPartialMethods() { - const before = `BeforeDeserialize${this.serializationFormat}`; - const after = `AfterDeserialize${this.serializationFormat}`; - this.beforeDeserialize = this.targetClass.addMethod(new PartialMethod(before, dotnet.Void, { - access: Access.Default, - parameters: [this.contentParameter, this.returnNowParameter], - description: `${before} will be called before the deserialization has commenced, allowing complete customization of the object before it is deserialized. - If you wish to disable the default deserialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afterDeserialize = this.targetClass.addMethod(new PartialMethod(after, dotnet.Void, { - access: Access.Default, - parameters: [this.contentParameter], - description: `${after} will be called after the deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ` - })); - } -} -export class NewDeserializerPartialClass extends NewSerializationPartialClass { +export class DeserializerPartialClass extends SerializationPartialClass { private beforeDeserialize!: Method; private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); this.apply(objectInitializer); } @@ -286,7 +143,7 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { const cvt = type.convertObjectMethod; const t = `((${virtualProperty.originalContainingSchema.language.csharp?.fullInternalInterfaceName})this)`; const tt = type ? `(${type.declaration})` : ''; - yield `${t}.${NewGetVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${NewGetVirtualPropertyName(virtualProperty)}",${t}.${NewGetVirtualPropertyName(virtualProperty)}, ${cvt});`; + yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; } }; } @@ -325,46 +182,4 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { } } -export class SerializerPartialClass extends SerializationPartialClass { - private beforeSerialize!: Method; - private afterSerialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); - this.apply(objectInitializer); - } - - async init() { - this.addPartialMethods(); - this.addSerializer(); - - } - - protected addSerializer() { - const serializeMethod = this.targetClass.addMethod(new Method(`SerializeTo${this.serializationFormat}`, this.serializationType, { - parameters: [this.refContainerParameter], - description: `Serializes this instance of ${this.thisCref} into a ${this.typeCref}.`, - returnsDescription: `a serialized instance of ${this.thisCref} /> as a ${this.typeCref}.` - })); - - } - - protected addPartialMethods() { - const before = `BeforeSerialize${this.serializationFormat}`; - const after = `AfterSerialize${this.serializationFormat}`; - // add partial methods for future customization - this.beforeSerialize = this.targetClass.addMethod(new PartialMethod(before, dotnet.Void, { - access: Access.Default, - parameters: [this.refContainerParameter, this.returnNowParameter], - description: `${before} will be called before the serialization has commenced, allowing complete customization of the object before it is serialized. - If you wish to disable the default serialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afterSerialize = this.targetClass.addMethod(new PartialMethod(after, dotnet.Void, { - access: Access.Default, - parameters: [this.refContainerParameter], - description: `${after} will be called after the serialization has finished, allowing customization of the ${this.typeCref} before it is returned. Implement this method in a partial class to enable this behavior ` - })); - } -} diff --git a/powershell/llcsharp/model/model-class-xml.ts b/powershell/llcsharp/model/model-class-xml.ts deleted file mode 100644 index 831158e974f..00000000000 --- a/powershell/llcsharp/model/model-class-xml.ts +++ /dev/null @@ -1,174 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { KnownMediaType, HeaderProperty, HeaderPropertyType } from '@azure-tools/codemodel-v3'; -import { EOL, DeepPartial } from '@azure-tools/codegen'; -import { items, values } from '@azure-tools/linq'; - -import { Access, Class, Constructor, dotnet, If, IsDeclaration, Method, Modifier, Not, Parameter, ParameterModifier, PartialMethod, Return, Statements, Switch, System, TerminalCase, Ternery } from '@azure-tools/codegen-csharp'; -import { ClientRuntime } from '../clientruntime'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelClass } from './model-class'; - -import { ModelProperty } from './property'; - -export class XmlSerializableClass extends Class { - private btj!: Method; - private atj!: Method; - private bfj!: Method; - private afj!: Method; - - constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - this.partial = true; - - this.addPartialMethods(); - - // set up the declaration for the toXml method. - const container = new Parameter('container', System.Xml.Linq.XElement, { description: `The container to serialize this object into. If the caller passes in null, a new instance will be created and returned to the caller.` }); - const mode = new Parameter('serializationMode', ClientRuntime.SerializationMode, { description: `Allows the caller to choose the depth of the serialization. See .` }); - - const toXmlMethod = this.addMethod(new Method('ToXml', System.Xml.Linq.XElement, { - parameters: [container, mode], - })); - - // setup the declaration for the xml deserializer constructor - const xmlParameter = new Parameter('xml', System.Xml.Linq.XElement, { description: `A ${System.Xml.Linq.XElement} instance to deserialize from.` }); - const deserializerConstructor = this.addMethod(new Constructor(this, { - parameters: [xmlParameter], access: Access.Internal, - description: `Deserializes a ${System.Xml.Linq.XElement} into a new instance of .` - })); - - const serializeStatements = new Statements(); - const deserializeStatements = new Statements(); - - for (const each of values(modelClass.backingFields)) { - serializeStatements.add(`${each.field.value}?.ToXml(result, ${mode.use});`); - deserializeStatements.add(`${each.field.value} = new ${each.className}(xml);`); - } - pushTempVar(); - for (const property of values(modelClass.schema.properties)) { - const prop = modelClass.$(property.details.csharp.name); - const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Xml, prop, container, prop.serializedName, mode); - - if (property.details.csharp[HeaderProperty] === HeaderPropertyType.Header) { - // it's a header only property. Don't serialize unless the mode has SerializationMode.IncludeHeaders enabled - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeHeaders})`, serializeStatement)); - } else { - if (property.details.csharp.readOnly) { - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); - } else { - serializeStatements.add(serializeStatement); - } - } - deserializeStatements.add(prop.assignPrivate((prop.type).deserializeFromContainerMember(KnownMediaType.Xml, xmlParameter, prop.serializedName, prop))); - } - popTempVar(); - const $this = this; - - // generate the implementation for toXml - toXmlMethod.add(function* () { - yield `${container} = ${container} ?? new ${System.Xml.Linq.XElement.declaration}(nameof(${$this.modelClass.name}));`; - yield EOL; - - yield 'bool returnNow = false;'; - yield `${$this.btj.name}(ref ${container}, ref returnNow);`; - - yield If('returnNow', `return ${container};`); - - // get serialization statements - yield serializeStatements; - - yield `${$this.atj.name}(ref ${container});`; - yield Return(container); - }); - - // and let's fill in the deserializer constructor statements now. - deserializerConstructor.add(function* () { - yield 'bool returnNow = false;'; - yield `${$this.bfj.name}(xml, ref returnNow);`; - yield If('returnNow', 'return;'); - - yield deserializeStatements; - yield `${$this.afj.name}(xml);`; - }); - } - - public get definition(): string { - const $this = this.modelClass; - // gotta write this just before we write out the class, since we had to wait until everyone had reported to their parents. - const d = this.modelClass.discriminators; - const isp = this.modelClass.isPolymorphic; - // create the FromXml method - const node = new Parameter('node', System.Xml.Linq.XElement, { description: `A ${System.Xml.Linq.XElement} instance to deserialize from.` }); - const fromXml = this.addMethod(new Method('FromXml', this.modelClass.modelInterface, { parameters: [node], static: Modifier.Static })); - fromXml.add(function* () { - - const xml = IsDeclaration(node, System.Xml.Linq.XElement, 'xml'); - - if (isp) { - yield If(Not(xml.check), Return(dotnet.Null)); - yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; - /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ - - if ($this.schema.discriminator) { - yield Switch(`xml.StringProperty("${$this.schema.discriminator.propertyName}")`, function* () { - for (const { key, value } of items(d)) { - yield TerminalCase(`"${key}"`, function* () { - yield Return(value.new(xml)); - }); - } - }); - } - yield Return($this.new(xml)); - } else { - // just tell it to create the instance (providing that it's a XElement) - yield Return(Ternery(xml.check, $this.new(xml), dotnet.Null)); - } - }); - - return super.definition; - } - - public get fileName(): string { - return `${super.fileName}.xml`; - } - - protected addPartialMethods() { - // add partial methods for future customization - this.btj = this.addMethod(new PartialMethod('BeforeToXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', System.Xml.Linq.XElement, { modifier: ParameterModifier.Ref, description: 'The XElement that the serialization result will be placed in.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }), - ], - })); - - this.atj = this.addMethod(new PartialMethod('AfterToXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', System.Xml.Linq.XElement, { modifier: ParameterModifier.Ref, description: 'The XElement that the serialization result will be placed in.' }), - ], - })); - - this.bfj = this.addMethod(new PartialMethod('BeforeFromXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('xml', System.Xml.Linq.XElement, { description: 'The XmlNode that should be deserialized into this object.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the deserialization should be processed, or if the method should return instantly.' }), - ], - })); - - this.afj = this.addMethod(new PartialMethod('AfterFromXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('xml', System.Xml.Linq.XElement, { description: 'The XmlNode that should be deserialized into this object.' }), - ], - })); - } - -} diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index c87075ae1bd..fd98f5310a2 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -8,19 +8,19 @@ import { camelCase, deconstruct, DeepPartial } from '@azure-tools/codegen'; import { items, values } from '@azure-tools/linq'; import { Access, Class, Constructor, Expression, ExpressionOrLiteral, Field, If, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Statements, System, TypeDeclaration, valueOf, Variable, BackedProperty, Property, Virtual, toExpression, StringExpression, LiteralExpression, Attribute } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State, NewState } from '../generator'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { ModelInterface, NewModelInterface } from './interface'; -import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-json'; -import { ModelProperty, NewModelProperty } from './property'; +import { State } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ObjectImplementation } from '../schema/object'; +import { ModelInterface } from './interface'; +import { JsonSerializableClass } from './model-class-json'; +import { ModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; -import { DictionaryImplementation, NewDictionaryImplementation } from './model-class-dictionary'; +import { DictionaryImplementation } from './model-class-dictionary'; import { Languages, Language, Schema as NewSchema, SchemaType, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; import { VirtualProperty as NewVirtualProperty, getAllVirtualProperties as newGetAllVirtualProperties } from '../../utils/schema'; -export function getVirtualPropertyName(vp?: VirtualProperty): string { +export function getVirtualPropertyName(vp?: NewVirtualProperty): string { if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { return getVirtualPropertyName(vp.accessViaMember); @@ -28,14 +28,6 @@ export function getVirtualPropertyName(vp?: VirtualProperty): string { return vp ? vp.name : ''; } -export function NewGetVirtualPropertyName(vp?: NewVirtualProperty): string { - - if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { - return NewGetVirtualPropertyName(vp.accessViaMember); - } - return vp ? vp.name : ''; -} - export interface BackingField { field: Field; typeDeclaration: TypeDeclaration; @@ -93,8 +85,8 @@ export class ModelClass extends Class implements EnhancedTypeDeclaration { /* @internal */ validateMethod?: Method; /* @internal */ discriminators: Map = new Map(); /* @internal */ parentModelClasses: Array = new Array(); - /* @internal */ get modelInterface(): ModelInterface { return this.schema.details.csharp.interfaceImplementation; } - /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.details.csharp.internalInterfaceImplementation; } + /* @internal */ get modelInterface(): ModelInterface { return this.schema.language.csharp?.interfaceImplementation; } + /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } /* @internal */ state: State; /* @internal */ backingFields = new Array(); @@ -106,472 +98,11 @@ export class ModelClass extends Class implements EnhancedTypeDeclaration { private readonly validationStatements = new Statements(); public ownedProperties = new Array(); - private pMap = new Map(); + private pMap = new Map(); // public hasHeaderProperties: boolean; constructor(namespace: Namespace, schemaWithFeatures: ObjectImplementation, state: State, objectInitializer?: DeepPartial) { - super(namespace, schemaWithFeatures.schema.details.csharp.name); - this.featureImplementation = schemaWithFeatures; - this.schema.details.csharp.classImplementation = this; // mark the code-model with the class we're creating. - this.state = state; - this.apply(objectInitializer); - - if (this.state.getValue('powershell') && this.schema.details.csharp.suppressFormat) { - this.add(new Attribute(DoNotFormatAttribute)); - } - - // must be a partial class - this.partial = true; - - this.handleDiscriminator(); - - // create an interface for this model class - if (!this.schema.details.csharp.interfaceImplementation) { - (this.schema.details.csharp.interfaceImplementation = new ModelInterface(this.namespace, this.schema.details.csharp.interfaceName || `I${this.schema.details.csharp.name}`, this, this.state)); - - } - this.interfaces.push(this.modelInterface); - - if (!this.schema.details.csharp.internalInterfaceImplementation) { - (this.schema.details.csharp.internalInterfaceImplementation = new ModelInterface(this.namespace, this.schema.details.csharp.internalInterfaceName || `I${this.schema.details.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); - - } - - this.interfaces.push(this.internalModelInterface); - - this.schema.details.csharp.internalInterfaceImplementation.init(); - this.schema.details.csharp.interfaceImplementation.init(); - - // add default constructor - this.addMethod(new Constructor(this, { description: `Creates an new instance.` })); // default constructor for fits and giggles. - - // handle parent interface implementation - if (!this.handleAllOf()) { - // handle the AdditionalProperties if used - if (this.schema.additionalProperties) { - this.dictionaryImpl = new DictionaryImplementation(this).init(); - } - } - - // create the properties for ths schema - this.createProperties(); - - // add validation implementation - this.addValidation(); - - // add header properties for this model. - // DISABLED. - this.addHeaderDeserializer(); - - if (this.state.project.jsonSerialization) { - this.jsonSerializer = new JsonSerializableClass(this); - } - } - - private nested(virtualProperty: VirtualProperty, internal: boolean): string { - if (virtualProperty.accessViaProperty) { - if (virtualProperty.accessViaProperty.accessViaProperty) { - // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - } - } - //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - } - - private accessor(virtualProperty: VirtualProperty, internal = false): string { - if (virtualProperty.accessViaProperty) { - const prefix = virtualProperty.accessViaProperty.accessViaProperty ? this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal) : ''; - const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); - if (containingProperty && virtualProperty.accessViaMember) { - //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - } - } - // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; - } - - private createProperties() { - // generate a protected backing field for each - // and then expand the nested properties into this class forwarding to the member. - - // add properties - if (this.schema.details.csharp.virtualProperties) { - const addFormatAttributesToProperty = (property: Property, virtualProperty: VirtualProperty) => { - if (virtualProperty.format) { - if (virtualProperty.format.suppressFormat) { - property.add(new Attribute(DoNotFormatAttribute)); - } else { - const parameters = []; - if (virtualProperty.format.index !== undefined) { - parameters.push(`Index = ${virtualProperty.format.index}`); - } - - if (virtualProperty.format.label !== undefined) { - parameters.push(`Label = ${new StringExpression(virtualProperty.format.label)}`); - } - - if (virtualProperty.format.width !== undefined) { - parameters.push(`Width = ${virtualProperty.format.width}`); - } - - property.add(new Attribute(FormatTableAttribute, { parameters })); - } - } - }; - - /* Owned Properties */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.owned)) { - const actualProperty = virtualProperty.property; - let n = 0; - const decl = this.state.project.modelsNamespace.resolveTypeDeclaration(actualProperty.schema, actualProperty.details.csharp.required, this.state.path('schema')); - - /* public property */ - const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.details.csharp.required, actualProperty.serializedName, actualProperty.details.csharp.description, this.state.path('properties', n++), { - initializer: actualProperty.details.csharp.constantValue ? typeof actualProperty.details.csharp.constantValue === 'string' ? new StringExpression(actualProperty.details.csharp.constantValue) : new LiteralExpression(actualProperty.details.csharp.constantValue) : undefined - }); - - if (actualProperty.details.csharp.readOnly) { - myProperty.set = undefined; - } - myProperty.details = virtualProperty.property.details; - - if (actualProperty.details.csharp.constantValue !== undefined) { - myProperty.setAccess = Access.Internal; - myProperty.set = undefined; - } - - if (virtualProperty.private) { - // when properties are inlined, the container accessor can be internalized. I think. - myProperty.setAccess = Access.Internal; - myProperty.getAccess = Access.Internal; - this.pMap.set(virtualProperty, myProperty); - } - - this.ownedProperties.push(this.add(myProperty)); - - if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined) { - /* internal interface property */ - - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: myProperty.get, - set: myProperty.assignPrivate('value') - })); - } - - if (this.state.getValue('powershell')) { - myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] })); - addFormatAttributesToProperty(myProperty, virtualProperty); - } - } - - /* Inherited properties. */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inherited)) { - // so each parent property that is getting exposed - // has to be accessed via the field in this.backingFields - const parentField = this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.details.csharp.interfaceImplementation.fullName === each.typeDeclaration.declaration : false); - - const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - const opsType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.originalContainingSchema, false, this.state); - const via = virtualProperty.accessViaProperty; - const parentCast = `(${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName})`; - const vp = this.add(new Property(virtualProperty.name, propertyType, { - description: virtualProperty.property.details.csharp.description, - get: toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`), - set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value`) - })); - - if (virtualProperty.property.details.csharp.constantValue !== undefined) { - vp.setAccess = Access.Internal; - vp.set = undefined; - } - - if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`), - set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`) - })); - } - - if (this.state.getValue('powershell')) { - vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] })); - addFormatAttributesToProperty(vp, virtualProperty); - } - } - - /* Inlined properties. */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inlined)) { - if (virtualProperty.private) { - // continue; - // can't remove it, it has to be either public or internally implemented. - } - - if (virtualProperty.accessViaProperty) { - const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); - if (containingProperty) { - - const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - - // regular inlined property - const vp = new Property(virtualProperty.name, propertyType, { - description: virtualProperty.property.details.csharp.description, - get: toExpression(`${this.accessor(virtualProperty)}`), - set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value`) - }); - - if (!virtualProperty.private) { - this.add(vp); - } - - if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: vp.get, - set: toExpression(`${this.accessor(virtualProperty)} = value`) - })); - } - - if (virtualProperty.property.details.csharp.constantValue !== undefined) { - vp.setAccess = Access.Internal; - vp.set = undefined; - } - - if (this.state.getValue('powershell')) { - vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] })); - addFormatAttributesToProperty(vp, virtualProperty); - } - } - } - } - - } - } - - private addValidation() { - if (this.validationStatements.implementation.trim()) { - // we do have something to valdiate! - - // add the IValidates implementation to this object. - this.interfaces.push(ClientRuntime.IValidates); - this.validateMethod = this.addMethod(new Method('Validate', System.Threading.Tasks.Task(), { - async: Modifier.Async, - parameters: [this.validationEventListener], - description: 'Validates that this object meets the validation criteria.', - returnsDescription: `A < see cref = "${System.Threading.Tasks.Task()}" /> that will be complete when validation is completed.` - })); - this.validateMethod.add(this.validationStatements); - } - } - - private additionalPropertiesType(aSchema: Schema): TypeDeclaration | undefined { - if (aSchema.additionalProperties) { - - if (aSchema.additionalProperties === true) { - return System.Object; - - } else { - // we're going to implement IDictionary - return this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema.additionalProperties, true, this.state); - } - } else - for (const each of values(aSchema.allOf)) { - const r = this.additionalPropertiesType(each); - if (r) { - return r; - } - } - return undefined; - } - - private handleAllOf() { - let hasAdditionalPropertiesInParent = false; - // handle s - // add an 'implements' for the interface for the allOf. - for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.allOf)) { - const aSchema = eachSchemaValue; - const aState = this.state.path('allOf', eachSchemaIndex); - - const td = this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema, true, aState); - const parentClass = (aSchema.details.csharp.classImplementation); - const className = parentClass.fullName; - const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); - - // add the interface as a parent to our interface. - const iface = aSchema.details.csharp.interfaceImplementation; - - // add a field for the inherited values - const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); - this.backingFields.push({ - className, - typeDeclaration: td, - field: backingField - }); - this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); - this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); - - this.internalModelInterface.interfaces.push(aSchema.details.csharp.internalInterfaceImplementation); - this.modelInterface.interfaces.push(iface); - - // - const addlPropType = this.additionalPropertiesType(aSchema); - if (addlPropType) { - this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); - hasAdditionalPropertiesInParent = true; - } - } - return hasAdditionalPropertiesInParent; - } - - private handleDiscriminator() { - if (this.schema.discriminator) { - // this has a discriminator property. - // our children are expected to tell us who they are - this.isPolymorphic = true; - // we'll add a deserializer factory method a bit later.. - } - - if (this.schema.details.csharp.discriminatorValue) { - // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. - // um. just how do we *really* know which allOf is polymorphic? - // that's really sad. - for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.allOf)) { - const parentSchema = eachAllOfValue; - const aState = this.state.path('allOf', eachAllOfIndex); - - // ensure the parent schema has it's class created first. - this.state.project.modelsNamespace.resolveTypeDeclaration(parentSchema, true, aState); - - const parentClass = parentSchema.details.csharp.classImplementation; - if (parentClass.isPolymorphic) { - // remember this class for later. - this.parentModelClasses.push(parentClass); - - // tell that parent who we are. - parentClass.addDiscriminator(this.schema.details.csharp.discriminatorValue, this); - } - } - } - } - private addHeaderDeserializer() { - const avp = getAllVirtualProperties(this.schema.details.csharp.virtualProperties); - const headers = new Parameter('headers', System.Net.Http.Headers.HttpResponseHeaders); - const readHeaders = new Method(`${ClientRuntime.IHeaderSerializable}.ReadHeaders`, undefined, { - access: Access.Explicit, - parameters: [headers], - }); - - let used = false; - - for (const headerProperty of values(avp).where(each => each.property.details.csharp[HeaderProperty] === HeaderPropertyType.HeaderAndBody || each.property.details.csharp[HeaderProperty] === HeaderPropertyType.Header)) { - used = true; - const t = `((${headerProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - const values = `__${camelCase([...deconstruct(headerProperty.property.serializedName), 'Header'])}`; - const td = this.state.project.modelsNamespace.resolveTypeDeclaration(headerProperty.property.schema, false, this.state.path('schema')); - readHeaders.add(If(`${valueOf(headers)}.TryGetValues("${headerProperty.property.serializedName}", out var ${values})`, `${t}.${headerProperty.name} = ${td.deserializeFromContainerMember(KnownMediaType.Header, headers, values, td.defaultOfType)};`)); - } - if (used) { - this.interfaces.push(ClientRuntime.IHeaderSerializable); - this.add(readHeaders); - } - } - - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.featureImplementation.validateValue(eventListener, property); - } - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.featureImplementation.validatePresence(eventListener, property); - } - - public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { - this.discriminators.set(discriminatorValue, modelClass); - - // tell any polymorphic parents incase we're doing subclass of a subclass. - for (const each of this.parentModelClasses) { - each.addDiscriminator(discriminatorValue, modelClass); - } - } -} - -export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.featureImplementation.deserializeFromNode(mediaType, node, defaultValue); - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.featureImplementation.serializeToNode(mediaType, value, serializedName, mode); - } - - get defaultOfType() { - return toExpression('null /* model class */'); - } - - get convertObjectMethod() { - return this.featureImplementation.convertObjectMethod; - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.featureImplementation.serializeToContent(mediaType, value, mode); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.featureImplementation.deserializeFromString(mediaType, content, defaultValue); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.featureImplementation.deserializeFromResponse(mediaType, content, defaultValue); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.featureImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.featureImplementation.isXmlAttribute; - } - - public isNullable = true; - - get isRequired(): boolean { - return this.featureImplementation.isRequired; - } - - public isPolymorphic = false; - public get schema() { return this.featureImplementation.schema; } - - /* @internal */ validateMethod?: Method; - /* @internal */ discriminators: Map = new Map(); - /* @internal */ parentModelClasses: Array = new Array(); - /* @internal */ get modelInterface(): NewModelInterface { return this.schema.language.csharp?.interfaceImplementation; } - /* @internal */ get internalModelInterface(): NewModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } - - /* @internal */ state: NewState; - /* @internal */ backingFields = new Array(); - /* @internal */ featureImplementation: NewObjectImplementation; - /* @internal */ validationEventListener: Parameter = new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive validation events.` }); - /* @internal */ jsonSerializer?: NewJsonSerializableClass; - // /* @internal */ xmlSerializer?: XmlSerializableClass; - /* @internal */ dictionaryImpl?: NewDictionaryImplementation; - - private readonly validationStatements = new Statements(); - public ownedProperties = new Array(); - private pMap = new Map(); - - // public hasHeaderProperties: boolean; - - constructor(namespace: Namespace, schemaWithFeatures: NewObjectImplementation, state: NewState, objectInitializer?: DeepPartial) { super(namespace, schemaWithFeatures.schema.language.csharp?.name || ''); this.featureImplementation = schemaWithFeatures; this.schema.language.csharp = this.schema.language.csharp || new Language(); @@ -590,13 +121,13 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // create an interface for this model class if (!this.schema.language.csharp.interfaceImplementation) { - (this.schema.language.csharp.interfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.interfaceName || `I${this.schema.language.csharp.name}`, this, this.state)); + (this.schema.language.csharp.interfaceImplementation = new ModelInterface(this.namespace, this.schema.language.csharp.interfaceName || `I${this.schema.language.csharp.name}`, this, this.state)); } this.interfaces.push(this.modelInterface); if (!this.schema.language.csharp.internalInterfaceImplementation) { - (this.schema.language.csharp.internalInterfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.internalInterfaceName || `I${this.schema.language.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); + (this.schema.language.csharp.internalInterfaceImplementation = new ModelInterface(this.namespace, this.schema.language.csharp.internalInterfaceName || `I${this.schema.language.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); } @@ -614,7 +145,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const dictSchema = (this.schema).type === SchemaType.Dictionary ? this.schema : this.schema.parents?.immediate?.find((schema) => schema.type === SchemaType.Dictionary); if (dictSchema) { - this.dictionaryImpl = new NewDictionaryImplementation(this).init(); + this.dictionaryImpl = new DictionaryImplementation(this).init(); } } @@ -629,7 +160,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { this.addHeaderDeserializer(); if (this.state.project.jsonSerialization) { - this.jsonSerializer = new NewJsonSerializableClass(this); + this.jsonSerializer = new JsonSerializableClass(this); } } @@ -637,11 +168,11 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { if (virtualProperty.accessViaProperty) { if (virtualProperty.accessViaProperty.accessViaProperty) { // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; } } //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; } private accessor(virtualProperty: NewVirtualProperty, internal = false): string { @@ -650,11 +181,11 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); if (containingProperty && virtualProperty.accessViaMember) { //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `((${virtualProperty.accessViaMember.originalContainingSchema.language.csharp?.fullInternalInterfaceName})${containingProperty.name}${prefix}).${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `((${virtualProperty.accessViaMember.originalContainingSchema.language.csharp?.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; } } // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; } private createProperties() { @@ -693,7 +224,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const decl = this.state.project.modelsNamespace.NewResolveTypeDeclaration(actualProperty.schema, actualProperty.language.csharp?.required, this.state.path('schema')); /* public property */ - const myProperty = new NewModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.language.csharp?.required, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), { + const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.language.csharp?.required, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), { initializer: actualProperty.language.csharp?.constantValue ? typeof actualProperty.language.csharp.constantValue === 'string' ? new StringExpression(actualProperty.language.csharp.constantValue) : new LiteralExpression(actualProperty.language.csharp.constantValue) : undefined }); @@ -896,7 +427,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // const addlPropType = this.additionalPropertiesType(aSchema); if (addlPropType) { - this.dictionaryImpl = new NewDictionaryImplementation(this).init(addlPropType, backingField); + this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); hasAdditionalPropertiesInParent = true; } } @@ -922,7 +453,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // ensure the parent schema has it's class created first. this.state.project.modelsNamespace.NewResolveTypeDeclaration(parentSchema, true, aState); - const parentClass = parentSchema.language.csharp?.classImplementation; + const parentClass = parentSchema.language.csharp?.classImplementation; if (parentClass.isPolymorphic) { // remember this class for later. this.parentModelClasses.push(parentClass); @@ -964,7 +495,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { return this.featureImplementation.validatePresence(eventListener, property); } - public addDiscriminator(discriminatorValue: string, modelClass: NewModelClass) { + public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { this.discriminators.set(discriminatorValue, modelClass); // tell any polymorphic parents incase we're doing subclass of a subclass. diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 58d0d0d64ac..92647993625 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -8,15 +8,15 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { State, NewState } from '../generator'; -import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../schema/schema-resolver'; -import { EnumClass, NewEnumClass } from '../enums/enum'; +import { State } from '../generator'; +import { EnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ObjectImplementation } from '../schema/object'; +import { SchemaDefinitionResolver } from '../schema/schema-resolver'; +import { EnumClass } from '../enums/enum'; import * as validation from '../validations'; -import { ModelInterface, NewModelInterface } from './interface'; -import { ModelClass, NewModelClass } from './model-class'; +import { ModelInterface } from './interface'; +import { ModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -36,134 +36,8 @@ export class ModelsNamespace extends Namespace { private subNamespaces = new Dictionary(); resolver = new SchemaDefinitionResolver(); - newResolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary | NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { - super('Models', parent); - this.subNamespaces[this.fullName] = this; - - - this.apply(objectInitializer); - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // special case... hook this up before we get anywhere. - state.project.modelsNamespace = this; - if (!(schemas instanceof NewSchemas)) { - for (const { key: index, value: schema } of items(schemas)) { - const state = this.state.path(index); - - // verify that the model isn't in a bad state - if (validation.objectWithFormat(schema, state)) { - continue; - } - this.resolveTypeDeclaration(schema, true, state); - } - } else { - if (schemas.objects) { - for (const schema of schemas.objects) { - this.NewResolveTypeDeclaration(schema, true, state); - } - } - if (schemas.strings) { - for (const schema of schemas.strings) { - this.NewResolveTypeDeclaration(schema, true, state); - } - } - //todo, need to add support for other types - } - } - - get outputFolder() { - return 'Models'; - } - - public resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: State): EnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - const td = this.resolver.resolveTypeDeclaration(schema, required, state); - - if (!schema.details.csharp.skip) { - if (td instanceof ObjectImplementation) { - // it's a class object. - // create it if necessary - - const fullname = schema.details.csharp.namespace || this.fullName; - - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - - const mc = schema.details.csharp.classImplementation || new ModelClass(ns, td, this.state, { description: schema.details.csharp.description }); - - // this gets implicity created during class creation: - return schema.details.csharp.interfaceImplementation; - } - - if (state.project.azure && /^api-?version$/i.exec(schema.details.csharp.name)) { - return td; - } - - if (td instanceof EnumImplementation) { - if (schema.details.csharp.enum) { - const ec = state.project.supportNamespace.findClassByName(schema.details.csharp.enum.name); - if (length(ec) === 0) { - new EnumClass(td, state); - // return schema.details.csharp.typeDeclaration = ec[0]; - } - } - - return schema.details.csharp.typeDeclaration = td; - } - } - return td; - } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - const td = this.newResolver.resolveTypeDeclaration(schema, required, state); - - if (!schema.language.csharp?.skip) { - if (td instanceof NewObjectImplementation) { - // it's a class object. - // create it if necessary - - const fullname = schema.language.csharp?.namespace || this.fullName; - - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - - const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); - - // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; - } - - if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { - return td; - } - - if (td instanceof NewEnumImplementation) { - if (schema.language.csharp?.enum) { - const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); - if (length(ec) === 0) { - new NewEnumClass(td, state); - // return schema.language.csharp.typeDeclaration = ec[0]; - } - } - schema.language.csharp = schema.language.csharp || new Language(); - return schema.language.csharp.typeDeclaration = td; - } - } - return td; - } -} - -export class NewModelsNamespace extends Namespace { - private subNamespaces = new Dictionary(); - - resolver = new SchemaDefinitionResolver(); - newResolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { + newResolver = new SchemaDefinitionResolver(); + constructor(parent: Namespace, private schemas: NewSchemas, private state: State, objectInitializer?: DeepPartial) { super('Models', parent); this.subNamespaces[this.fullName] = this; @@ -176,29 +50,29 @@ export class NewModelsNamespace extends Namespace { if (schemas.objects) { for (const schema of schemas.objects) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.dictionaries) { for (const schema of schemas.dictionaries) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.any) { for (const schema of schemas.any) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.strings) { for (const schema of schemas.strings) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.sealedChoices) { for (const schema of schemas.sealedChoices) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } //todo, need to add support for other types @@ -209,7 +83,7 @@ export class NewModelsNamespace extends Namespace { return 'Models'; } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: State): EnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -217,7 +91,7 @@ export class NewModelsNamespace extends Namespace { const td = this.newResolver.resolveTypeDeclaration(schema, required, state); if (!schema.language.csharp?.skip) { - if (td instanceof NewObjectImplementation) { + if (td instanceof ObjectImplementation) { // it's a class object. // create it if necessary @@ -225,22 +99,22 @@ export class NewModelsNamespace extends Namespace { const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); + const mc = schema.language.csharp?.classImplementation || new ModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; + return schema.language.csharp?.interfaceImplementation; } if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { return td; } - if (td instanceof NewEnumImplementation) { + if (td instanceof EnumImplementation) { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { - new NewEnumClass(td, state); - // return schema.language.csharp.typeDeclaration = ec[0]; + new EnumClass(td, state); + // return schema.language.csharp.typeDeclaration = ec[0]; } } schema.language.csharp = schema.language.csharp || new Language(); diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index 014eee82945..94a82a74ee4 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -11,11 +11,10 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Property, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; -import { ModelClass } from './model-class'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; @@ -54,79 +53,15 @@ export class ModelProperty extends BackedProperty implements EnhancedVariable { return (this.type).validateValue(eventListener, this); } - private required: boolean; - // DISABLED - // public IsHeaderProperty: boolean; - public schema: Schema; - public serializedName: string; - private typeDeclaration: EnhancedTypeDeclaration; - public details: any; - - constructor(name: string, schema: Schema, isRequired: boolean, serializedName: string, description: string, state: State, objectInitializer?: DeepPartial) { - const decl = state.project.modelsNamespace.resolveTypeDeclaration(schema, isRequired, state.path('schema')); - super(name, decl); - this.typeDeclaration = decl; - this.serializedName = serializedName; - this.schema = schema; - if (this.schema.readOnly) { - this.set = undefined; - } - this.apply(objectInitializer); - this.description = description; - this.required = isRequired; - if (this.schema.type === JsonType.Object && isAnExpression(this.get) && schema.details.csharp.classImplementation) { - // for objects, the getter should auto-create a new object - this.get = toExpression(`(${this.get.value} = ${this.get.value} ?? new ${schema.details.csharp.fullname}())`); - } - } - - -} - -export class NewModelProperty extends BackedProperty implements EnhancedVariable { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, container, this, serializedName, mode); - } - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - if (this.required) { - return (this.type).validatePresence(eventListener, this); - } - return ''; - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return (this.type).validateValue(eventListener, this); - } - private required: boolean; // DISABLED // public IsHeaderProperty: boolean; public schema: NewSchema; public serializedName: string; - private typeDeclaration: NewEnhancedTypeDeclaration; + private typeDeclaration: EnhancedTypeDeclaration; public language: any; - constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: State, objectInitializer?: DeepPartial) { const decl = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, isRequired, state.path('schema')); super(name, decl); this.typeDeclaration = decl; diff --git a/powershell/llcsharp/operation/api-class.ts b/powershell/llcsharp/operation/api-class.ts index 34aa980a8be..1d66df80f69 100644 --- a/powershell/llcsharp/operation/api-class.ts +++ b/powershell/llcsharp/operation/api-class.ts @@ -6,79 +6,50 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Class, Namespace } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../generator'; -import { CallMethod, OperationMethod, NewOperationMethod, ValidationMethod, NewCallMethod, NewValidationMethod } from '../operation/method'; +import { State } from '../generator'; +import { OperationMethod, CallMethod, ValidationMethod } from '../operation/method'; import { ParameterLocation } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; export class ApiClass extends Class { // protected sender: Property; - constructor(namespace: Namespace, protected state: State | NewState, objectInitializer?: DeepPartial) { - super(namespace, (state instanceof NewState) ? state.model.language.csharp?.name || '' : state.model.details.csharp.name); + constructor(namespace: Namespace, protected state: State, objectInitializer?: DeepPartial) { + super(namespace, state.model.language.csharp?.name || ''); this.apply(objectInitializer); // add basics // this.sender = this.add(new Property("Sender", ClientRuntime.ISendAsync)); // add operations from code model - if (!(state instanceof NewState)) { - for (const { key: operationIndex, value: operation } of items(state.model.http.operations)) { - // an operation has parameters for parameters, body, callbacks, listener and sender - // we need to make sure that the parameters for a given operation are consistent between the operation method, the call method, and the validation method. - // can we generate the common parameters here and just give them to the methods? (ie, can we share the instances between the methods?) - // code-dom doesn't store references from the child to the parent, so as long as the definitions work without modification, it looks like we can. - // we'll do that work in the OM and expose them as public properties. - const operationMethod = new OperationMethod(this, operation, false, state.path('components', 'operations', operationIndex)); + // todo + for (const operationGroup of state.model.operationGroups) { + for (const operation of operationGroup.operations) { + const operationMethod = new OperationMethod(this, operation, false, state); this.addMethod(operationMethod); - if ([...values(operation.parameters).select(each => each.in === ParameterLocation.Path)].length > 0) { + // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it + const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); + if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new OperationMethod(this, operation, true, state.path('components', 'operations', operationIndex)); + const identityMethod = new OperationMethod(this, operation, true, state); identityMethod.emitCall(false); this.addMethod(identityMethod); } // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new CallMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + const cm = new CallMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(cm)) { this.addMethod(cm); } - const vm = new ValidationMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + const vm = new ValidationMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(vm)) { this.addMethod(vm); } } - } else { - // todo - for (const operationGroup of state.model.operationGroups) { - for (const operation of operationGroup.operations) { - const operationMethod = new NewOperationMethod(this, operation, false, state); - this.addMethod(operationMethod); - // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it - const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); - if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { - // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new NewOperationMethod(this, operation, true, state); - identityMethod.emitCall(false); - this.addMethod(identityMethod); - } - - // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new NewCallMethod(this, operationMethod, state); - if (!this.hasMethodWithSameDeclaration(cm)) { - this.addMethod(cm); - } - - const vm = new NewValidationMethod(this, operationMethod, state); - if (!this.hasMethodWithSameDeclaration(vm)) { - this.addMethod(vm); - } - } - } } } } diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 127dc877cce..aa4e6521316 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -24,20 +24,16 @@ import { Using } from '@azure-tools/codegen-csharp'; import { Local, LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { HttpOperation, Schema } from '../code-model'; -import { State, NewState } from '../generator'; -import { CallbackParameter, NewCallbackParameter, OperationBodyParameter, OperationParameter, NewOperationParameter, NewOperationBodyParameter } from '../operation/parameter'; +import { State } from '../generator'; +import { CallbackParameter, OperationParameter, OperationBodyParameter } from '../operation/parameter'; import { isMediaTypeJson, isMediaTypeXml, KnownMediaType, knownMediaType, normalizeMediaType, parseMediaType } from '@azure-tools/codemodel-v3'; import { ClassType, dotnet, System } from '@azure-tools/codegen-csharp'; import { Ternery } from '@azure-tools/codegen-csharp'; -function removeEncoding(pp: OperationParameter, paramName: string, kmt: KnownMediaType): string { - const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; - return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; -} -function newRemoveEncoding(pp: NewOperationParameter, paramName: string, kmt: KnownMediaType): string { +function removeEncoding(pp: OperationParameter, paramName: string, kmt: KnownMediaType): string { const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; } @@ -89,218 +85,7 @@ export class OperationMethod extends Method { protected callName: string; - constructor(protected parent: Class, public operation: HttpOperation, public viaIdentity: boolean, protected state: State, objectInitializer?: DeepPartial) { - super(viaIdentity ? `${operation.details.csharp.name}ViaIdentity` : operation.details.csharp.name, System.Threading.Tasks.Task()); - this.apply(objectInitializer); - this.async = Modifier.Async; - this.returnsDescription = `A that will be complete when handling of the response is completed.`; - const $this = this; - - this.callName = `${operation.details.csharp.name}_Call`; - this.push(Using('NoSynchronizationContext', '')); - - // add parameters - this.methodParameters = []; - - const identity = new Parameter('viaIdentity', System.String); - if (this.viaIdentity) { - this.addParameter(identity); - } - - for (let index = 0; index < length(this.operation.parameters); index++) { - const value = this.operation.parameters[index]; - - const p = new OperationParameter(this, value, this.state.path('parameters', index)); - - if (value.details.csharp.constantValue) { - const constTd = state.project.modelsNamespace.resolveTypeDeclaration(value.schema, true, state); - p.defaultInitializer = constTd.deserializeFromString(KnownMediaType.UriParameter, new StringExpression(`${value.details.csharp.constantValue}`), toExpression(constTd.defaultOfType)); - } - - // don't add path parameters when we're in identity mode - if (!this.viaIdentity || value.in !== ParameterLocation.Path) { - this.addParameter(p); - } else { - this.add(function* () { - yield ''; - }); - } - this.methodParameters.push(p); - } - - this.description = this.operation.details.csharp.description; - - // add body paramter if there should be one. - if (this.operation.requestBody) { - // this request does have a request body. - this.bodyParameter = new OperationBodyParameter(this, 'body', this.operation.requestBody.description || '', this.operation.requestBody.schema, this.operation.requestBody.required, this.state.path('requestBody'), { - mediaType: knownMediaType(this.operation.requestBody.contentType), - contentType: this.operation.requestBody.contentType - }); - this.addParameter(this.bodyParameter); - } - - for (const responses of values(this.operation.responses)) { - for (const response of values(responses)) { - const responseType = response.schema ? state.project.modelsNamespace.resolveTypeDeclaration(response.schema, true, state) : null; - const headerType = response.headerSchema ? state.project.modelsNamespace.resolveTypeDeclaration(response.headerSchema, true, state) : null; - - const newCallbackParameter = new CallbackParameter(response.details.csharp.name, responseType, headerType, this.state, { description: response.details.csharp.description }); - this.addParameter(newCallbackParameter); - this.callbacks.push(newCallbackParameter); - - } - } - - // add eventhandler parameter - this.contextParameter = this.addParameter(new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive events.` })); - - // add optional parameter for sender - this.senderParameter = this.addParameter(new Parameter('sender', ClientRuntime.ISendAsync, { description: `an instance of an ${ClientRuntime.ISendAsync} pipeline to use to make the request.` })); - - let rx = this.operation.path; - // For post API, Some URI may contain an action string .e.x '/start' at the end - // of the URI, for such cases, we will drop the action string if identityCorrection - // is set in the configuration - if (this.operation.method === 'post' && this.state.project.identityCorrection) { - const idx = rx.lastIndexOf('/'); - rx = rx.substr(0, idx); - } - - - let url = `${this.operation.baseUrl}${this.operation.path.startsWith('/') ? this.operation.path.substr(1) : this.operation.path}`; - - - const serverParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Uri); - - const headerParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Header); - const pathParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Path); - const queryParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Query); - const cookieParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Cookie); - - // replace any server params in the uri - for (const pp of serverParams) { - url = url.replace(`{${pp.param.name}}`, `" - + ${pp.name} - + "`); - } - - for (const pp of pathParams) { - rx = rx.replace(`{${pp.param.name}}`, `(?<${pp.param.name}>[^/]+)`); - - if (this.viaIdentity) { - url = url.replace(`{${pp.param.name}}`, `" - + ${pp.name} - + "`); - } else { - url = url.replace(`{${pp.param.name}}`, `" - + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} - + "`); - } - } - rx = `"^${rx}$"`; - url = url.replace(/\s*\+ ""/gm, ''); - - const bp = this.bodyParameter; - // add method implementation... - - this.add(function* () { - const eventListener = new EventListener($this.contextParameter, $this.state.project.emitSignals); - - yield EOL; - - if ($this.viaIdentity) { - yield '// verify that Identity format is an exact match for uri'; - yield EOL; - - const match = Local('_match', `${System.Text.RegularExpressions.Regex.new(rx).value}.Match(${identity.value})`); - yield match.declarationStatement; - yield If(`!${match}.Success`, `throw new global::System.Exception("Invalid identity for URI '${$this.operation.path}'");`); - yield EOL; - yield '// replace URI parameters with values from identity'; - for (const pp of pathParams) { - yield `var ${pp.name} = ${match.value}.Groups["${pp.param.name}"].Value;`; - } - } - - yield '// construct URL'; - const urlV = new LocalVariable('_url', dotnet.Var, { - initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( - "${url}" - ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${removeEncoding(pp, pp.param.name, KnownMediaType.QueryParameter)}`, ` - + "&"` - )} - ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) - }); - yield urlV.declarationStatement; - - yield EOL; - - yield eventListener.signal(ClientRuntime.Events.URLCreated, urlV.value); - yield EOL; - - yield '// generate request object '; - yield `var request = ${System.Net.Http.HttpRequestMessage.new(`${ClientRuntime.fullName}.Method.${$this.operation.method.capitalize()}, ${urlV.value}`)};`; - yield eventListener.signal(ClientRuntime.Events.RequestCreated, urlV.value); - yield EOL; - - if (length(headerParams) > 0) { - yield '// add headers parameters'; - for (const hp of headerParams) { - if (hp.param.name === 'Content-Length') { - // content length is set when the request body is set - continue; - } - yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.name, ClientRuntime.SerializationMode.None); - } - yield EOL; - } - yield eventListener.signal(ClientRuntime.Events.HeaderParametersAdded, urlV.value); - - if (bp) { - yield '// set body content'; - yield `request.Content = ${bp.serializeToContent(bp.mediaType, ClientRuntime.SerializationMode.None)};`; - yield `request.Content.Headers.ContentType = ${System.Net.Http.Headers.MediaTypeHeaderValue.Parse(bp.contentType)};`; - yield eventListener.signal(ClientRuntime.Events.BodyContentSet, urlV.value); - } - - yield '// make the call '; - }); - } - - emitCall(returnFromCall: boolean) { - - // storage will return from the call for download, etc. - if (returnFromCall) { - this.returnType = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); - } - - this.add(`await this.${this.callName}(request,${this.callbacks.joinWith(each => each.use, ',')},${this.contextParameter.use},${this.senderParameter.use});`); - - // remove constant parameters and make them locals instead. - this.insert('// Constant Parameters'); - for (let i = length(this.parameters); i--; i < 0) { - const p = this.parameters[i]; - if (p && p.defaultInitializer) { - this.parameters.splice(i, 1); - this.insert(new LocalVariable(p.name, dotnet.Var, { initializer: p.defaultInitializer })); - } - } - } -} - -export class NewOperationMethod extends Method { - public methodParameters: Array; - public bodyParameter?: NewOperationBodyParameter; - public contextParameter!: Parameter; - public senderParameter!: Parameter; - public resourceUri!: Parameter; - public callbacks = new Array(); - - protected callName: string; - - constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: State, objectInitializer?: DeepPartial) { super(viaIdentity ? `${operation.language.csharp?.name}ViaIdentity` : operation.language.csharp?.name || '', System.Threading.Tasks.Task()); this.apply(objectInitializer); this.async = Modifier.Async; @@ -325,7 +110,7 @@ export class NewOperationMethod extends Method { baseUrl = value.clientDefaultValue; continue; } - const p = new NewOperationParameter(this, value, this.state.path('parameters', index)); + const p = new OperationParameter(this, value, this.state.path('parameters', index)); if (value.language.csharp?.constantValue) { const constTd = state.project.modelsNamespace.NewResolveTypeDeclaration(value.schema, true, state); @@ -350,7 +135,7 @@ export class NewOperationMethod extends Method { // this request does have a request body. const param = this.operation.requests[0].parameters.find((p) => !p.origin || p.origin.indexOf('modelerfour:synthesized') < 0); if (param) { - this.bodyParameter = new NewOperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { + this.bodyParameter = new OperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { // TODO: temp solution. We need a class like NewKnowMediaType mediaType: knownMediaType(KnownMediaType.Json), contentType: KnownMediaType.Json @@ -362,7 +147,7 @@ export class NewOperationMethod extends Method { for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { const responseType = (response).schema ? state.project.modelsNamespace.NewResolveTypeDeclaration(((response).schema), true, state) : null; const headerType = response.language.default.headerSchema ? state.project.modelsNamespace.NewResolveTypeDeclaration(response.language.default.headerSchema, true, state) : null; - const newCallbackParameter = new NewCallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); + const newCallbackParameter = new CallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); this.addParameter(newCallbackParameter); this.callbacks.push(newCallbackParameter); @@ -411,7 +196,7 @@ export class NewOperationMethod extends Method { + "`); } else { url = url.replace(`{${pp.param.language.default.serializedName}}`, `" - + ${newRemoveEncoding(pp, '', KnownMediaType.UriParameter)} + + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} + "`); } } @@ -445,7 +230,7 @@ export class NewOperationMethod extends Method { initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( "${url}" ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${newRemoveEncoding(pp, pp.param.language.default.serializedName, KnownMediaType.QueryParameter)}`, ` + + ${removeEncoding(pp, pp.param.language.default.serializedName, KnownMediaType.QueryParameter)}`, ` + "&"` )} ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) @@ -510,8 +295,8 @@ export class NewOperationMethod extends Method { export class CallMethod extends Method { public returnNull = false; constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { - super(`${opMethod.operation.details.csharp.name}_Call`, System.Threading.Tasks.Task()); - this.description = `Actual wire call for method.`; + super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); + this.description = `Actual wire call for method.`; this.returnsDescription = opMethod.returnsDescription; this.apply(objectInitializer); @@ -545,17 +330,18 @@ export class CallMethod extends Method { // add response handlers yield Switch(`${response}.StatusCode`, function* () { - for (const { key: responseCode, value: responses } of items(opMethod.operation.responses)) { - if (responseCode !== 'default') { + for (const responses of [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)]) { + if (responses.protocol.http?.statusCodes[0] !== 'default') { + const responseCode = responses.protocol.http?.statusCodes[0]; // will use enum when it can, fall back to casting int when it can't - yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.responsesEmitter($this, opMethod, responses, eventListener)); + yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.responsesEmitter($this, opMethod, [responses], eventListener)); } else { - yield DefaultCase($this.responsesEmitter($this, opMethod, responses, eventListener)); + yield DefaultCase($this.responsesEmitter($this, opMethod, [responses], eventListener)); } } // missing default response? - if (!opMethod.operation.responses.default) { + if (!opMethod.operation.exceptions) { // if no default, we need one that handles the rest of the stuff. yield TerminalDefaultCase(function* () { yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`; @@ -571,13 +357,13 @@ export class CallMethod extends Method { yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value); const EOL = 'EOL'; // LRO processing (if appropriate) - if ($this.opMethod.operation.details.csharp.lro) { + if ($this.opMethod.operation.language.csharp?.lro) { yield '// this operation supports x-ms-long-running-operation'; const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`)); yield originalUri; - yield `// declared final-state-via: ${$this.opMethod.operation.details.csharp.lro['final-state-via']}`; - const fsv = $this.opMethod.operation.details.csharp.lro['final-state-via']; + yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`; + const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via']; let finalUri: LocalVariable; switch (fsv) { @@ -591,11 +377,10 @@ export class CallMethod extends Method { finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); yield finalUri; break; - case 'azure-asyncoperation': case 'azure-async-operation': - // depending on the type of request, do the appropriate behavior - switch ($this.opMethod.operation.method.toLowerCase()) { + //depending on the type of request, do the appropriate behavior + switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) { case 'post': case 'delete': finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); @@ -611,19 +396,20 @@ export class CallMethod extends Method { default: // depending on the type of request, fall back to the appropriate behavior - switch ($this.opMethod.operation.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; + if ($this.opMethod.operation.requests) { + switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) { + case 'post': + case 'delete': + finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield finalUri; + break; + case 'patch': + case 'put': + // perform a final GET on the original URI. + finalUri = originalUri; + break; + } } - break; } @@ -782,20 +568,20 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield 'break;'; } - private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { + private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { if (length(responses) > 1) { yield Switch('_contentType', function* () { for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); + const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); - let count = length(eachResponse.mimeTypes); - for (const mt of values(eachResponse.mimeTypes)) { + let count = length(eachResponse.protocol.http?.mediaTypes); + for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { count--; - const mediaType = normalizeMediaType(mt); + const mediaType = normalizeMediaType(mt); if (mediaType) { if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.responseHandler(mimetype, eachResponse, callbackParameter)); + yield Case(new StringExpression(mediaType).toString(), $this.NewResponseHandler(mimetype, eachResponse, callbackParameter)); } else { yield TerminalCase(new StringExpression(mediaType).toString(), ''); } @@ -805,14 +591,13 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) }); } else { const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); // all mimeTypes per for this response code. yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); + yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); } } - private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { const callbackParameters = new Array(); @@ -841,390 +626,22 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - public responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { - return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); - } -} -export class NewCallMethod extends Method { - public returnNull = false; - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { - super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); - this.description = `Actual wire call for method.`; - this.returnsDescription = opMethod.returnsDescription; - - this.apply(objectInitializer); - this.access = Access.Internal; - this.async = Modifier.Async; - this.push(Using('NoSynchronizationContext', '')); + private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { + const callbackParameters = new Array(); - const $this = this; - // add parameters - // request, listener, sender - const reqParameter = this.addParameter(new Parameter('request', System.Net.Http.HttpRequestMessage, { description: 'the prepared HttpRequestMessage to send.' })); - opMethod.callbacks.forEach(each => this.addParameter(each)); + if (callbackParameter.responseType) { + // hande the body response + const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); + if (r) { - this.addParameter(opMethod.contextParameter); - this.addParameter(opMethod.senderParameter); + callbackParameters.push(r); + } - // add statements to this method - this.add(function* () { - const eventListener = new EventListener(opMethod.contextParameter, $this.state.project.emitSignals); - - const response = Local('_response', dotnet.Null, System.Net.Http.HttpResponseMessage); - yield response; - yield Try(function* () { - - const responder = function* () { - // TODO: omit generating _contentType var if it will never be used - // const contentType = new LocalVariable('_contentType', dotnet.Var, { initializer: `_response.Content.Headers.ContentType?.MediaType` }); - const contentType = Local('_contentType', `${response}.Content.Headers.ContentType?.MediaType`); - - yield contentType; - - // add response handlers - yield Switch(`${response}.StatusCode`, function* () { - for (const responses of [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)]) { - if (responses.protocol.http?.statusCodes[0] !== 'default') { - const responseCode = responses.protocol.http?.statusCodes[0]; - // will use enum when it can, fall back to casting int when it can't - yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); - } else { - yield DefaultCase($this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); - } - } - - // missing default response? - if (!opMethod.operation.exceptions) { - // if no default, we need one that handles the rest of the stuff. - yield TerminalDefaultCase(function* () { - yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`; - }); - } - }); - }; - - // try statements - yield eventListener.signal(ClientRuntime.Events.BeforeCall, reqParameter.use); - yield `${response.value} = await ${opMethod.senderParameter.value}.SendAsync(${reqParameter.use}, ${opMethod.contextParameter.value});`; - - yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value); - const EOL = 'EOL'; - // LRO processing (if appropriate) - if ($this.opMethod.operation.language.csharp?.lro) { - yield '// this operation supports x-ms-long-running-operation'; - const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`)); - yield originalUri; - - yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`; - const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via']; - let finalUri: LocalVariable; - - switch (fsv) { - case 'original-uri': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - - case 'location': - // perform a final GET on the uri in Location header - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'azure-asyncoperation': - case 'azure-async-operation': - //depending on the type of request, do the appropriate behavior - switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - } - break; - - default: - // depending on the type of request, fall back to the appropriate behavior - if ($this.opMethod.operation.requests) { - switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - } - } - break; - - } - - const asyncOperation = Local('asyncOperation', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield asyncOperation; - const location = Local('location', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield location; - - yield While(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), function* () { - yield EOL; - yield '// get the delay before polling. (default to 30 seconds if not present)'; - yield `int delay = (int)(${response.value}.Headers.RetryAfter?.Delta?.TotalSeconds ?? 30);`; - // yield If(`!int.TryParse( ${response.invokeMethod('GetFirstHeader', new StringExpression(`Retry-After`)).value}, out int delay)`, `delay = 30;`); - - yield eventListener.signal(ClientRuntime.Events.DelayBeforePolling, '$"Delaying {delay} seconds before polling."', response.value); - - yield EOL; - yield '// start the delay timer (we\'ll await later...)'; - const waiting = Local('waiting', new LiteralExpression(`${System.Threading.Tasks.Task()}.Delay(delay * 1000, ${$this.opMethod.contextParameter}.Token )`)); - yield waiting; - - yield EOL; - yield '// while we wait, let\'s grab the headers and get ready to poll. '; - yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {'; - yield ' ' + asyncOperation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield '}'; - yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {'; - yield ' ' + location.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield '}'; - const uriLocal = Local('_uri', Ternery( - System.String.IsNullOrEmpty(asyncOperation), - Ternery(System.String.IsNullOrEmpty(location), - originalUri, - location), - asyncOperation)); - yield uriLocal; - - yield `${reqParameter.use} = ${reqParameter.use}.CloneAndDispose(${System.Uri.new(uriLocal)}, ${ClientRuntime.Method.Get});`; - - yield EOL; - yield '// and let\'s look at the current response body and see if we have some information we can give back to the listener'; - const content = Local('content', new LiteralExpression(`await ${response.value}.Content.ReadAsStringAsync()`)); - yield content; - - yield 'await waiting;'; - - yield EOL; - yield '// check for cancellation'; - yield `if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; }`; - - yield eventListener.signal(ClientRuntime.Events.Polling, `$"Polling {${uriLocal}}."`, response.value); - - yield EOL; - yield '// drop the old response'; - yield `${response.value}?.Dispose();`; - - yield EOL; - yield '// make the polling call'; - yield `${response.value} = await ${opMethod.senderParameter}.SendAsync(${reqParameter.value}, ${opMethod.contextParameter});`; - - - yield EOL; - yield ` -// if we got back an OK, take a peek inside and see if it's done -if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) -{ - try { - if( ${ClientRuntime.JsonNode.Parse(toExpression(`await ${response.value}.Content.ReadAsStringAsync()`))} is ${ClientRuntime.JsonObject} json) - { - var state = json.Property("properties")?.PropertyT<${ClientRuntime.JsonString}>("provisioningState") ?? json.PropertyT<${ClientRuntime.JsonString}>("status"); - if( state is null ) - { - // the body doesn't contain any information that has the state of the LRO - // we're going to just get out, and let the consumer have the result - break; - } - await ${$this.opMethod.contextParameter}.Signal(${ClientRuntime.Events.Polling}, $"Polled {${uriLocal}} provisioning state {state}.", ${response.value}); if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; } - - switch( state?.ToString()?.ToLower() ) - { - case "succeeded": - case "failed": - case "canceled": - // we're done polling. - break; - - default: - // need to keep polling! - ${response.value}.StatusCode = ${System.Net.HttpStatusCode.Created}; - continue; - } - } - } catch { - // if we run into a problem peeking into the result, - // we really don't want to do anything special. - } -}`; - - yield EOL; - yield '// check for terminal status code'; - yield If(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), 'continue;'); - - yield '// we are done polling, do a request on final target?'; - - switch (fsv) { - case 'original-uri': - case 'azure-asyncoperation': - case 'azure-async-operation': - case 'location': - // perform a final GET on the specified final URI. - yield $this.finalGet(finalUri, reqParameter, response); - break; - - default: - yield If(`!string.IsNullOrWhiteSpace(${finalUri})`, function* () { - yield $this.finalGet(finalUri, reqParameter, response); - }); - break; - } - }); - - } - yield responder(); - }); - - yield Finally(function* () { - yield '// finally statements'; - yield eventListener.signalNoCheck(ClientRuntime.Events.Finally, 'request', '_response'); - yield `${response.value}?.Dispose();`; - yield `${reqParameter.use}?.Dispose();`; - }); - - if ($this.returnNull) { - yield Return('result'); - $this.insert(new LocalVariable('result', System.Net.Http.HttpResponseMessage, { initializer: dotnet.Null })); - } - }); - - this.opMethod.emitCall($this.returnNull); - } - - private * finalGet(finalLocation: ExpressionOrLiteral, reqParameter: Variable, response: Variable) { - yield '// create a new request with the final uri'; - yield reqParameter.assign(`${valueOf(reqParameter)}.CloneAndDispose(${System.Uri.new(finalLocation)}, ${ClientRuntime.Method.Get})`); - - yield EOL; - yield '// drop the old response'; - yield `${response.value}?.Dispose();`; - - yield EOL; - yield '// make the final call'; - yield response.assign(`await ${this.opMethod.senderParameter}.SendAsync(${valueOf(reqParameter)}, ${this.opMethod.contextParameter})`); - - // make sure we're not polling anymore. - yield 'break;'; - } - - private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { - if (length(responses) > 1) { - yield Switch('_contentType', function* () { - for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); - - let count = length(eachResponse.mimeTypes); - for (const mt of values(eachResponse.mimeTypes)) { - count--; - const mediaType = normalizeMediaType(mt); - if (mediaType) { - if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.responseHandler(mimetype, eachResponse, callbackParameter)); - } else { - yield TerminalCase(new StringExpression(mediaType).toString(), ''); - } - } - } - } - }); - } else { - const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); - // all mimeTypes per for this response code. - yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); - } - } - - private * NewResponsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { - if (length(responses) > 1) { - yield Switch('_contentType', function* () { - for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); - - let count = length(eachResponse.protocol.http?.mediaTypes); - for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { - count--; - const mediaType = normalizeMediaType(mt); - if (mediaType) { - if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.NewResponseHandler(mimetype, eachResponse, callbackParameter)); - } else { - yield TerminalCase(new StringExpression(mediaType).toString(), ''); - } - } - } - } - }); - } else { - const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); - // all mimeTypes per for this response code. - yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); - } - } - - private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { - const callbackParameters = new Array(); - - if (callbackParameter.responseType) { - // hande the body response - const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); - if (r) { - - callbackParameters.push(r); - } - - // if (parseMediaType(mimetype)) { - // this media type isn't directly supported by deserialization - // we can return a stream to the consumer instead - // } - } - - if (callbackParameter.headerType) { - // header model deserialization... - const r = callbackParameter.headerType.deserializeFromResponse(KnownMediaType.Header, toExpression('_response'), toExpression('null')); - if (r) { - callbackParameters.push(r); - } - } - // make the callback with the appropriate parameters - yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; - } - - private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { - const callbackParameters = new Array(); - - if (callbackParameter.responseType) { - // hande the body response - const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); - if (r) { - - callbackParameters.push(r); - } - - // if (parseMediaType(mimetype)) { - // this media type isn't directly supported by deserialization - // we can return a stream to the consumer instead - // } - } + // if (parseMediaType(mimetype)) { + // this media type isn't directly supported by deserialization + // we can return a stream to the consumer instead + // } + } if (callbackParameter.headerType) { // header model deserialization... @@ -1247,48 +664,6 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) export class ValidationMethod extends Method { constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { - super(`${opMethod.operation.details.csharp.name}_Validate`, System.Threading.Tasks.Task()); - this.apply(objectInitializer); - this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; - this.returnsDescription = opMethod.returnsDescription; - this.access = Access.Internal; - this.async = Modifier.Async; - this.push(Using('NoSynchronizationContext', '')); - - // add the method parameters - for (const parameter of opMethod.methodParameters) { - if (!parameter.defaultInitializer) { - this.addParameter(parameter); - } - } - - if (opMethod.bodyParameter) { - this.addParameter(opMethod.bodyParameter); - } - - this.addParameter(opMethod.contextParameter); - - // add statements to this method - this.add(function* () { - for (const parameter of opMethod.methodParameters) { - if (!parameter.defaultInitializer) { - // spit out parameter validation - yield parameter.validatePresenceStatement(opMethod.contextParameter); - yield parameter.validationStatement(opMethod.contextParameter); - } - } - - // spit out body parameter validation too - if (opMethod.bodyParameter) { - yield opMethod.bodyParameter.validatePresenceStatement(opMethod.contextParameter); - yield opMethod.bodyParameter.validationStatement(opMethod.contextParameter); - } - }); - } -} -export class NewValidationMethod extends Method { - - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { super(`${opMethod.name}_Validate`, System.Threading.Tasks.Task()); this.apply(objectInitializer); this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; diff --git a/powershell/llcsharp/operation/namespace.ts b/powershell/llcsharp/operation/namespace.ts index f2c8d1d854d..22f6a2736a6 100644 --- a/powershell/llcsharp/operation/namespace.ts +++ b/powershell/llcsharp/operation/namespace.ts @@ -6,12 +6,12 @@ import { ImportDirective } from '@azure-tools/codegen-csharp'; import { Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State, NewState } from '../generator'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class ServiceNamespace extends Namespace { - constructor(public state: State | NewState, objectInitializer?: DeepPartial) { - super(state instanceof NewState ? state.model.language.csharp?.namespace : state.model.details.csharp.namespace || 'INVALID-NAMESPACE', state.project); + constructor(public state: State, objectInitializer?: DeepPartial) { + super(state.model.language.csharp?.namespace, state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); } diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index ea6f207eaa3..e46c779bedb 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -15,64 +15,18 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { HttpOperationParameter, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; /** represents a method parameter for an http operation (header/cookie/query/path) */ + export class OperationParameter extends Parameter implements EnhancedVariable { public typeDeclaration: EnhancedTypeDeclaration; - public param: HttpOperationParameter; - - constructor(parent: Method, param: HttpOperationParameter, state: State, objectInitializer?: DeepPartial) { - const typeDeclaration = state.project.modelsNamespace.resolveTypeDeclaration(param.schema, param.required, state.path('schema')); - super(param.details.csharp.name, typeDeclaration); - this.param = param; - this.typeDeclaration = typeDeclaration; - this.apply(objectInitializer); - this.description = param.details.csharp.description || ''; - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)) - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); - } - - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validatePresence(eventListener, this); - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validateValue(eventListener, this); - } -} - -export class NewOperationParameter extends Parameter implements EnhancedVariable { - public typeDeclaration: NewEnhancedTypeDeclaration; - public param: NewHttpOperationParameter; - constructor(parent: Method, param: NewHttpOperationParameter, state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Method, param: NewHttpOperationParameter, state: State, objectInitializer?: DeepPartial) { const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(param.schema, !!param.required, state); super(param.language.csharp?.name || '', typeDeclaration); this.param = param; @@ -115,6 +69,7 @@ export class NewOperationParameter extends Parameter implements EnhancedVariable } /** represents a method parameter for an http operation (body) */ + export class OperationBodyParameter extends Parameter implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { @@ -154,67 +109,7 @@ export class OperationBodyParameter extends Parameter implements EnhancedVariabl public typeDeclaration: EnhancedTypeDeclaration; - constructor(parent: Method, name: string, description: string, schema: Schema, required: boolean, state: State, objectInitializer?: DeepPartial) { - const typeDeclaration = state.project.modelsNamespace.resolveTypeDeclaration(schema, required, state.path('schema')); - super(name, typeDeclaration); - this.typeDeclaration = typeDeclaration; - this.mediaType = KnownMediaType.Json; - this.contentType = KnownMediaType.Json; - - this.apply(objectInitializer); - this.description = description || schema.details.csharp.description; - } - - public get jsonSerializationStatement(): OneOrMoreStatements { - // get the body serialization from the typeDeclaration. - - return '/* body parameter */';// (this.type).jsonserialize(this.name); - } - public get jsonDeserializationStatement(): OneOrMoreStatements { - return '/* body parameter */';// (this.type).jsonDeserializationImplementation(this.name); - } -} - -export class NewOperationBodyParameter extends Parameter implements EnhancedVariable { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)); - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - // return this.assign(this.typeDeclaration.deserializeFromNode(mediaType, node, this)); - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); - } - - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validatePresence(eventListener, this); - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validateValue(eventListener, this); - } - public mediaType: KnownMediaType; - public contentType: string; - - public typeDeclaration: NewEnhancedTypeDeclaration; - - constructor(parent: Method, name: string, description: string, schema: NewSchema, required: boolean, state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Method, name: string, description: string, schema: NewSchema, required: boolean, state: State, objectInitializer?: DeepPartial) { const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, required, state.path('schema')); super(name, typeDeclaration); this.typeDeclaration = typeDeclaration; @@ -235,6 +130,7 @@ export class NewOperationBodyParameter extends Parameter implements EnhancedVari } } + export class CallbackParameter extends Parameter { responseType: (EnhancedTypeDeclaration) | null; headerType: (EnhancedTypeDeclaration) | null; @@ -259,36 +155,6 @@ export class CallbackParameter extends Parameter { } } - this.responseType = responseType; - this.headerType = headerType; - this.apply(objectInitializer); - } -} - -export class NewCallbackParameter extends Parameter { - responseType: (NewEnhancedTypeDeclaration) | null; - headerType: (NewEnhancedTypeDeclaration) | null; - - constructor(name: string, responseType: (NewEnhancedTypeDeclaration) | null, headerType: (NewEnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { - // regular pipeline style. (callback happens after the pipline is called) - if (responseType) { - if (headerType) { - // both - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); - } else { - // just response - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task())); - } - } else { - if (headerType) { - // just headers - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); - } else { - // no content? - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task())); - } - } - this.responseType = responseType; this.headerType = headerType; this.apply(objectInitializer); diff --git a/powershell/llcsharp/project.ts b/powershell/llcsharp/project.ts index e20ffe398bb..650a8f9ae22 100644 --- a/powershell/llcsharp/project.ts +++ b/powershell/llcsharp/project.ts @@ -7,14 +7,13 @@ import { Host } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { State, NewState } from './generator'; -import { ModelsNamespace, NewModelsNamespace } from './model/namespace'; +import { State } from './generator'; +import { ModelsNamespace } from './model/namespace'; import { ApiClass } from './operation/api-class'; import { ServiceNamespace } from './operation/namespace'; import { SupportNamespace } from './enums/namespace'; import { DeepPartial } from '@azure-tools/codegen'; - export class Project extends codeDomProject { public jsonSerialization = true; @@ -48,7 +47,7 @@ export class Project extends codeDomProject { // add project namespace - this.projectNamespace = this.state.model.details.csharp.namespace; + this.projectNamespace = this.state.model.language.csharp?.namespace; this.overrides = { 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, @@ -91,82 +90,4 @@ export class Project extends codeDomProject { public serviceNamespace!: ServiceNamespace; public modelsNamespace!: ModelsNamespace; public supportNamespace!: SupportNamespace; -} - -export class NewProject extends codeDomProject { - - public jsonSerialization = true; - public xmlSerialization = false; - public defaultPipeline = true; - public emitSignals = true; - public projectNamespace!: string; - public overrides!: Dictionary; - protected state!: NewState; - - apifolder!: string; - runtimefolder!: string; - azure!: boolean; - license!: string; - identityCorrection!: boolean; - - constructor(protected service: Host, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - - public async init(): Promise { - await super.init(); - - this.state = await new NewState(this.service).init(this); - this.apifolder = await this.state.getValue('api-folder', ''); - this.runtimefolder = await this.state.getValue('runtime-folder', 'runtime'); - this.azure = await this.state.getValue('azure', false) || await this.state.getValue('azure-arm', false); - this.identityCorrection = await this.state.getValue('identity-correction-for-post', false); - this.license = await this.state.getValue('header-text', ''); - - - // add project namespace - this.projectNamespace = this.state.model.language.csharp?.namespace; - this.overrides = { - 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, - 'using Converters;': '', - 'using Internal.Extensions;': '', - 'using Data;': '', - 'using Parser;': '', - - 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, - 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, - 'Microsoft.Rest': this.projectNamespace - }; - - this.serviceNamespace = new ServiceNamespace(this.state); - this.serviceNamespace.header = this.license; - this.addNamespace(this.serviceNamespace); - - // add support namespace - this.supportNamespace = new SupportNamespace(this.serviceNamespace, this.state); - this.supportNamespace.header = this.license; - this.addNamespace(this.supportNamespace); - - // add model classes - this.modelsNamespace = new NewModelsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); - this.modelsNamespace.header = this.license; - this.addNamespace(this.modelsNamespace); - - // create API class - new ApiClass(this.serviceNamespace, this.state, { description: `Low-level API implementation for the ${this.state.model.info.title} service. \n${this.state.model.info.description || ''}` }); - - // abort now if we have any errors. - this.state.checkpoint(); - - return this; - } - - public serviceNamespace!: ServiceNamespace; - public modelsNamespace!: NewModelsNamespace; - public supportNamespace!: SupportNamespace; } \ No newline at end of file diff --git a/powershell/llcsharp/schema/Uuid.ts b/powershell/llcsharp/schema/Uuid.ts index 55486b5dedf..75034805561 100644 --- a/powershell/llcsharp/schema/Uuid.ts +++ b/powershell/llcsharp/schema/Uuid.ts @@ -7,25 +7,10 @@ import { nameof } from '@azure-tools/codegen'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { StringSchema } from '@azure-tools/codemodel'; -import { String, NewString } from './string'; +import { String } from './string'; -export class Uuid extends String { - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } - get declaration(): string { - return 'string'; - } - public validatePresence(eventListener: Variable, property: Variable): string { - return this.isRequired ? `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim() : ''; - } - validateValue(eventListener: Variable, property: Variable): string { - return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$");`; - } -} - -export class NewUuid extends NewString { +export class Uuid extends String { constructor(schema: StringSchema, isRequired: boolean) { super(schema, isRequired); } diff --git a/powershell/llcsharp/schema/array.ts b/powershell/llcsharp/schema/array.ts index 16794ca1772..9d1c35835d6 100644 --- a/powershell/llcsharp/schema/array.ts +++ b/powershell/llcsharp/schema/array.ts @@ -19,7 +19,7 @@ import { Schema as NewSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; export class ArrayOf implements EnhancedTypeDeclaration { public isXmlAttribute = false; @@ -28,255 +28,7 @@ export class ArrayOf implements EnhancedTypeDeclaration { return toExpression('null /* arrayOf */'); } - constructor(public schema: Schema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { - } - - - protected get isWrapped(): boolean { - return this.schema.xml && this.schema.xml.wrapped || false; - } - - protected get wrapperName(): string | undefined { - return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; - } - - protected get serializedName(): string | undefined { - if (this.schema instanceof NewSchema) { - return this.schema.serialization?.xml ? this.schema.serialization.xml.name : undefined; - } else { - return this.schema.xml ? this.schema.xml.name : undefined; - } - - } - get elementTypeDeclaration(): string { - return this.elementType.declaration; - } - - get declaration(): string { - return `${this.elementType.declaration}[]`; - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get convertObjectMethod() { - try { - const v = pushTempVar(); - const i = pushTempVar(); - // return `${v} => ${v} is string || !(${v} is global::System.Collections.IEnumerable) ? new ${this.declaration} { ${this.elementType.convertObjectMethod}(${v}) } : System.Linq.Enumerable.ToArray( System.Linq.Enumerable.Select( System.Linq.Enumerable.OfType((global::System.Collections.IEnumerable)${v}), ${this.elementType.convertObjectMethod}))` - return `${v} => TypeConverterExtensions.SelectToArray<${this.elementTypeDeclaration}>(${v}, ${this.elementType.convertObjectMethod})`; - } finally { - popTempVar(); - popTempVar(); - } - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // json array - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonArray}>("${serializedName}"), out var ${tmp}) ? ${this.deserializeFromNode(mediaType, tmp, toExpression('null'))} : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - if (this.isWrapped) { - // wrapped xml arrays will have a container around them. - return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}?.Element("${this.serializedName || serializedName}")`, defaultValue)}`); - } else { - // whereas non-wrapped will have all the elements in the container directly. - return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}`, defaultValue)}`); - } - } - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - const each = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp} , (${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}) ) )`; - - const deser = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(tmp, `(${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}`)); - - return toExpression(`If( ${valueOf(node)} as ${ClientRuntime.JsonArray}, out var ${tmp}) ? ${System.Func(this).new(`()=> ${valueOf(deser)} )`)}() : ${defaultValue}`); - } - case KnownMediaType.Xml: { - // XElement should be a container of items, right? - // if the reference doesn't define an XML schema then use its default name - //const defaultName = this.elementType.schema.details.csharp.name; - //const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp}.Elements("${this.elementType.schema.xml ? this.elementType.schema.xml.name || defaultName : defaultName}"), (${each})=> ${this.elementType.deserializeFromNode(mediaType, each, toExpression('null'))} ) )`; - - //return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? new System.Func<${this.elementType.declaration}[]>(()=> ${deser} )() : ${defaultValue}`); - } - } - } finally { - popTempVar(); - popTempVar(); - } - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonArray.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - } - return undefined; - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Xml: - case KnownMediaType.Json: { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - - try { - const each = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.Json: { - const serArray = `global::System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}))`; - return toExpression(`null != ${value} ? new ${ClientRuntime.XNodeArray}(${serArray}) : null`); - } - - case KnownMediaType.Xml: { - if (this.isWrapped) { - const name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; - return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); - } else { - throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); - } - } - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - return toExpression(`(null != ${value} && ${value}.Length > 0 ? "${value}=" + ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current, each) => current + "," + ( ${this.encode}(each?.ToString()??${System.String.Empty}) ))) : ${System.String.Empty})`); - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(`(null != ${value} ? ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - try { - const each = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - return System.Net.Http.StringContent.new( - `${(this.serializeToNode(mediaType, value, '', mode))}`, - System.Text.Encoding.UTF8); - } - case KnownMediaType.Xml: { - // if the reference doesn't define an XML schema then use its default name - const defaultName = this.elementType.schema.details.csharp.name; - return System.Net.Http.StringContent.new(Ternery( - IsNotNull(value), - `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, - System.String.Empty - ), System.Text.Encoding.UTF8); - } - - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(`(null != ${value} ? ${this.encode}(System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); - } - - } finally { - popTempVar(); - } - - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - try { - const each = pushTempVar(); - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const $this = this; - return If(`null != ${value}`, function* () { - const t = new LocalVariable(tmp, dotnet.Var, { initializer: `new ${ClientRuntime.XNodeArray}()` }); - yield t.declarationStatement; - yield ForEach(each, toExpression(value), `AddIf(${$this.elementType.serializeToNode(mediaType, each, '', mode)} ,${tmp}.Add);`); - yield `${container}.Add("${serializedName}",${tmp});`; - }); - } - case KnownMediaType.Xml: - if (this.isWrapped) { - return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; - } else { - return If(`null != ${value}`, ForEach(each, toExpression(value), `AddIf(${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}, ${container}.Add);`)); - } - } - } finally { - popTempVar(); - popTempVar(); - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `; - } - return ''; - } - validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - // check if the underlyingType has validation. - if (!this.elementType.validateValue(eventListener, new LocalVariable(`${property} [{ __i }]`, dotnet.Var))) { - return ''; - } - - return ` - if (${ property} != null ) { - for (int __i = 0; __i < ${ property}.Length; __i++) { - ${ this.elementType.validateValue(eventListener, new LocalVariable(`${property}[__i]`, dotnet.Var))} - } - } - `.trim(); - } -} - -export class NewArrayOf implements NewEnhancedTypeDeclaration { - public isXmlAttribute = false; - public isNullable = true; - get defaultOfType() { - return toExpression('null /* arrayOf */'); - } - - constructor(public schema: NewSchema, public isRequired: boolean, public elementType: NewEnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { + constructor(public schema: NewSchema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { } diff --git a/powershell/llcsharp/schema/binary.ts b/powershell/llcsharp/schema/binary.ts index da9c9a0bf8a..49091f193c8 100644 --- a/powershell/llcsharp/schema/binary.ts +++ b/powershell/llcsharp/schema/binary.ts @@ -10,85 +10,11 @@ import { Expression, ExpressionOrLiteral, toExpression } from '@azure-tools/code import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { BinarySchema } from '@azure-tools/codemodel'; -export class Binary implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - constructor(public schema: Schema, public isRequired: boolean) { - } - - get convertObjectMethod() { - return 'i=>i'; - } - public isNullable = true; - - get defaultOfType() { - return toExpression('null /* binary type */'); - } - - get declaration(): string { - return System.IO.Stream.declaration; - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - if (mediaType === KnownMediaType.Stream) { - // dunno. - } - if (mediaType === KnownMediaType.Json) { - return toExpression('null /* no need to deserialize a stream here */ '); - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return undefined; - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`${valueOf(content)}.Content.ReadAsStreamAsync()`); - } - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - if (mediaType === KnownMediaType.Stream) { - return toExpression(System.Net.Http.StreamContent.new(value)); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - if (mediaType === KnownMediaType.Json) { - return `/* shouldn't need to serialize binary for a ${mediaType} */`; - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - public validatePresence(eventListener: Variable, property: Variable): string { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - return ''; - } -} - -export class NewBinary implements NewEnhancedTypeDeclaration { +export class Binary implements EnhancedTypeDeclaration { public isXmlAttribute = false; constructor(public schema: BinarySchema, public isRequired: boolean) { } diff --git a/powershell/llcsharp/schema/boolean.ts b/powershell/llcsharp/schema/boolean.ts index 8942f25e507..342b75a0ea3 100644 --- a/powershell/llcsharp/schema/boolean.ts +++ b/powershell/llcsharp/schema/boolean.ts @@ -7,26 +7,9 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, BooleanSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; -export class Boolean extends Primitive { - isXmlAttribute = false; - jsonType = ClientRuntime.JsonBoolean; - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - - get declaration(): string { - return `bool${this.isRequired ? '' : '?'}`; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } -} - -export class NewBoolean extends NewPrimitive { +export class Boolean extends NewPrimitive { isXmlAttribute = false; jsonType = ClientRuntime.JsonBoolean; diff --git a/powershell/llcsharp/schema/byte-array.ts b/powershell/llcsharp/schema/byte-array.ts index 9d36914c92b..3a27284dbc4 100644 --- a/powershell/llcsharp/schema/byte-array.ts +++ b/powershell/llcsharp/schema/byte-array.ts @@ -12,7 +12,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { Schema as NewSchema, ByteArraySchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; export class ByteArray implements EnhancedTypeDeclaration { @@ -104,110 +104,6 @@ export class ByteArray implements EnhancedTypeDeclaration { return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; } - constructor(public schema: Schema, public isRequired: boolean) { - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - public validatePresence(eventListener: Variable, property: Variable): string { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - return ''; - } -} - -export class NewByteArray implements NewEnhancedTypeDeclaration { - public isXmlAttribute = false; - - get declaration(): string { - return 'byte[]'; - } - - get convertObjectMethod() { - return 'i => i'; - } - - public isNullable = true; - - get defaultOfType() { - return toExpression('null /* byte array */'); - } - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.Xml: { - return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}")?.Value, out var ${tmp}) ? System.Convert.FromBase64String(${tmp}.Replace("_","/").Replace("-","+").PadRight( ${tmp}.Length + ${tmp}.Length * 3 % 4, '=')) : ${defaultValue}`); - } - case KnownMediaType.Json: { - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmp}) ? System.Convert.FromBase64String( ((string)${tmp}).Replace("_","/").Replace("-","+").PadRight( ((string)${tmp}).Length + ((string)${tmp}).Length * 3 % 4, '=') ) : null`); - } - case KnownMediaType.Header: { - //const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? System.Convert.FromBase64String(${tmp}) : ${defaultValue}`); - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`${ClientRuntime.JsonString.new(`System.Convert.ToBase64String(${value})`)}`); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - try { - const b = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Xml: { - return `AddIf( null != ${value} ? ${System.Xml.Linq.XElement.new(serializedName, System.Convert.ToBase64String(value))} : null, ${container}.Add);`; - } - - case KnownMediaType.Json: { - return `AddIf( null != ${value} ? ${System.Convert.ToBase64String(value)} : null ,(v)=> ${container}.Add( "${serializedName}",v) );`; - } - - case KnownMediaType.Header: { - return If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}", ${System.Convert.ToBase64String(value)});`); - } - } - - } finally { - popTempVar(); - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - constructor(public schema: ByteArraySchema, public isRequired: boolean) { } diff --git a/powershell/llcsharp/schema/char.ts b/powershell/llcsharp/schema/char.ts index 68c576b39a8..d894a7487cd 100644 --- a/powershell/llcsharp/schema/char.ts +++ b/powershell/llcsharp/schema/char.ts @@ -7,42 +7,11 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, SchemaType, ChoiceSchema, ChoiceValue } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; import { length } from '@azure-tools/linq'; -export class Char extends Primitive { - public isXmlAttribute = false; - private choices?: Array; - jsonType = ClientRuntime.JsonString; - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - this.choices = length(schema.enum) > 0 ? schema.enum : undefined; - } - - get declaration(): string { - return `char${this.isRequired ? '' : ' ?'}`; - } - - get convertObjectMethod() { - return 'global::System.Convert.Char'; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateEnum(property)} - `.trim(); - } - - private validateEnum(property: Variable): string { - if (!this.choices) { - return ''; - } - return '// todo validate enum choices'; - } -} -export class NewChar extends NewPrimitive { +export class Char extends NewPrimitive { public isXmlAttribute = false; private choices?: Array; jsonType = ClientRuntime.JsonString; diff --git a/powershell/llcsharp/schema/date-time.ts b/powershell/llcsharp/schema/date-time.ts index f09cf4940b1..e271fb11ff7 100644 --- a/powershell/llcsharp/schema/date-time.ts +++ b/powershell/llcsharp/schema/date-time.ts @@ -12,101 +12,10 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema, DateSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; -export class DateTime extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonString; - // public DateFormat = new StringExpression('yyyy-MM-dd'); - public DateTimeFormat = new StringExpression('yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss.fffffffK'); - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get declaration(): string { - return `global::System.DateTime${this.isRequired ? '' : '?'}`; - } - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; - } - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; - } - - get convertObjectMethod() { - return '(v) => v is global::System.DateTime _v ? _v : global::System.Xml.XmlConvert.ToDateTime( v.ToString() , global::System.Xml.XmlDateTimeSerializationMode.Unspecified)'; - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - toExpression(`(${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : - toExpression(`null != ${value} ? (${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); - - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `"${serializedName}=" + ${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)` : - `(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - - case KnownMediaType.Xml: - // container : XElement - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : - `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - // public static string DateFormat = "yyyy-MM-dd"; - // public static string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; - // public static string DateTimeRfc1123Format = "R"; - // public static JsonString CreateDate(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateFormat, CultureInfo.InvariantCulture)) : null; - // public static JsonString CreateDateTime(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeFormat, CultureInfo.InvariantCulture)) : null; - // public static JsonString CreateDateTimeRfc1123(DateTime ? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeRfc1123Format, CultureInfo.InvariantCulture)) : null; - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } -} -export class NewDateTime extends NewPrimitive { +export class DateTime extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonString; // public DateFormat = new StringExpression('yyyy-MM-dd'); @@ -198,99 +107,16 @@ export class NewDateTime extends NewPrimitive { } } -export class DateTime1123 extends DateTime { - public DateTimeFormat = new StringExpression('R'); - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } -} -export class NewDateTime1123 extends NewDateTime { + +export class DateTime1123 extends DateTime { public DateTimeFormat = new StringExpression('R'); constructor(schema: DateTimeSchema, isRequired: boolean) { super(schema, isRequired); } } -export class UnixTime extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonNumber; - - private EpochDate = System.DateTime.new('1970', '1', '1', '0', '0', '0', System.DateTimeKind.Utc); - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; - } - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`).Cast(ClientRuntime.JsonNode) : - Ternery(IsNotNull(value), this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds)??0)`).Cast(ClientRuntime.JsonNode), dotnet.Null); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); - } - - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `(${value}.ToString())` : - `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - _serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return super.serializeToNode(mediaType, new LiteralExpression(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`), serializedName, mode); - } - - get q(): string { - return this.isRequired ? '' : '?'; - } - - get longType(): string { - return this.isRequired ? 'long' : 'long?'; - } - - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - get declaration(): string { - return `global::System.DateTime${this.isRequired ? '' : '?'}`; - } -} - -export class NewUnixTime extends NewPrimitive { +export class UnixTime extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/date.ts b/powershell/llcsharp/schema/date.ts index 62de87bcdfb..c4a48751abe 100644 --- a/powershell/llcsharp/schema/date.ts +++ b/powershell/llcsharp/schema/date.ts @@ -6,16 +6,10 @@ import { StringExpression } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { DateSchema } from '@azure-tools/codemodel'; -import { DateTime, NewDateTime } from './date-time'; +import { DateTime } from './date-time'; -export class Date extends DateTime { - public DateTimeFormat = new StringExpression('yyyy-MM-dd'); - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } -} -export class NewDate extends NewDateTime { +export class Date extends DateTime { public DateTimeFormat = new StringExpression('yyyy-MM-dd'); constructor(schema: DateSchema, isRequired: boolean) { super(schema, isRequired); diff --git a/powershell/llcsharp/schema/duration.ts b/powershell/llcsharp/schema/duration.ts index 1203f8fb816..711398f9a55 100644 --- a/powershell/llcsharp/schema/duration.ts +++ b/powershell/llcsharp/schema/duration.ts @@ -9,69 +9,11 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { Schema as NewSchema, DurationSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; import { ClientRuntime } from '../clientruntime'; -export class Duration extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonString; - - constructor(public schema: Schema, public isRequired: boolean) { - super(schema); - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get declaration(): string { - return `global::System.TimeSpan${this.isRequired ? '' : '?'}`; - } - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.Xml.XmlConvert.ToTimeSpan( ${tmpValue} )`; - } - - get convertObjectMethod() { - return '(v) => v is global::System.TimeSpan _v ? _v : global::System.Xml.XmlConvert.ToTimeSpan( v.ToString() )'; - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - if (!this.isRequired) { - return toExpression(`(null != ${value} ? ${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}: null)`).Cast(ClientRuntime.JsonNode); - } - return toExpression(`${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}`).Cast(ClientRuntime.JsonNode); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value}))`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})))`); - } - } - return toExpression(`/* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - public validatePresence(eventListener: Variable, property: Variable): string { - return ''; - } -} -export class NewDuration extends NewPrimitive { +export class Duration extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonString; diff --git a/powershell/llcsharp/schema/enum.ts b/powershell/llcsharp/schema/enum.ts index bf80b84f77e..798329dbbe0 100644 --- a/powershell/llcsharp/schema/enum.ts +++ b/powershell/llcsharp/schema/enum.ts @@ -5,7 +5,7 @@ import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -import { String, NewString } from './string'; +import { String } from './string'; import { dotnet, toExpression } from '@azure-tools/codegen-csharp'; export class EnumImplementation extends String { @@ -14,28 +14,6 @@ export class EnumImplementation extends String { return !this.isRequired; } - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } - - get defaultOfType() { - return this.isRequired ? toExpression(`((${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}${this.isRequired ? '' : '?'})"")`) : dotnet.Null; - } - - get convertObjectMethod() { - return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}.CreateFrom`; - } - - - get declaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}${this.isRequired ? '' : '?'}`; } -} - -export class NewEnumImplementation extends NewString { - public isXmlAttribute = false; - get isNullable(): boolean { - return !this.isRequired; - } - constructor(schema: NewSchema, isRequired: boolean) { super(schema, isRequired); diff --git a/powershell/llcsharp/schema/extended-type-declaration.ts b/powershell/llcsharp/schema/extended-type-declaration.ts index 0a0c59d327f..b08fd1ab2c7 100644 --- a/powershell/llcsharp/schema/extended-type-declaration.ts +++ b/powershell/llcsharp/schema/extended-type-declaration.ts @@ -12,55 +12,8 @@ import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; /** A TypeDeclaration that can assist in generating code for a variety of serialization, validation and other common use cases */ -export interface EnhancedTypeDeclaration extends TypeDeclaration { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression; - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression; - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression; - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression; - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements; - - /** defaultOfType */ - readonly defaultOfType: Expression; - - readonly convertObjectMethod: string; // "global::System.Convert.ToString"; - - /** is a value for this required */ - isRequired: boolean; - - /** when encoding as xml, is this encoded as an attribute */ - isXmlAttribute: boolean; - /** the underlying schema for this type declarartion. */ - schema: Schema; - - isNullable: boolean; - - /** emits the code required to validate that this is set to a value */ - validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements; - - /** emits the code required to validate that this has a permissable value */ - validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements; -} - -export interface NewEnhancedTypeDeclaration extends TypeDeclaration { +export interface EnhancedTypeDeclaration extends TypeDeclaration { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression; diff --git a/powershell/llcsharp/schema/integer.ts b/powershell/llcsharp/schema/integer.ts index d6673cb5de5..0d39024b097 100644 --- a/powershell/llcsharp/schema/integer.ts +++ b/powershell/llcsharp/schema/integer.ts @@ -8,45 +8,10 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { NumberSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; -export class Numeric extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonNumber; - - constructor(schema: Schema, public isRequired: boolean, protected numericType: string) { - super(schema); - } - get declaration(): string { - return `${this.numericType}`; - } - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateMinimum(eventListener, property)} -${this.validateMaximum(eventListener, property)} -${this.validateExclusiveMinimum(eventListener, property)} -${this.validateExclusiveMaximum(eventListener, property)} -${this.validateMultipleOf(eventListener, property)} -`.trim(); - } - protected validateMinimum(eventListener: Variable, property: Variable): string { - return this.schema.minimum && !this.schema.exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThanOrEqual(${nameof(property.value)},${property},${this.schema.minimum});` : ''; - } - protected validateMaximum(eventListener: Variable, property: Variable): string { - return this.schema.maximum && !this.schema.exclusiveMaximum ? `await ${eventListener}.AssertIsLessThanOrEqual(${nameof(property.value)},${property},${this.schema.maximum});` : ''; - } - protected validateExclusiveMinimum(eventListener: Variable, property: Variable): string { - return this.schema.minimum && this.schema.exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThan(${nameof(property.value)},${property},${this.schema.minimum});` : ''; - } - protected validateExclusiveMaximum(eventListener: Variable, property: Variable): string { - return this.schema.maximum && this.schema.exclusiveMaximum ? `await ${eventListener}.AssertIsLessThan(${nameof(property.value)},${property},${this.schema.maximum});` : ''; - } - protected validateMultipleOf(eventListener: Variable, property: Variable): string { - return this.schema.multipleOf ? `await ${eventListener}.AssertIsMultipleOf(${nameof(property.value)},${property},${this.schema.multipleOf});` : ''; - } -} -export class NewNumeric extends NewPrimitive { +export class Numeric extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/object.ts b/powershell/llcsharp/schema/object.ts index bb9dce1cad5..cf6a138e813 100644 --- a/powershell/llcsharp/schema/object.ts +++ b/powershell/llcsharp/schema/object.ts @@ -16,172 +16,10 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, ObjectSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; -export class ObjectImplementation implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - - get defaultOfType() { - return toExpression('null /* object */'); - } - - get isNullable(): boolean { - return true; - } - - get convertObjectMethod() { - return `${this.schema.details.csharp.fullname}TypeConverter.ConvertFrom`; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // JsonObject - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonObject}>("${serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromJson(${tmp}) : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement or XElement/XAttribute - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - // prefer specified XML name if available - return toExpression(`If( ${valueOf(container)}?.Element("${this.schema.xml ? this.schema.xml.name || serializedName : serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); - } - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // we're always going to go thru FromJson; it'll handle nulls and polymorphism. - return toExpression(`${this.classDeclaration}.FromJson(${node}) `); - } - case KnownMediaType.Xml: { - - return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - return toExpression(`${value}?.ToJson(null, ${mode.value})`); - } - case KnownMediaType.Xml: { - return toExpression(`${value}?.ToXml(null, ${mode.value})`); - } - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - return System.Net.Http.StringContent.new( - Ternery( - IsNotNull(value), - `${value}.ToJson(null).ToString()`, - new StringExpression('{}')), - System.Text.Encoding.UTF8); - } - case KnownMediaType.Xml: { - return System.Net.Http.StringContent.new( - Ternery( - IsNotNull(value), - `${value}.ToXml(null).ToString()`, - System.String.Empty), - System.Text.Encoding.UTF8); - } - case KnownMediaType.Multipart: { - let contents = ''; - for (const p of values(this.schema.properties)) { - // to do -- add in a potential support for the filename too. - contents = `${contents}${EOL} bodyContent.Add( ${System.Net.Http.StreamContent.new(`${value}.${p.details.csharp.name}`)},"${p.serializedName}");`; - } - // bodyContent.Add(new _ystem.Net.Http.StreamContent(body.AudioFile), "audioFile"); - return toExpression(`new ${System.Func(System.Net.Http.MultipartFormDataContent)}(() => -{ - var bodyContent = ${System.Net.Http.MultipartFormDataContent.new()}; - ${contents} - return bodyContent; -})()`); - } - } - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - } - return undefined; - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - if (this.schema.details.csharp.hasHeaders) { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)}.ReadHeaders(_response.Headers))`); - } - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - case KnownMediaType.Xml: { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - // const v = (value).valuePrivate || value; - switch (mediaType) { - case KnownMediaType.Json: - return `AddIf( null != ${value} ? (${ClientRuntime.JsonNode}) ${value}.ToJson(null,${mode.value}) : null, "${serializedName}" ,${container}.Add );`; - - case KnownMediaType.Xml: - // prefer specified XML name if available - return `AddIf( null != ${value} ? ${value}.ToXml(new ${System.Xml.Linq.XElement}("${this.schema.xml ? this.schema.xml.name || serializedName : serializedName}")) : null, ${container}.Add );`; - - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - - isRequired = false; - - constructor(public schema: Schema) { - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `.trim(); - } - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return `await ${eventListener}.AssertObjectIsValid(${nameof(property.value)}, ${property}); `; - } - get declaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.interfaceName}`; } - get classDeclaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}`; } - -} - -export class NewObjectImplementation implements NewEnhancedTypeDeclaration { +export class ObjectImplementation implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/llcsharp/schema/primitive.ts b/powershell/llcsharp/schema/primitive.ts index 50c34b01c93..2264da29511 100644 --- a/powershell/llcsharp/schema/primitive.ts +++ b/powershell/llcsharp/schema/primitive.ts @@ -15,7 +15,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, PrimitiveSchema } from '@azure-tools/codemodel'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; let tmpVar: number | undefined; let max = 0; @@ -49,190 +49,7 @@ export function popTempVar() { } } -export abstract class Primitive implements EnhancedTypeDeclaration { - abstract isRequired: boolean; - abstract isXmlAttribute: boolean; - abstract declaration: string; - abstract jsonType: ClassType; - get isNullable(): boolean { - return !this.isRequired; - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get defaultOfType() { - return toExpression(`default(${this.declaration})`); - } - - get convertObjectMethod() { - const v = pushTempVar(); - const result = `(${v})=> (${this.baseType}) global::System.Convert.ChangeType(${v}, typeof(${this.baseType}))`; - popTempVar(); - - return result; - } - - constructor(public schema: Schema) { - } - /** validatePresence on primitives is generally not required; the nullability determines requiredness... */ - public validatePresence(eventListener: Variable, property: Variable): string { - return ''; - } - - abstract validateValue(eventListener: Variable, property: Variable): string; - protected get baseType(): string { - return this.declaration.replace('?', ''); - } - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `(${this.declaration})${tmpValue}`; - } - - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `(${this.declaration})${tmpValue}`; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // JsonObject - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${this.jsonType}>("${serializedName}"), out var ${tmp}) ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement or XElement/XAttribute - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - - return toExpression(this.isXmlAttribute ? - `If( ${valueOf(container)}?.Attribute("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : - `If( ${valueOf(container)}?.Element("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - } - - case KnownMediaType.Header: { - // HttpResponseHeaders - const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${this.baseType}.TryParse( ${tmp}, out ${this.baseType} ${tmp}Value ) ? ${tmp}Value : ${defaultValue} : ${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); - } - - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: - // node should be a json type - return toExpression(`${node} is ${this.jsonType} ${tmp} ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - - case KnownMediaType.Xml: - // XElement or XAttribute - return toExpression( - this.isXmlAttribute ? - `${node} is ${System.Xml.Linq.XAttribute} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : - `${node} is ${System.Xml.Linq.XElement} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)}: ${defaultValue}`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainer doens't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - try { - const tmp = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.UriParameter: { - return toExpression(`${this.baseType}.TryParse( ${valueOf(content)}, out ${this.baseType} ${tmp} ) ? ${tmp} : ${defaultValue}`); - - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - this.jsonType.new(value).Cast(ClientRuntime.JsonNode) : - Ternery(IsNotNull(value), this.jsonType.new(`(${this.baseType})${value}`).Cast(ClientRuntime.JsonNode), dotnet.Null); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); - } - - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `(${value}.ToString())` : - `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - - case KnownMediaType.Xml: - // container : XElement - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}.ToString());`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}"}`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } -} - -export abstract class NewPrimitive implements NewEnhancedTypeDeclaration { +export abstract class NewPrimitive implements EnhancedTypeDeclaration { abstract isRequired: boolean; abstract isXmlAttribute: boolean; abstract declaration: string; diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index bd1eab1c708..1e5c2a4c3fa 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -5,162 +5,36 @@ import { codeModelSchema, ArraySchema, UnixTimeSchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel'; -import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; +import { codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; -import { ArrayOf, NewArrayOf } from './array'; -import { Binary, NewBinary } from './binary'; -import { Boolean, NewBoolean } from './boolean'; -import { ByteArray, NewByteArray } from './byte-array'; -import { Char, NewChar } from './char'; -import { Date, NewDate } from './date'; -import { DateTime, DateTime1123, UnixTime, NewDateTime, NewDateTime1123, NewUnixTime } from './date-time'; -import { Duration, NewDuration } from './duration'; -import { EnumImplementation, NewEnumImplementation } from './enum'; -import { Numeric, NewNumeric } from './integer'; -import { ObjectImplementation, NewObjectImplementation } from './object'; -import { String, NewString } from './string'; -import { Uuid, NewUuid } from './Uuid'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { ArrayOf } from './array'; +import { Binary } from './binary'; +import { Boolean } from './boolean'; +import { ByteArray } from './byte-array'; +import { Char } from './char'; +import { Date } from './date'; +import { DateTime, DateTime1123, UnixTime } from './date-time'; +import { Duration } from './duration'; +import { EnumImplementation } from './enum'; +import { Numeric } from './integer'; +import { ObjectImplementation } from './object'; +import { String } from './string'; +import { Uuid } from './Uuid'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { PwshModel } from '../../utils/PwshModel'; -import { NewModelState } from '../../utils/model-state'; +import { ModelState } from '../../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { schemaHasEnum } from '../validations'; export class SchemaDefinitionResolver { private readonly cache = new Map(); - private add(schema: Schema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { - this.cache.set(schema.details.csharp.fullname || '', value); - return value; - } - - resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - // determine if we need a new model class for the type or just a known type object - switch (schema.type) { - case JsonType.Array: { - // can be recursive! - // handle boolean arrays as booleans (powershell will try to turn it into switches!) - const elementType = (schema.items && schema.items.type === JsonType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(schema.items, true, state.path('items')); - return new ArrayOf(schema, required, elementType, schema.minItems, schema.maxItems, schema.uniqueItems); - } - - case JsonType.Object: { - const result = schema.details.csharp && this.cache.get(schema.details.csharp.fullname || ''); - if (result) { - return result; - } - return this.add(schema, new ObjectImplementation(schema)); - } - case JsonType.String: - switch (schema.format) { - case StringFormat.Base64Url: - case StringFormat.Byte: - // member should be byte array - // on wire format should be base64url - return new ByteArray(schema, required); - - case StringFormat.Binary: - // represent as a stream - // wire format is stream of bytes - return new Binary(schema, required); - - case StringFormat.Char: - // a single character - return new Char(schema, required); - - case StringFormat.Date: - return new Date(schema, required); - - case StringFormat.DateTime: - return new DateTime(schema, required); - - case StringFormat.DateTimeRfc1123: - return new DateTime1123(schema, required); - - case StringFormat.Duration: - return new Duration(schema, required); - - case StringFormat.Uuid: - return new Uuid(schema, required); - - case StringFormat.Url: - case StringFormat.Password: - case StringFormat.None: - case undefined: - case null: - if (schema.extensions && schema.extensions['x-ms-enum']) { - return new EnumImplementation(schema, required); - } - /* - if(schema.extensions && schema.extensions['x-ms-header-collection-prefix']) { - return new Wildcard(schema, new String({}, required)); - } - */ - // just a regular old string. - return new String(schema, required); - - default: - state.warning(`Schema with type:'${schema.type} and 'format:'${schema.format}' is not recognized.`, message.DoesNotSupportEnum); - return new String(schema, required); - } - - case JsonType.Boolean: - return new Boolean(schema, required); - - case JsonType.Integer: - switch (schema.format) { - case IntegerFormat.Int64: - case IntegerFormat.None: - return new Numeric(schema, required, required ? 'long' : 'long?'); - case IntegerFormat.UnixTime: - return new UnixTime(schema, required); - case IntegerFormat.Int32: - return new Numeric(schema, required, required ? 'int' : 'int?'); - } - // fallback to int if the format isn't recognized - return new Numeric(schema, required, required ? 'int' : 'int?'); - - case JsonType.Number: - switch (schema.format) { - case NumberFormat.None: - case NumberFormat.Double: - return new Numeric(schema, required, required ? 'double' : 'double?'); - case NumberFormat.Float: - return new Numeric(schema, required, required ? 'float' : 'float?'); - case NumberFormat.Decimal: - return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); - } - // fallback to float if the format isn't recognized - return new Numeric(schema, required, required ? 'float' : 'float?'); - - case undefined: - if (schema.extensions && schema.extensions['x-ms-enum']) { - return new EnumImplementation(schema, required); - } - - // "any" case - // this can happen when a model is just an all-of something else. (sub in the other type?) - break; - - } - state.error(`Schema '${schema.details.csharp.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); - throw new Error('Unknown Model. Fatal.'); - } - -} - -export class NewSchemaDefinitionResolver { - private readonly cache = new Map(); - private add(schema: NewSchema, value: NewEnhancedTypeDeclaration): NewEnhancedTypeDeclaration { + private add(schema: NewSchema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { this.cache.set(schema.language?.csharp?.fullname || '', value); return value; } - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -171,8 +45,8 @@ export class NewSchemaDefinitionResolver { // can be recursive! // handle boolean arrays as booleans (powershell will try to turn it into switches!) const ar = schema; - const elementType = (ar.elementType.type === SchemaType.Boolean) ? new NewBoolean(schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items')); - return new NewArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); + const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items')); + return new ArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); } case SchemaType.Any: @@ -182,60 +56,60 @@ export class NewSchemaDefinitionResolver { if (result) { return result; } - return this.add(schema, new NewObjectImplementation(schema)); + return this.add(schema, new ObjectImplementation(schema)); } case SchemaType.Time: case SchemaType.Credential: case SchemaType.String: { - return new NewString(schema, required); + return new String(schema, required); } case SchemaType.Binary: - return new NewBinary(schema, required); + return new Binary(schema, required); case SchemaType.Duration: - return new NewDuration(schema, required); + return new Duration(schema, required); case SchemaType.Uuid: - return new NewUuid(schema, required); + return new Uuid(schema, required); case SchemaType.DateTime: if ((schema).format === StringFormat.DateTimeRfc1123) { - return new NewDateTime1123(schema, required); + return new DateTime1123(schema, required); } - return new NewDateTime(schema, required); + return new DateTime(schema, required); case SchemaType.Date: - return new NewDate(schema, required); + return new Date(schema, required); case SchemaType.ByteArray: - return new NewByteArray(schema, required); + return new ByteArray(schema, required); case SchemaType.Boolean: - return new NewBoolean(schema, required); + return new Boolean(schema, required); case SchemaType.Integer: switch ((schema).precision) { case 64: - return new NewNumeric(schema, required, required ? 'long' : 'long?'); + return new Numeric(schema, required, required ? 'long' : 'long?'); // skip-for-time-being // case IntegerFormat.UnixTime: // return new UnixTime(schema, required); case 16: case 32: - return new NewNumeric(schema, required, required ? 'int' : 'int?'); + return new Numeric(schema, required, required ? 'int' : 'int?'); } // fallback to int if the format isn't recognized - return new NewNumeric(schema, required, required ? 'int' : 'int?'); + return new Numeric(schema, required, required ? 'int' : 'int?'); case SchemaType.UnixTime: - return new NewUnixTime(schema, required); + return new UnixTime(schema, required); case SchemaType.Number: switch ((schema).precision) { case 64: - return new NewNumeric(schema, required, required ? 'double' : 'double?'); + return new Numeric(schema, required, required ? 'double' : 'double?'); case 32: - return new NewNumeric(schema, required, required ? 'float' : 'float?'); + return new Numeric(schema, required, required ? 'float' : 'float?'); case 128: - return new NewNumeric(schema, required, required ? 'decimal' : 'decimal?'); + return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); } // fallback to float if the format isn't recognized - return new NewNumeric(schema, required, required ? 'float' : 'float?'); + return new Numeric(schema, required, required ? 'float' : 'float?'); case SchemaType.Constant: return this.resolveTypeDeclaration((schema).valueType, required, state); @@ -245,12 +119,12 @@ export class NewSchemaDefinitionResolver { } case SchemaType.SealedChoice: if (schema.language.default.skip === true) { - return new NewString(schema, required); + return new String(schema, required); } - return new NewEnumImplementation(schema, required); + return new EnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { - return new NewEnumImplementation(schema, required); + return new EnumImplementation(schema, required); } // "any" case diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index a39aa57f1d9..19ae3320108 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -14,203 +14,13 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { ChoiceSchema, Schema as NewSchema, SchemaType, SealedChoiceSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; -/** A ETD for the c# string type. */ -export class String implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - - get defaultOfType() { - return toExpression('null'); - } - get convertObjectMethod() { - return 'global::System.Convert.ToString'; - } - - get isNullable(): boolean { - return true; - } - - get encode(): string { - return this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // container should be a JsonObject - const tmpVar = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmpVar}) ? (string)${tmpVar} : (string)${defaultValue}`); - } - case KnownMediaType.Xml: { - const xTmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}"), out var ${xTmp}) ? (string)${xTmp} : (string)${defaultValue}`); - } - case KnownMediaType.Header: { - // HttpResponseHeaders - const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${tmp} : (string)${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: - // node should be a JsonString - return toExpression(`${node} is ${ClientRuntime.JsonString} ${tmp} ? (${this.declaration})(${tmp}.ToString()) : ${defaultValue}`); - - case KnownMediaType.Xml: - return toExpression(`${node} is ${System.Xml.Linq.XElement} ${tmp} ? (string)${tmp} : ${defaultValue}`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainer doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`null != (((object)${value})?.ToString()) ? (${ClientRuntime.JsonNode}) new ${ClientRuntime.JsonString}(${value}.ToString()) : null`); - - case KnownMediaType.Xml: - return toExpression(`null != (${value}?.ToString()) ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value})`); - } else { - return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${valueOf(value)}))`); - } - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - if (this.isRequired) { - return toExpression(`${this.encode}(${value})`); - } - return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : ${this.encode}(${value}) )`); - - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - case KnownMediaType.UriParameter: { - return toExpression(content); - } - } - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${container}.Add );`; - - case KnownMediaType.Xml: - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${container}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value});`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `(${serializedName}={${value}.ToString()})` : - `(null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}")`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - constructor(public schema: Schema, public isRequired: boolean) { - } - - get declaration(): string { - return 'string'; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateMinLength(eventListener, property)} -${this.validateMaxLength(eventListener, property)} -${this.validateRegex(eventListener, property)} -${this.validateEnum(eventListener, property)} - `.trim(); - - } - - public validatePresence(eventListener: Variable, property: Variable): string { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - - private validateMinLength(eventListener: Variable, property: Variable): string { - if (!this.schema.minLength) { - return ''; - } - return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${this.schema.minLength});`; - } - private validateMaxLength(eventListener: Variable, property: Variable): string { - if (!this.schema.maxLength) { - return ''; - } - return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${this.schema.maxLength});`; - } - private validateRegex(eventListener: Variable, property: Variable): string { - if (!this.schema.pattern) { - return ''; - } - return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${this.schema.pattern}");`; - } - private validateEnum(eventListener: Variable, property: Variable): string { - if (!this.schema.enum || length(this.schema.enum) === 0) { - return ''; - } - return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${this.schema.enum.joinWith((v) => `@"${v}"`)});`; - } -} /** A ETD for the c# string type. */ -export class NewString implements NewEnhancedTypeDeclaration { +export class String implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/main.ts b/powershell/main.ts index b8cfe84ed64..21590a6993a 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { AutoRestExtension, } from '@azure-tools/autorest-extension-base'; -import { applyModifiers } from './plugins/modifiers'; -import { createCommands } from './plugins/create-commands'; -import { namer } from './plugins/ps-namer'; -import { powershell } from './plugins/powershell'; -import { addCompleter } from './plugins/add-azure-completers'; -import { csnamer } from './plugins/cs-namer'; -import { llcsharp } from './plugins/llcsharp'; +//import { applyModifiers } from './plugins/modifiers'; +//import { createCommands } from './plugins/create-commands'; +//import { namer } from './plugins/ps-namer'; +//import { powershell } from './plugins/powershell'; +//import { addCompleter } from './plugins/add-azure-completers'; +//import { csnamer } from './plugins/cs-namer'; +//import { llcsharp } from './plugins/llcsharp'; import { createInlinedPropertiesPlugin } from './plugins/plugin-create-inline-properties'; import { tweakModelPlugin } from './plugins/plugin-tweak-model'; import { tweakModelAzurePluginV2 } from './plugins/plugin-tweak-model-azure-v2'; @@ -27,13 +27,6 @@ require('source-map-support').install(); export async function main() { const pluginHost = new AutoRestExtension(); - pluginHost.Add('powershell', powershell); - pluginHost.Add('create-commands', createCommands); - pluginHost.Add('psnamer', namer); - pluginHost.Add('modifiers', applyModifiers); - pluginHost.Add('add-azure-completers', addCompleter); - pluginHost.Add('csnamer', csnamer); - pluginHost.Add('llcsharp', llcsharp); // Following are plugins moved from remodeler pluginHost.Add('tweakm4codemodel', tweakM4ModelPlugin); pluginHost.Add('tweakcodemodel-v2', tweakModelPlugin); diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 2f0e682375a..8024ec3f3a3 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -5,8 +5,8 @@ import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; -import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, NewObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; +import { Schema, ClientRuntime, ObjectImplementation, SchemaDefinitionResolver, DeserializerPartialClass } from '../llcsharp/exports'; +import { State } from '../internal/state'; import { PSObject, PSTypeConverter, TypeConverterAttribute } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -36,239 +36,7 @@ export class ModelExtensionsNamespace extends Namespace { } resolver = new SchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary, private state: State, objectInitializer?: DeepPartial) { - super('Models', parent); - this.apply(objectInitializer); - this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); - this.subNamespaces[this.fullName] = this; - - const $this = this; - const resolver = (s: Schema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state); - - // Add typeconverters to model classes (partial) - for (const schema of values(schemas)) { - if (!schema || schema.details.csharp.skip) { - continue; - } - - const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof ObjectImplementation) { - - // it's a class object. - const className = td.schema.details.csharp.name; - const interfaceName = td.schema.details.csharp.interfaceName || ''; - const converterClass = `${className}TypeConverter`; - - if (this.findClassByName(className).length > 0) { - continue; - } - - // get the actual full namespace for the schema - const fullname = schema.details.csharp.namespace || this.fullName; - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionModelExtensionsNamespace(this.outputFolder, fullname)); - - // create the model extensions for each object model - // 2. A partial interface with the type converter attribute - const modelInterface = new Interface(ns, interfaceName, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. - }); - modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - - // 1. A partial class with the type converter attribute - const model = new Class(ns, className, undefined, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${className}.PowerShell` - }); - - // if the model is supposed to be use 'by-reference' we should create an I*Reference interface for that - // and add that interface to the extension class - if (schema.details.csharp.byReference) { - const refInterface = `${interfaceName}_Reference`; - schema.details.csharp.referenceInterface = `${ns.fullName}.${refInterface}`; - - const referenceInterface = new Interface(ns, refInterface, { - partial: true, - description: `Reference for model ${fullname}`, - fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. - }); - referenceInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - referenceInterface.add(new InterfaceProperty('Id', dotnet.String, { setAccess: Access.Internal })); - model.interfaces.push(referenceInterface); - - // add it to the generic reference type. - // referenceType = referenceType || this.CreateReferenceType(); - // referenceType.interfaces.push(referenceInterface); - } - - - model.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { - static: Modifier.Static, - parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], - description: `Creates a new instance of , deserializing the content from a json string.`, - returnsDescription: 'an instance of the model class.' - })); - - model.add(new LambdaMethod('ToJsonString', dotnet.String, new LiteralExpression(`ToJson(${dotnet.Null}, ${ClientRuntime.SerializationMode.IncludeAll})?.ToString()`), { - description: 'Serializes this instance to a json string.', - returnsDescription: 'a containing this model serialized to JSON text.' - })); - - const hashDeseralizer = new DeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); - const psDeseralizer = new DeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); - - // + static FromJsonString(string json); - // + string ToJsonString() - - // 3. A TypeConverter class - const typeConverter = new Class(ns, converterClass, PSTypeConverter, { - description: `A PowerShell PSTypeConverter to support converting to an instance of `, - fileName: `${className}.TypeConverter` - }); - typeConverter.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the parameter can be converted to the parameter', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false', - })); - typeConverter.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], description: 'NotImplemented -- this will return null', - returnsDescription: 'will always return null.' - })); - typeConverter.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, new LiteralExpression('CanConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - typeConverter.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression('ConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })); - - typeConverter.add(new Method('CanConvertFrom', dotnet.Bool, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { description: `the instance to check if it can be converted to the type.` }), - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: `true if the instance could be converted to a type, otherwise false ` - })).add(function* () { - yield If('null == sourceValue', Return(dotnet.True)); - - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; - - if (schema.details.default.uid === 'universal-parameter-type' || schema.details.csharp.byReference) { - yield '// we allow string conversion too.'; - yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); - } - - yield If(IsAssignableFrom(PSObject, t), function* () { - yield '// we say yest to PSObjects'; - yield Return(dotnet.True); - }); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), function* () { - yield '// we say yest to Hashtables/dictionaries'; - yield Return(dotnet.True); - }); - - yield Try(If('null != sourceValue.ToJsonString()', Return(dotnet.True))); - yield Catch(undefined, '// Not one of our objects'); - - yield Try(function* () { - const t = new LocalVariable('text', dotnet.String, { initializer: 'sourceValue.ToString()?.Trim()' }); - yield t.declarationStatement; - yield Return(`${dotnet.True} == ${t.value}?.StartsWith("{") && ${dotnet.True} == ${t.value}?.EndsWith("}") && ${ClientRuntime.JsonNode.Parse(t)}.Type == ${ClientRuntime.JsonType.Object}`); - }); - yield Catch(undefined, '// Doesn\'t look like it can be treated as JSON'); - - yield Return(dotnet.False); - }); - - typeConverter.add(new Method('ConvertFrom', modelInterface, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { - description: `the value to convert into an instance of .` - }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })).add(function* () { - // null begets null - yield If('null == sourceValue', Return(dotnet.Null)); - - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; - - if (($this.state.project.azure && schema.details.default.uid === 'universal-parameter-type') || schema.details.csharp.byReference) { - yield '// support direct string to id type conversion.'; - yield If(`${t.value} == typeof(${System.String})`, function* () { - yield Return(`new ${className} { Id = sourceValue }`); - }); - } - - if (schema.details.csharp.byReference) { - yield '// if Id is present with by-reference schemas, just return the type with Id '; - yield Try(Return(`new ${className} { Id = sourceValue.Id }`)); - yield Catch(undefined, '// Not an Id reference parameter'); - } - - // if the type can be assigned directly, do that - yield If(IsAssignableFrom(td, t), Return('sourceValue')); - - // try using json first (either from string or toJsonString()) - yield Try(Return(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`)); - yield Catch(undefined, '// Unable to use JSON pattern'); - - yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); - - // null if not successful - yield Return(dotnet.Null); - }); - } - } - } -} - -export class NewModelExtensionsNamespace extends Namespace { - CreateReferenceType(): Class { - const rt = new Class(this, 'ReferenceType'); - rt.add(new Property('Id', dotnet.String, { setAccess: Access.Internal })); - return rt; - } - private subNamespaces = new Dictionary(); - - public get outputFolder(): string { - return join(this.state.project.apiFolder, 'Models'); - } - resolver = new NewSchemaDefinitionResolver(); - - constructor(parent: Namespace, private schemas: Dictionary>, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private schemas: Dictionary>, private state: State, objectInitializer?: DeepPartial) { super('Models', parent); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); @@ -285,7 +53,7 @@ export class NewModelExtensionsNamespace extends Namespace { } const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof NewObjectImplementation) { + if (td instanceof ObjectImplementation) { // it's a class object. const className = td.schema.language.csharp?.name || ''; @@ -350,8 +118,8 @@ export class NewModelExtensionsNamespace extends Namespace { returnsDescription: 'a containing this model serialized to JSON text.' })); - const hashDeseralizer = new NewDeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); - const psDeseralizer = new NewDeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); + const hashDeseralizer = new DeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); + const psDeseralizer = new DeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); // + static FromJsonString(string json); // + string ToJsonString() diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index 58b81933822..40dbf645bb5 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -6,291 +6,10 @@ import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, If, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; import { InvocationInfo, PSCredential, IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, } from '../internal/powershell-declarations'; -import { State, NewState } from '../internal/state'; +import { State } from '../internal/state'; import { ClientRuntime } from '../llcsharp/exports'; import { DeepPartial } from '@azure-tools/codegen'; -export class ModuleClass extends Class { - - // get the name of the client API class - TaskOfHttpResponseMessage = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); - - // lets the common code call the signal again (recursive! careful!) - incomingSignalFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - /* returns */ System.Threading.Tasks.Task()); - - eventListenerFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - this.incomingSignalFunc, - InvocationInfo, - dotnet.String, - dotnet.String, - dotnet.String, - System.Exception, - /* returns */ System.Threading.Tasks.Task()); - - IEventListenerExpanded = [ - System.Threading.CancellationToken, /* token */ - System.Action(), /* Cancel() */ - this.incomingSignalFunc, - ]; - - nextStep = System.Func( - System.Net.Http.HttpRequestMessage, - ...this.IEventListenerExpanded, - /* returns */ this.TaskOfHttpResponseMessage); - - initMethod = this.add(new Method('Init', dotnet.Void, { description: 'Initialization steps performed after the module is loaded.' })); - createPipelineMethod!: Method; - - pInvocationInfo = new Parameter('invocationInfo', InvocationInfo, { description: 'The from the cmdlet' }); - pPipeline = new Parameter('pipeline', ClientRuntime.HttpPipeline, { modifier: ParameterModifier.Ref, description: 'The HttpPipeline for the request' }); - pProxy = new Parameter('proxy', System.Uri, { description: 'The HTTP Proxy to use.' }); - pProxyCredential = new Parameter('proxyCredential', PSCredential, { description: 'The HTTP Proxy Credentials' }); - pUseDefaultCredentials = new Parameter('proxyUseDefaultCredentials', dotnet.Bool, { description: 'True if the proxy should use default credentials' }); - - pCorrelationId = new Parameter('correlationId', dotnet.String, { description: 'the cmdlet\'s correlation id.' }); - pParameterName = new Parameter('parameterName', dotnet.String, { description: 'The name of the parameter to get the value for.' }); - - pId = new Parameter('id', dotnet.String, { description: 'The ID of the event ' }); - pToken = new Parameter('token', System.Threading.CancellationToken, { description: 'The cancellation token for the event ' }); - pGetEventData = new Parameter('getEventData', System.Func(System.EventArgs), { description: 'A delegate to get the detailed event data' }); - - pParameterSetName = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.' }); - pParameterSetNameWithDefault = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.', defaultInitializer: dotnet.Null }); - pProcessRecordId = new Parameter('processRecordId', dotnet.String, { description: 'the cmdlet\'s process record correlation id.' }); - pException = new Parameter('exception', System.Exception, { description: 'the exception that is being thrown (if available)' }); - - fPipeline = this.add(new Field('_pipeline', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance' })); - fPipelineWithProxy = this.add(new Field('_pipelineWithProxy', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance (when proxy is enabled)' })); - fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); - fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); - - constructor(namespace: Namespace, private readonly state: State, objectInitializer?: DeepPartial) { - super(namespace, 'Module'); - this.apply(objectInitializer); - this.partial = true; - this.description = 'A class that contains the module-common code and data.'; - - const $this = this; - - // static instance property - this.add(new LazyProperty('Instance', this, new LiteralExpression(`new ${this.declaration}()`), { - instanceAccess: this.declaration, - static: Modifier.Static, - description: 'the singleton of this module class' - })); - - const clientAPI = new ClassType(this.state.model.details.csharp.namespace, this.state.model.details.csharp.name); - const clientProperty = this.add(new Property('ClientAPI', clientAPI, { description: 'The instance of the Client API' })); - - if (this.state.project.azure) { - this.createAzureInitAndPipeline(namespace); - } else { - this.createInitAndPipeline(namespace); - } - - this.add(new Constructor(this, { - access: Access.Private, - description: 'Creates the module instance.', - body: function* () { - yield '/// constructor'; - yield clientProperty.assignPrivate(clientAPI.new()); - yield `${$this.fHandler}.Proxy = ${$this.fWebProxy};`; - - yield $this.fPipeline.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new()))); - yield $this.fPipelineWithProxy.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new($this.fHandler)))); - } - })); - - /* extensibility points */ - this.add(new PartialMethod('BeforeCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); - this.add(new PartialMethod('AfterCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); - this.add(new PartialMethod('CustomInit', dotnet.Void)); - - /* Setting the Proxy */ - this.add(new Method('SetProxyConfiguration', dotnet.Void, { - parameters: [this.pProxy, this.pProxyCredential, this.pUseDefaultCredentials], - *body() { - yield '// set the proxy configuration'; - yield `${$this.fWebProxy}.Address = proxy;`; - yield `${$this.fWebProxy}.BypassProxyOnLocal = false;`; - yield `${$this.fWebProxy}.Credentials = proxyCredential ?.GetNetworkCredential();`; - yield `${$this.fWebProxy}.UseDefaultCredentials = proxyUseDefaultCredentials;`; - yield `${$this.fHandler}.UseProxy = proxy != null;`; - } - })); - } - - createInitAndPipeline(namespace: Namespace) { - const $this = this; - // Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId) - const customEventListenerFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - this.incomingSignalFunc, - InvocationInfo, - dotnet.String, - System.Exception, - /* returns */ System.Threading.Tasks.Task()); - - const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); - const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc)); - const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); - - // non-azure init method - this.initMethod.add(function* () { - yield '// called at module init time...'; - yield 'CustomInit();'; - }); - - this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { - parameters: [this.pInvocationInfo, this.pParameterSetNameWithDefault], - description: 'Creates an instance of the HttpPipeline for each call.', - returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` - })); - - // non-azure createPipeline method - this.createPipelineMethod.add(function* () { - const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); - yield pip.declarationStatement; - yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); - yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield Return(pip); - }); - - this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); - - // Add Signal extensibility point - const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); - // Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module - const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { - parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async, - description: 'Called to dispatch events to the common module listener', - returnsDescription: `A that will be complete when handling of the event is completed.` - })); - - signalImpl.push(Using('NoSynchronizationContext', '')); - signalImpl.add(function* () { - // Emit call to EventListener after explicit null check. - // Not using Null-Conditional operator causes Null Reference exception when Func is null, due to awaiting null Task. - yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`) - }); - } - - createAzureInitAndPipeline(namespace: Namespace) { - const $this = this; - - const sendAsyncStep = namespace.add(new Alias('SendAsyncStepDelegate', - System.Func( - System.Net.Http.HttpRequestMessage, - ...this.IEventListenerExpanded, - this.nextStep, /* Next( ...) */ - /* returns */ this.TaskOfHttpResponseMessage))); - - const pipelineChangeDelegate = namespace.add(new Alias('PipelineChangeDelegate', System.Action(sendAsyncStep.fullDefinition))); - - const getParameterDelegate = namespace.add(new Alias('GetParameterDelegate', System.Func( - dotnet.String, /* resourceId */ - dotnet.String, /* moduleName */ - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.String, /* parameterName */ - /* returns */ dotnet.Object))); - - const moduleLoadPipelineDelegate = namespace.add(new Alias('ModuleLoadPipelineDelegate', System.Action( - dotnet.String, /* resourceId */ - dotnet.String, /* moduleName */ - pipelineChangeDelegate.fullDefinition, /* prependStep */ - pipelineChangeDelegate.fullDefinition))); /* appendStep */ - - const newRequestPipelineDelegate = namespace.add(new Alias('NewRequestPipelineDelegate', System.Action( - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.String, /* processRecordId */ - pipelineChangeDelegate.fullDefinition, /* prependStep */ - pipelineChangeDelegate.fullDefinition))); /* appendStep */ - - const argumentCompleterDelegate = namespace.add(new Alias('ArgumentCompleterDelegate', System.Func( - dotnet.String, /* completerName */ - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.StringArray, /* resourceTypes */ - dotnet.StringArray, /* parentResourceParameterNames */ - /* returns */ dotnet.StringArray, - ))); - - const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); - const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', this.eventListenerFunc)); - - namespace.add(new Alias('NextDelegate', this.nextStep)); - - /* AzAccounts VTable properties */ - const OnModuleLoad = this.add(new Property('OnModuleLoad', moduleLoadPipelineDelegate, { description: 'The delegate to call when this module is loaded (supporting a commmon module).' })); - const OnNewRequest = this.add(new Property('OnNewRequest', newRequestPipelineDelegate, { description: 'The delegate to call before each new request (supporting a commmon module).' })); - const GetParameterValue = this.add(new Property('GetParameterValue', getParameterDelegate, { description: 'The delegate to call to get parameter data from a common module.' })); - const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); - const ArgumentCompleter = this.add(new Property('ArgumentCompleter', argumentCompleterDelegate, { description: 'Gets completion data for azure specific fields' })); - const ProfileName = this.add(new Property('ProfileName', System.String, { description: 'The name of the currently selected Azure profile' })); - - const moduleIdentity = this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); - const currentProfile = this.add(new Field('Profile', dotnet.String, { initialValue: System.String.Empty, description: 'The currently selected profile.' })); - const moduleResourceId = this.add(new LambdaProperty('ResourceId', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The ResourceID for this module (azure arm).' })); - - /* get parameter method (calls azAccounts) */ - this.add(new LambdaMethod('GetParameter', dotnet.Object, new LiteralExpression(`${GetParameterValue.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value}, ${$this.pInvocationInfo.value}, ${$this.pCorrelationId.value},${$this.pParameterName.value} )`), { - parameters: [this.pInvocationInfo, this.pCorrelationId, this.pParameterName], - description: 'Gets parameters from a common module.', - returnsDescription: 'The parameter value from the common module. (Note: this should be type converted on the way back)' - })); - - /* signal method (calls azAccounts) */ - const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); - const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { - parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pCorrelationId, this.pProcessRecordId, this.pException], async: Modifier.Async, - description: 'Called to dispatch events to the common module listener', - returnsDescription: `A that will be complete when handling of the event is completed.` - })); - - signalImpl.push(Using('NoSynchronizationContext', '')); - signalImpl.add(function* () { - yield `await ${EventListener.value}?.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName}, ${$this.pCorrelationId},${$this.pProcessRecordId},${$this.pException});`; - }); - - /* init method */ - this.initMethod.add(function* () { - yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipeline.value}.Prepend(step); } , (step)=> { ${$this.fPipeline.value}.Append(step); } );`; - yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipelineWithProxy.value}.Prepend(step); } , (step)=> { ${$this.fPipelineWithProxy.value}.Append(step); } );`; - yield 'CustomInit();'; - }); - - this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { - parameters: [this.pInvocationInfo, this.pCorrelationId, this.pProcessRecordId, this.pParameterSetNameWithDefault], - description: 'Creates an instance of the HttpPipeline for each call.', - returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` - })); - - /* pipeline create method */ - this.createPipelineMethod.add(function* () { - const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); - yield pip.declarationStatement; - yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); - yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield `pipeline.Append(new Runtime.CmdInfoHandler(${$this.pProcessRecordId}, ${$this.pInvocationInfo.use}, ${$this.pParameterSetName}).SendAsync);`; - yield `${OnNewRequest.value}?.Invoke( ${$this.pInvocationInfo.use}, ${$this.pCorrelationId},${$this.pProcessRecordId}, (step)=> { ${pip}.Prepend(step); } , (step)=> { ${pip}.Append(step); } );`; - yield Return(pip); - }); - } -} - export class NewModuleClass extends Class { // get the name of the client API class @@ -352,7 +71,7 @@ export class NewModuleClass extends Class { fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); - constructor(namespace: Namespace, private readonly state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, private readonly state: State, objectInitializer?: DeepPartial) { super(namespace, 'Module'); this.apply(objectInitializer); this.partial = true; diff --git a/powershell/module/module-namespace.ts b/powershell/module/module-namespace.ts index 6913ba6936b..f6afc90087e 100644 --- a/powershell/module/module-namespace.ts +++ b/powershell/module/module-namespace.ts @@ -4,35 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; -import { ModuleClass, NewModuleClass } from './module-class'; +import { State } from '../internal/state'; +import { NewModuleClass } from './module-class'; import { DeepPartial } from '@azure-tools/codegen'; export class ModuleNamespace extends Namespace { - public moduleClass: ModuleClass; - - public get outputFolder(): string { - return this.state.project.moduleFolder; - } - - constructor(public state: State, objectInitializer?: DeepPartial) { - super(state.model.details.csharp.namespace || 'INVALID.NAMESPACE', state.project); - this.apply(objectInitializer); - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // module class - this.moduleClass = new ModuleClass(this, state); - } -} - -export class NewModuleNamespace extends Namespace { public moduleClass: NewModuleClass; public get outputFolder(): string { return this.state.project.moduleFolder; } - constructor(public state: NewState, objectInitializer?: DeepPartial) { + constructor(public state: State, objectInitializer?: DeepPartial) { super(state.model.language.csharp?.namespace || 'INVALID.NAMESPACE', state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); diff --git a/powershell/plugins/add-azure-completers-v2.ts b/powershell/plugins/add-azure-completers-v2.ts index 81b1ac87afb..557ce432631 100644 --- a/powershell/plugins/add-azure-completers-v2.ts +++ b/powershell/plugins/add-azure-completers-v2.ts @@ -6,10 +6,10 @@ import { values } from '@azure-tools/linq'; import { Host } from '@azure-tools/autorest-extension-base'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { serialize } from '@azure-tools/codegen'; -type State = NewModelState; +type State = ModelState; const resourceGroupNames = new Set([ 'resourcegroupname', @@ -45,6 +45,6 @@ async function tweakModel(state: State): Promise { export async function addCompleterV2(service: Host) { - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-add-azure-completers-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/add-azure-completers.ts b/powershell/plugins/add-azure-completers.ts deleted file mode 100644 index 3dd1a7f22cd..00000000000 --- a/powershell/plugins/add-azure-completers.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, processCodeModel, ModelState } from '@azure-tools/codemodel-v3'; -import { values } from '@azure-tools/linq'; -import { Host } from '@azure-tools/autorest-extension-base'; - -type State = ModelState; - -const resourceGroupNames = new Set([ - 'resourcegroupname', - 'resourcegroup', -]); -const subscriptionIdNames = new Set([ - 'subscriptionid', -]); -const locationNames = new Set([ - 'location', -]); - -async function tweakModel(state: State): Promise { - const model = state.model; - for (const operation of values(model.commands.operations)) { - for (const parameter of values(operation.parameters)) { - const parameterName = parameter.details.csharp.name.toLowerCase(); - if (resourceGroupNames.has(parameterName)) { - parameter.details.csharp.completer = 'ResourceGroup'; - } - if (subscriptionIdNames.has(parameterName)) { - parameter.details.csharp.completer = 'SubscriptionId'; - } - if (locationNames.has(parameterName)) { - parameter.details.csharp.completer = 'Location'; - } - // 'Resource' - // 'ResourceId' - } - } - return model; -} - - -export async function addCompleter(service: Host) { - return processCodeModel(tweakModel, service, 'add-azure-completers'); -} diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index d53d8132d1e..fc36205364f 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { HttpMethod, codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -//import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Schema } from '../llcsharp/exports'; @@ -14,11 +13,11 @@ import { clone } from '@azure-tools/linq'; import { verbs } from '../internal/verbs'; import { PwshModel } from '../utils/PwshModel'; import { IParameter } from '../utils/components'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; //import { Schema as SchemaV3 } from '../utils/schema'; import { CommandOperation } from '../utils/command-operation'; -type State = NewModelState; +type State = ModelState; // UNUSED: Moved to plugin-tweak-model.ts in remodeler @@ -478,7 +477,7 @@ export async function createCommandsV2(service: Host) { // return processCodeModel(commandCreator, service); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-createcommands-v2.yaml', serialize(await (await new Inferrer(state).init()).createCommands()), undefined, 'code-model-v4'); // return processCodeModel(async (state) => { diff --git a/powershell/plugins/create-commands.ts b/powershell/plugins/create-commands.ts deleted file mode 100644 index 1e9c2ee92e3..00000000000 --- a/powershell/plugins/create-commands.ts +++ /dev/null @@ -1,454 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; -import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { Schema } from '../llcsharp/exports'; -import { Channel, Host } from '@azure-tools/autorest-extension-base'; -import { Lazy } from '@azure-tools/tasks'; -import { clone } from '@azure-tools/linq'; -import { verbs } from '../internal/verbs'; - -type State = ModelState; - - -// UNUSED: Moved to plugin-tweak-model.ts in remodeler -// For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. -export function titleToAzureServiceName(title: string): string { - const titleCamelCase = pascalCase(deconstruct(title)).trim(); - const serviceName = titleCamelCase - // Remove: !StartsWith(Management)AndContains(Management), Client, Azure, Microsoft, APIs, API, REST - .replace(/(?!^Management)(?=.*)Management|Client|Azure|Microsoft|APIs|API|REST/g, '') - // Remove: EndsWith(ServiceResourceProvider), EndsWith(ResourceProvider), EndsWith(DataPlane), EndsWith(Data) - .replace(/ServiceResourceProvider$|ResourceProvider$|DataPlane$|Data$/g, ''); - return serviceName || titleCamelCase; -} - - -const pluralizationService = new EnglishPluralizationService(); -pluralizationService.addWord('Database', 'Databases'); -pluralizationService.addWord('database', 'databases'); - - -interface CommandVariant { - alias: Array; - verb: string; - subject: string; - subjectPrefix: string; - variant: string; - action: string; -} - - -function fn(active: Array, remaining: Array, result: Array>): Array> { - if (length(active) || length(remaining)) { - if (length(remaining)) { - fn([...active, remaining[0]], remaining.slice(1), result); - fn(active, remaining.slice(1), result); - } else { - result.push(active); - } - } - return result; -} -function combinations(elements: Array) { - return fn([], elements, []); -} - -function splitOnPreposition(preposition: string, parts: Array) { - const i = parts.indexOf(preposition); - if (i > 0) { - return [ - parts.slice(0, i), - parts.slice(i + 1) - ]; - } - return undefined; -} - -function splitOnAnyPreposition(parts: Array) { - for (const p of ['with', 'at', 'by', 'for', 'in', 'of']) { - const result = splitOnPreposition(p, parts); - if (result && result[0].length > 0) { - // we found it, let's give it back. - return result; - } - } - return undefined; -} - - -export /* @internal */ class Inferrer { - commonParameters = new Array(); - verbMap!: { [operationIdMethod: string]: string }; - prefix!: string; - serviceName!: string; - subjectPrefix!: string; - isAzure!: boolean; - - constructor(private state: State) { - } - async init() { - this.commonParameters = await this.state.getValue('azure', false) ? [ - // 'resourceGroupName', - 'subscriptionId' - ] : []; - - this.verbMap = await this.state.getValue('verb-mapping') || {}; - this.isAzure = await this.state.getValue('azure', false); - this.prefix = await this.state.getValue('prefix'); - this.serviceName = titleToAzureServiceName(await this.state.getValue('service-name')); - this.state.setValue('service-name', this.serviceName); - - this.subjectPrefix = await this.state.getValue('subject-prefix'); - - this.state.setValue('isAzure', this.isAzure); - this.state.setValue('prefix', this.prefix); - - const model = this.state.model; - - this.state.message({ - Channel: Channel.Debug, Text: `[CMDLET-PREFIX] => '${model.details.default.prefix}'` - }); - - model.details.default.serviceName = this.serviceName; - this.state.message({ - Channel: Channel.Debug, Text: `[SERVICE-NAME] => '${model.details.default.serviceName}'` - }); - - model.details.default.subjectPrefix = this.subjectPrefix; - this.state.message({ - Channel: Channel.Debug, Text: `[SUBJECT-PREFIX] => '${model.details.default.subjectPrefix}'` - }); - - return this; - } - - async createCommands() { - const model = this.state.model; - this.state.model.commands = { - operations: new Dictionary(), - parameters: new Dictionary(), - }; - - this.state.message({ Channel: Channel.Debug, Text: 'detecting high level commands...' }); - - for (const operation of values(model.http.operations)) { - for (const variant of await this.inferCommandNames(operation, this.state)) { - // no common parameters (standard variations) - await this.addVariants(operation.parameters, operation, variant, '', this.state); - } - } - return model; - } - - inferCommand(operation: Array, group: string, suffix: Array = []): Array { - operation = operation.filter(each => each !== 'all'); - // no instant match - switch (length(operation)) { - case 0: - throw new Error('Missing operation id?'); - - case 1: - // simple operation, just an id with a single value - // OPERATION => OPERATION-GROUP - return [ - this.createCommandVariant(operation[0], deconstruct(group), suffix, this.state.model) - ]; - - case 2: - // should try to infer [SUBJECT] and [ACTION] from operation - if (verbs.has(operation[0])) { - // [ACTION][SUBJECT] - return [ - this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) - ]; - } - if (verbs.has(operation[1])) { - // [SUBJECT][ACTION] - return [ - this.createCommandVariant(operation[1], [...deconstruct(group), operation[0]], suffix, this.state.model) - ]; - - } - // can't tell which is the [ACTION] -- let's return it the way we used to, - // but now let's mention that we are doing that. - this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); - return [ - this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) - ]; - - } - // three or more words. - // first, see if it's an 'or' - const either = splitOnPreposition('or', operation); - if (either) { - // looks like we got two sets of operations from this. - return [ - ...this.inferCommand([...either[0], ...either[1].slice(1)], group, suffix), - ...this.inferCommand(either[1], group, suffix), - ]; - } - - // any other preposition? - const parts = splitOnAnyPreposition(operation); - if (parts) { - // so this is something like DoActionWithStyle - return [...this.inferCommand(parts[0], group, parts[1])]; - } - - // if not, then seek out a verb from there. - for (let i = 0; i < length(operation); i++) { - if (verbs.has(operation[i])) { - // if the action is first - if (i === 0) { - // everything else is the subject - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i + 1)] : operation.slice(i + 1), suffix, this.state.model)]; - } - if (i === length(operation) - 1) { - // if it's last, the subject would be the first thing - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(0, i)] : operation.slice(0, i), suffix, this.state.model)]; - } - - // otherwise - // things before are part of the subject - // things after the verb should be part of the suffix - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i, i)] : operation.slice(i, i), [...suffix, ...operation.slice(i + 1)], this.state.model)]; - } - } - - // so couldn't tell what the action was. - // fallback to the original behavior with a warning. - this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); - return [this.createCommandVariant(operation[0], group ? [...deconstruct(group), ...operation.slice(1)] : operation.slice(1), [...suffix, ...operation.slice(1)], this.state.model)]; - } - - async inferCommandNames(op: http.HttpOperation, state: State): Promise> { - const operationId = op.operationId || ''; - - let [group, method] = operationId.split('_', 2); - if (!method) { - if (!group) { - // no operation id at all? - const path = op.path.replace(/{.*?}/g, '').replace(/\/+/g, '/').replace(/\/$/g, ''); - method = path.split('/').last; - } else { - // no group given, use string as method - method = group; - } - group = pascalCase(op.tags) || ''; - - } - - const groupWords = deconstruct(group); - groupWords[groupWords.length - 1] = pluralizationService.singularize(groupWords.last); - - group = pascalCase(groupWords); - const operation = deconstruct(method); - - // instant match - if (this.verbMap[method]) { - return [this.createCommandVariant(method, [group], [], state.model)]; - } - - // dig deeper. - return this.inferCommand(operation, group); - } - - async addVariant(vname: string, body: http.RequestBody | undefined, bodyParameterName: string, parameters: Array, operation: http.HttpOperation, variant: CommandVariant, state: State) { - const op = await this.addCommandOperation(vname, parameters, operation, variant, state); - - // if this has a body with it, let's add that parameter - if (body && body.schema) { - op.details.default.hasBody = true; - op.parameters.push(new components.IParameter(bodyParameterName, body.schema, { - details: { - default: { - description: body.schema.details.default.description, - name: pascalCase(bodyParameterName), - isBodyParameter: true, - } - } - })); - - // let's add a variant where it's expanded out. - // *IF* the body is an object - if (body.schema.type === JsonType.Object) { - const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); - opExpanded.details.default.dropBodyParameter = true; - opExpanded.parameters.push(new components.IParameter(`${bodyParameterName}Body`, body.schema, { - details: { - default: { - description: body.schema.details.default.description, - name: pascalCase(`${bodyParameterName}Body`), - isBodyParameter: true, - } - } - })); - } - } - } - - - isNameConflict(model: codemodel.Model, variant: CommandVariant, vname: string) { - for (const each of values(model.commands.operations)) { - if (each.details.default.name === vname) { - return true; - } - } - return false; - } - - // for tracking unique operation identities - operationIdentities = new Set(); - - async addCommandOperation(vname: string, parameters: Array, operation: http.HttpOperation, variant: CommandVariant, state: State): Promise { - let apiversion = ''; - - for (const each of items(operation.responses)) { - for (const rsp of each.value) { - if (rsp.schema && rsp.schema.details && rsp.schema.details.default && rsp.schema.details.default.apiversion) { - apiversion = rsp.schema.details.default.apiversion; - break; - } - } - } - - // if vname is > 64 characters, let's trim it - // after trimming it, make sure there aren't any other operation with a name that's exactly the same - if (length(vname) > 64) { - const names = deconstruct(vname); - let newVName = ''; - for (let i = 0; i < length(names); i++) { - newVName = pascalCase(names.slice(0, i)); - if (length(newVName) > 60) { - break; - } - } - vname = newVName; - } - - // if we have an identical vname, let's add 'etc' - let fname = `${variant.verb}-${variant.subject}-${vname}`; - let n = 1; - while (this.operationIdentities.has(fname)) { - vname = `${vname.replace(/\d*$/g, '')}${n++}`; - fname = `${variant.verb}-${variant.subject}-${vname}`; - } - this.operationIdentities.add(fname); - - variant.variant = vname; - vname = pascalCase(vname); - const xmsMetadata = operation.pathExtensions ? operation.pathExtensions['x-ms-metadata'] ? clone(operation.pathExtensions['x-ms-metadata']) : {} : {}; - - return state.model.commands.operations[`${length(state.model.commands.operations)}`] = new command.CommandOperation(operation.operationId, { - asjob: operation.details.default.asjob ? true : false, - extensions: { - ...operation.pathExtensions, - 'x-ms-metadata': xmsMetadata - }, - ...variant, - details: { - ...operation.details, - default: { - ...operation.details.default, - subject: variant.subject, - subjectPrefix: variant.subjectPrefix, - verb: variant.verb, - name: vname, - alias: variant.alias - } - }, - operationId: operation.operationId, - parameters: parameters.map(httpParameter => { - // make it's own copy of the parameter since after this, - // the parameter can be altered for each operation individually. - const each = clone(httpParameter, false, undefined, undefined, ['schema', 'origin']); - each.details.default = { - ...each.details.default, - name: pascalCase(each.details.default.name), - httpParameter - }; - return each; - }), - callGraph: [operation], - }); - } - - async addVariants(parameters: Array, operation: http.HttpOperation, variant: CommandVariant, vname: string, state: State) { - // now synthesize parameter set variants multiplexed by the variants. - const [constants, requiredParameters] = values(parameters).bifurcate(parameter => parameter.details.default.constantValue || parameter.details.default.fromHost ? true : false); - const constantParameters = constants.map(each => `'${each.details.default.constantValue}'`); - - // the body parameter - const body = operation.requestBody; - const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : ''; - - // all the properties in the body parameter - const bodyProperties = (body && body.schema) ? values(getAllProperties(body.schema)).where(property => !property.details.default.readOnly).toArray() : []; - - // smash body property names together - const bodyPropertyNames = bodyProperties.joinWith(each => each.details.default.name); - - // for each polymorphic body, we should do a separate variant that takes the polymorphic body type instead of the base type - const polymorphicBodies = (body && body.schema && body.schema.details.default.polymorphicChildren && length(body.schema.details.default.polymorphicChildren)) ? (>body.schema.details.default.polymorphicChildren).joinWith(child => child.details.default.name) : ''; - - // wait! "update" should be "set" if it's a POST - if (variant.verb === 'Update' && operation.method === http.HttpMethod.Put) { - variant.verb = 'Set'; - } - - // create variant - state.message({ Channel: Channel.Debug, Text: `${variant.verb}-${variant.subject} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${bodyPropertyNames} ${polymorphicBodies ? `; Polymorphic bodies: ${polymorphicBodies} ` : ''}` }); - await this.addVariant(pascalCase([variant.action, vname]), body, bodyParameterName, [...constants, ...requiredParameters], operation, variant, state); - - const [pathParams, otherParams] = values(requiredParameters).bifurcate(each => each.in === ParameterLocation.Path); - const dvi = await state.getValue('disable-via-identity', false); - - if (!dvi && length(pathParams) > 0 && variant.action.toLowerCase() != 'list') { - // we have an operation that has path parameters, a good canididate for piping for identity. - await this.addVariant(pascalCase([variant.action, vname, 'via-identity']), body, bodyParameterName, [...constants, ...otherParams], operation, variant, state); - } - - } - - createCommandVariant(action: string, subject: Array, variant: Array, model: codemodel.Model): CommandVariant { - const verb = this.getPowerShellVerb(action); - if (verb === 'Invoke') { - // if the 'operation' name was "post" -- it's kindof redundant. - // so, only include the operation name in the group name if it's anything else - if (action.toLowerCase() !== 'post') { - subject = [action, ...subject]; - } - } - - return { - alias: [], - subject: pascalCase([...removeSequentialDuplicates(subject.map(each => pluralizationService.singularize(each)))]), - variant: pascalCase(variant), - verb, - subjectPrefix: model.details.default.subjectPrefix, - action - }; - } - - getPowerShellVerb(action: string): string { - const verb = this.verbMap[pascalCase(action)]; - if (verb) { - return verb; - } else { - return 'Invoke'; - } - } -} - - -export async function createCommands(service: Host) { - // return processCodeModel(commandCreator, service); - return processCodeModel(async (state) => { - return await (await new Inferrer(state).init()).createCommands(); - }, service, 'createCommands'); -} \ No newline at end of file diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 3443cd53c70..be6a2e70d71 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -4,19 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, StringSchema, ChoiceSchema, SealedChoiceSchema } from '@azure-tools/codemodel'; -//import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { System } from '@azure-tools/codegen-csharp'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { SchemaDetails } from '../llcsharp/code-model'; -import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; +import { SchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { SchemaDetails as NewSchemaDetails } from '../utils/schema'; -type State = NewModelState; +type State = ModelState; function setPropertyNames(schema: Schema) { @@ -160,7 +159,7 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, } -async function setOperationNames(state: State, resolver: NewSchemaDefinitionResolver) { +async function setOperationNames(state: State, resolver: SchemaDefinitionResolver) { // keep a list of operation names that we've assigned. const operationNames = new Set(); for (const operationGroup of values(state.model.operationGroups)) { @@ -231,7 +230,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso } async function nameStuffRight(state: State): Promise { - const resolver = new NewSchemaDefinitionResolver(); + const resolver = new SchemaDefinitionResolver(); const model = state.model; // set the namespace for the service @@ -260,7 +259,7 @@ export async function csnamerV2(service: Host) { //return processCodeModel(nameStuffRight, service, 'csnamer'); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-csnamer-v2.yaml', serialize(await nameStuffRight(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/cs-namer.ts b/powershell/plugins/cs-namer.ts deleted file mode 100644 index 4cf798a7899..00000000000 --- a/powershell/plugins/cs-namer.ts +++ /dev/null @@ -1,245 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; - -import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { System } from '@azure-tools/codegen-csharp'; - -import { Host } from '@azure-tools/autorest-extension-base'; -import { Schema, SchemaDetails } from '../llcsharp/code-model'; -import { SchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; - -type State = ModelState; - - -function setPropertyNames(schema: Schema) { - // name each property in this schema - for (const propertySchema of values(schema.properties)) { - const propertyDetails = propertySchema.details.default; - - const className = schema.details.csharp.name; - - let pname = getPascalIdentifier(propertyDetails.name); - if (pname === className) { - pname = `${pname}Property`; - } - - if (pname === 'default') { - pname = '@default'; - } - - propertySchema.details.csharp = { - ...propertyDetails, - name: pname // and so are the propertyNmaes - }; - - if (propertyDetails.isNamedStream) { - propertySchema.details.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); - } - } - -} - - -function setSchemaNames(schemas: Dictionary, azure: boolean, serviceNamespace: string) { - const baseNamespace = new Set(); - const subNamespace = new Map>(); - // dolauli need to notice this -- schemas in the namespace of the lowest supported api version - // in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion. - // otherwise, we just want to differientiate with a simple incremental numbering scheme. - - for (const schema of values(schemas)) { - let thisNamespace = baseNamespace; - let thisApiversion = ''; - - // create the namespace if required - if (azure) { - const metadata = schema.extensions && schema.extensions['x-ms-metadata']; - if (metadata) { - const apiVersions = | undefined>metadata.apiVersions; - if (apiVersions && length(apiVersions) > 0) { - thisApiversion = minimum(apiVersions); - thisNamespace = subNamespace.get(thisApiversion) || new Set(); - subNamespace.set(thisApiversion, thisNamespace); - } - } - } - - // for each schema, we're going to set the name - // to the suggested name, unless we have collisions - // at which point, we're going to add a number (for now?) - const details = schema.details.default; - let schemaName = getPascalIdentifier(details.name); - const apiName = (!thisApiversion) ? '' : getPascalIdentifier(`Api ${thisApiversion}`); - const ns = (!thisApiversion) ? [] : ['.', apiName]; - - - let n = 1; - while (thisNamespace.has(schemaName)) { - schemaName = getPascalIdentifier(`${details.name}_${n++}`); - } - thisNamespace.add(schemaName); - - // object types. - if (schema.type === JsonType.Object) { - schema.details.csharp = { - ...details, - apiversion: thisApiversion, - apiname: apiName, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), // objects have an interfaceName - internalInterfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal'])), // objects have an ineternal interfaceName for setting private members. - fullInternalInterfaceName: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal']))}`, - name: getPascalIdentifier(schemaName), - namespace: pascalCase([serviceNamespace, '.', 'Models', ...ns]), // objects have a namespace - fullname: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${getPascalIdentifier(schemaName)}`, - }; - } else if (schema.type === JsonType.String && schema.details.default.enum) { - // oh, it's an enum type - schema.details.csharp = { - ...details, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), - name: getPascalIdentifier(schema.details.default.enum.name), - namespace: pascalCase([serviceNamespace, '.', 'Support']), - fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schema.details.default.enum.name)}`, - enum: { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name), - values: schema.details.default.enum.values.map(each => { - return { - ...each, - name: getPascalIdentifier(each.name), - description: each.description - }; - }) - } - }; - } else { - schema.details.csharp = { - ...details, - interfaceName: '', - internalInterfaceName: '', - name: schemaName, - namespace: '', - fullname: '' - }; - } - - // name each property in this schema - setPropertyNames(schema); - - // fix enum names - if (schema.details.default.enum) { - schema.details.csharp.enum = { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name) - }; - - // and the value names themselves - for (const value of values(schema.details.csharp.enum.values)) { - value.name = getPascalIdentifier(value.name); - } - } - } - -} - -async function setOperationNames(state: State, resolver: SchemaDefinitionResolver) { - // keep a list of operation names that we've assigned. - const operationNames = new Set(); - - for (const operation of values(state.model.http.operations)) { - const details = operation.details.default; - - // come up with a name - const oName = getPascalIdentifier(details.name); - let i = 1; - let operationName = oName; - while (operationNames.has(operationName)) { - // if we have used that name, try again. - operationName = `${oName}${i++}`; - } - operationNames.add(operationName); - - operation.details.csharp = { - ...details, // inherit - name: operationName, - }; - - // parameters are camelCased. - for (const parameter of values(operation.parameters)) { - const parameterDetails = parameter.details.default; - - let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name))); - - if (propName === 'default') { - propName = '@default'; - } - - parameter.details.csharp = { - ...parameterDetails, - name: propName - }; - } - - for (const responses of values(operation.responses)) { - // per responseCode - for (const response of values(responses)) { - const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state.path('schemas', response.schema.details.default.name)) : undefined; - const headerTypeDefinition = response.headerSchema ? resolver.resolveTypeDeclaration(response.headerSchema, true, state.path('schemas', response.headerSchema.details.default.name)) : undefined; - let code = (System.Net.HttpStatusCode[response.responseCode] ? System.Net.HttpStatusCode[response.responseCode].value : response.responseCode).replace('global::System.Net.HttpStatusCode', ''); - let rawValue = code.replace(/\./, ''); - if (response.responseCode === 'default' || rawValue === 'default' || '') { - rawValue = 'any response code not handled elsewhere'; - code = 'default'; - } - response.details.csharp = { - ...response.details.default, - responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '', - headerType: headerTypeDefinition ? headerTypeDefinition.declaration : '', - name: (length(responses) <= 1) ? - camelCase(fixLeadingNumber(deconstruct(`on ${code}`))) : // the common type (or the only one.) - camelCase(fixLeadingNumber(deconstruct(`on ${code} ${response.mimeTypes[0]}`))), - description: (length(responses) <= 1) ? - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}).` : - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}) with a Content-Type matching ${response.mimeTypes.join(',')}.` - - }; - } - } - } -} - -async function nameStuffRight(state: State): Promise { - const resolver = new SchemaDefinitionResolver(); - const model = state.model; - - // set the namespace for the service - const serviceNamespace = await state.getValue('namespace', 'Sample.API'); - const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false); - const clientName = getPascalIdentifier(model.details.default.name); - - // dolauli see model.details.csharp for c# related staff - // set c# client details (name) - model.details.csharp = { - ...model.details.default, // copy everything by default - name: clientName, - namespace: serviceNamespace, - fullname: `${serviceNamespace}.${clientName}` - }; - - setSchemaNames(>model.schemas, azure, serviceNamespace); - await setOperationNames(state, resolver); - - return model; -} - - -export async function csnamer(service: Host) { - // dolauli add names for http operations and schemas - return processCodeModel(nameStuffRight, service, 'csnamer'); -} - diff --git a/powershell/plugins/llcsharp-v2.ts b/powershell/plugins/llcsharp-v2.ts index a5c14fed490..c90a8a2c61d 100644 --- a/powershell/plugins/llcsharp-v2.ts +++ b/powershell/plugins/llcsharp-v2.ts @@ -7,8 +7,7 @@ import { codeModelSchema } from '@azure-tools/codemodel'; import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; import { join } from 'path'; import { Model } from '../llcsharp/code-model'; -import { State } from '../llcsharp/generator'; -import { Project, NewProject } from '../llcsharp/project'; +import { Project } from '../llcsharp/project'; import { PwshModel } from '../utils/PwshModel'; import { Dictionary } from '@azure-tools/linq'; @@ -16,7 +15,7 @@ const resources = `${__dirname}/../../resources`; export async function llcsharpV2(service: Host) { try { - const project = await new NewProject(service).init(); + const project = await new Project(service).init(); await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); diff --git a/powershell/plugins/llcsharp.ts b/powershell/plugins/llcsharp.ts deleted file mode 100644 index b4735cdffbf..00000000000 --- a/powershell/plugins/llcsharp.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { Host } from '@azure-tools/autorest-extension-base'; -import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; -import { join } from 'path'; -import { Model } from '../llcsharp/code-model'; -import { State } from '../llcsharp/generator'; -import { Project } from '../llcsharp/project'; -import { Dictionary } from '@azure-tools/linq'; - -const resources = `${__dirname}/../../resources`; - -export async function llcsharp(service: Host) { - try { - const project = await new Project(service).init(); - - await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); - - // recursive copy resources - await copyResources(join(resources, 'runtime', 'csharp', 'client'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - await copyResources(join(resources, 'runtime', 'csharp', 'pipeline'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - // Note: - // we are using the Carbon.Json library, but we don't *really* want to expose that as public members where we don't have to - // and I don't want to make code changes in the source repository, so I can keep merging from upstream as simple as possible. - // so, we're converting as much as possible to internal, and exposing only what must be exposed to make the code compile. - - await copyResources(join(resources, 'runtime', 'csharp', 'json'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), { - ...project.overrides, - 'public': 'internal', - 'internal (.*) class JsonNumber': 'public $1 class JsonNumber', - 'internal (.*) class JsonObject': 'public $1 class JsonObject', - 'internal (.*) class JsonNode': 'public $1 class JsonNode', - 'internal (.*) class JsonString': 'public $1 class JsonString', - 'internal (.*) class XNodeArray': 'public $1 class XNodeArray', - 'internal (.*) class JsonArray': 'public $1 class JsonArray', - 'internal(.*) class JsonTokenizer': 'public$1 class JsonTokenizer', - 'internal(.*) class JsonParser': 'public$1 class JsonParser', - 'internal(.*) class TokenReader': 'public$1 class TokenReader', - 'internal(.*) class SourceReader': 'public$1 class SourceReader', - 'internal(.*) class (.*)Converter': 'public$1 class $2Converter', - 'internal(.*) interface IJsonSerializable': 'public$1 interface IJsonSerializable', - 'internal override string ToString': 'public override string ToString', - 'internal void Add\\(': 'public void Add(', - 'internal bool ContainsKey\\(': 'public bool ContainsKey(', - 'internal bool Remove\\(': 'public bool Remove(', - 'internal bool TryGetValue\\(': 'public bool TryGetValue(', - 'internal (.*) JsonNode this\\[': 'public $1 JsonNode this[', - - 'internal ICollection Values': 'public ICollection Values', - 'internal ICollection Keys': 'public ICollection Keys', - 'internal bool IsReadOnly': 'public bool IsReadOnly', - 'internal (.*) int Count': 'public $1 int Count', - 'internal bool Contains\\(': 'public bool Contains(', - 'internal(.*) bool Equals': 'public$1 bool Equals', - 'internal (.*) int GetHashCode': 'public $1 int GetHashCode', - 'internal void Dispose': 'public void Dispose', - 'internal (.*) operator': 'public $1 operator', - 'internal object FromJson\\(': 'public object FromJson(', - 'internal JsonNode ToJson\\(': 'public JsonNode ToJson(', - - }); - - if (project.xmlSerialization) { - await copyResources(join(resources, 'runtime', 'csharp', 'xml'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - } - - if (project.azure) { - await copyResources(join(resources, 'runtime', 'csharp.azure'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - } - - } catch (E) { - console.error(`${__filename} - ${E.stack}/${E.message}`); - throw E; - } -} diff --git a/powershell/plugins/modifiers-v2.ts b/powershell/plugins/modifiers-v2.ts index 7ad674ad718..007c698777e 100644 --- a/powershell/plugins/modifiers-v2.ts +++ b/powershell/plugins/modifiers-v2.ts @@ -3,19 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, ModelState, command } from '@azure-tools/codemodel-v3'; import { Host, Channel } from '@azure-tools/autorest-extension-base'; import { pascalCase, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { stat } from 'fs'; import { CommandOperation } from '../utils/command-operation'; // import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { PwshModel } from '../utils/PwshModel'; import { allVirtualParameters, allVirtualProperties } from '../utils/resolve-conflicts'; import { EnumValue } from '../utils/schema'; -type State = NewModelState; +type State = ModelState; let directives: Array = []; @@ -709,7 +708,7 @@ export async function applyModifiersV2(service: Host) { .where(directive => isWhereCommandDirective(directive) || isWhereModelDirective(directive) || isWhereEnumDirective(directive) || isRemoveCommandDirective(directive)) .toArray(); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); const result = await tweakModel(state); await service.WriteFile('code-model-v4-modifiers-v2.yaml', serialize(result), undefined, 'code-model-v4'); diff --git a/powershell/plugins/modifiers.ts b/powershell/plugins/modifiers.ts deleted file mode 100644 index e6928d1e7f3..00000000000 --- a/powershell/plugins/modifiers.ts +++ /dev/null @@ -1,701 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, ModelState, command } from '@azure-tools/codemodel-v3'; -import { Host, Channel } from '@azure-tools/autorest-extension-base'; -import { pascalCase } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; - -type State = ModelState; - -let directives: Array = []; - -interface WhereCommandDirective { - select?: string; - where: { - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - }; - set?: { - 'alias': Array | string; - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - 'parameter-description'?: string; - 'completer'?: { - name: string; - description: string; - script: string; - }; - 'default'?: { - name: string; - description: string; - script: string; - }; - }; - 'clear-alias': boolean; - hide?: boolean; -} -interface RemoveCommandDirective { - select?: string; - where: { - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - }; - remove: boolean; -} - - -function hasSpecialChars(str: string): boolean { - return !/^[a-zA-Z0-9]+$/.test(str); -} - - -function getFilterError(whereObject: any, prohibitedFilters: Array, selectionType: string): string { - let error = ''; - for (const each of values(prohibitedFilters)) { - if (whereObject[each] !== undefined) { - error += `Can't filter by ${each} when selecting command. `; - } - } - - return error; -} - -function getSetError(setObject: any, prohibitedSetters: Array, selectionType: string): string { - let error = ''; - for (const each of values(prohibitedSetters)) { - if (setObject[each] !== undefined) { - error += `Can't set ${each} when a ${selectionType} is selected. `; - } - } - - return error; -} - - -function isWhereCommandDirective(it: any): it is WhereCommandDirective { - const directive = it; - const select = directive.select; - const where = directive.where; - const set = directive.set; - if (directive.remove === undefined && where && (where.verb || where.variant || where['parameter-name'] || where.subject || where['subject-prefix'] || directive.hide || select === 'command' || select === 'parameter' || directive['clear-alias'])) { - const prohibitedFilters = ['model-name', 'property-name', 'enum-name', 'enum-value-name']; - let error = getFilterError(where, prohibitedFilters, 'command'); - - if (set !== undefined) { - const prohibitedSetters = ['property-name', 'property-description', ' model-name', 'enum-name', 'enum-value-name']; - error += getSetError(set, prohibitedSetters, 'command'); - } - - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); - } - - return true; - } - - return false; -} - -function isRemoveCommandDirective(it: any): it is RemoveCommandDirective { - const directive = it; - const where = directive.where; - const remove = directive.remove; - if (where && remove && (where.subject || where.verb || where.variant || where['subject-prefix'] || where['parameter-name'] || directive.select === 'command') && directive.select !== 'parameter') { - return true; - } - - return false; -} - - -interface WhereModelDirective { - select?: string; - where: { - 'model-name'?: string; - 'model-fullname'?: string; - 'model-namespace'?: string; - 'property-name'?: string; - }; - set: { - 'suppress-format'?: boolean; - 'format-table'?: { - 'properties'?: Array; - 'exclude-properties'?: Array; - 'labels'?: { [name: string]: string }; - 'width'?: { [name: string]: number }; - }; - 'model-name'?: string; - 'property-name'?: string; - 'property-description'?: string; - }; -} - -function isWhereModelDirective(it: any): it is WhereModelDirective { - const directive = it; - const where = directive.where; - const set = directive.set; - - - if (where && set && (where['model-name'] || where['model-fullname'] || where['model-namespace'] || where['property-name'] || directive.select === 'model')) { - const prohibitedFilters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; - let error = getFilterError(where, prohibitedFilters, 'enum'); - const prohibitedSetters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; - error += getSetError(set, prohibitedSetters, 'enum'); - const modelSelectNameConflict = []; - let modelSelectNameType = ''; - if (where['model-name']) { - modelSelectNameType = 'model-name'; - if (where['model-fullname']) { - modelSelectNameConflict.push('model-fullname'); - } - - if (where['model-namespace']) { - modelSelectNameConflict.push('model-namespace'); - } - } else if (where['model-fullname']) { - modelSelectNameType = 'model-fullname'; - if (where['model-name']) { - modelSelectNameConflict.push('model-name'); - } - - if (where['model-namespace']) { - modelSelectNameConflict.push('model-namespace'); - } - } else if (where['model-namespace']) { - modelSelectNameType = 'model-namespace'; - if (where['model-fullname']) { - modelSelectNameConflict.push('model-fullname'); - } - - if (where['model-name']) { - modelSelectNameConflict.push('model-name'); - } - } - - if (length(modelSelectNameConflict) > 0) { - error += `Can't select ${modelSelectNameType} and ${modelSelectNameConflict} at the same time`; - } - - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}.Reason: ${error}.`); - } - - return true; - - } - return false; -} - -interface WhereEnumDirective { - select?: string; - where: { - 'enum-name'?: string; - 'enum-value-name'?: string; - }; - set: { - 'enum-name'?: string; - 'enum-value-name'?: string; - }; -} - -function isWhereEnumDirective(it: any): it is WhereEnumDirective { - const directive = it; - const where = directive.where; - const set = directive.set; - if (where && set && (where['enum-name'] || where['enum-value-name'] || directive.select === 'enum')) { - const prohibitedFilters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; - let error = getFilterError(where, prohibitedFilters, 'enum'); - const prohibitedSetters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; - error += getSetError(set, prohibitedSetters, 'enum'); - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); - } - - return true; - } - return false; -} - -async function tweakModel(state: State): Promise { - - // only look at directives without the `transform` node. - // dolauli for directives with transform are implemented in autorest core - for (const directive of directives.filter(each => !each.transform)) { - const getPatternToMatch = (selector: string | undefined): RegExp | undefined => { - return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined; - }; - - if (isWhereCommandDirective(directive)) { - const selectType = directive.select; - const clearAlias = directive['clear-alias']; - const subjectRegex = getPatternToMatch(directive.where['subject']); - const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); - const verbRegex = getPatternToMatch(directive.where.verb); - const variantRegex = getPatternToMatch(directive.where.variant); - const parameterRegex = getPatternToMatch(directive.where['parameter-name']); - - const alias = - (directive.set !== undefined) ? - (directive.set.alias !== undefined) ? - !Array.isArray(directive.set.alias) ? - [directive.set.alias] - : directive.set.alias - : undefined - : undefined; - const subjectReplacer = (directive.set !== undefined) ? directive.set['subject'] : undefined; - const subjectPrefixReplacer = (directive.set !== undefined) ? directive.set['subject-prefix'] : undefined; - const verbReplacer = (directive.set !== undefined) ? directive.set.verb : undefined; - const variantReplacer = (directive.set !== undefined) ? directive.set.variant : undefined; - const parameterReplacer = (directive.set !== undefined) ? directive.set['parameter-name'] : undefined; - const paramDescriptionReplacer = (directive.set !== undefined) ? directive.set['parameter-description'] : undefined; - const paramCompleterReplacer = (directive.set !== undefined) ? directive.set['completer'] : undefined; - const paramDefaultReplacer = (directive.set !== undefined) ? directive.set['default'] : undefined; - - // select all operations - let operations: Array = values(state.model.commands.operations).toArray(); - if (subjectRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.subject}`.match(subjectRegex)) - .toArray(); - } - - if (subjectPrefixRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.subjectPrefix}`.match(subjectPrefixRegex)) - .toArray(); - } - - if (verbRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.verb}`.match(verbRegex)) - .toArray(); - } - - if (variantRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.name}`.match(variantRegex)) - .toArray(); - } - - if (parameterRegex && selectType === 'command') { - operations = values(operations) - .where(operation => values(allVirtualParameters(operation.details.csharp.virtualParameters)) - .any(parameter => !!`${parameter.name}`.match(parameterRegex))) - .toArray(); - } - - if (parameterRegex && (selectType === undefined || selectType === 'parameter')) { - const parameters = values(operations) - .selectMany(operation => allVirtualParameters(operation.details.csharp.virtualParameters)) - .where(parameter => !!`${parameter.name}`.match(parameterRegex)) - .toArray(); - for (const p of values(parameters)) { - const parameter = p; - const prevName = parameter.name; - parameter.name = parameterReplacer ? parameterRegex ? parameter.name.replace(parameterRegex, parameterReplacer) : parameterReplacer : parameter.name; - parameter.description = paramDescriptionReplacer ? paramDescriptionReplacer : parameter.description; - parameter.completerInfo = paramCompleterReplacer ? paramCompleterReplacer : parameter.completerInfo; - parameter.defaultInfo = paramDefaultReplacer ? paramDefaultReplacer : parameter.defaultInfo; - - if (clearAlias) { - parameter.alias = []; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from parameter ${parameter.name}.` - }); - } - - if (alias) { - const parsedAlias = new Array(); - for (const each of values(alias)) { - parsedAlias.push(hasSpecialChars(each) ? prevName.replace(parameterRegex, each) : each); - } - - parameter.alias = [...new Set(values(parameter.alias, parsedAlias).toArray())]; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to parameter ${parameter.name}.` - }); - } - - if (parameterReplacer) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed parameter-name from ${prevName} to ${parameter.name}.` - }); - } - - if (paramDescriptionReplacer) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Set parameter-description from parameter ${parameter.name}.` - }); - } - } - - } else if (operations) { - for (const operation of values(operations)) { - const getCmdletName = (verb: string, subjectPrefix: string, subject: string, variantName: string): string => { - return `${verb}-${subjectPrefix}${subject}${variantName ? `_${variantName}` : ''}`; - }; - - const prevSubject = operation.details.csharp.subject; - const prevSubjectPrefix = operation.details.csharp.subjectPrefix; - const prevVerb = operation.details.csharp.verb; - const prevVariantName = operation.details.csharp.name; - const oldCommandName = getCmdletName(prevVerb, prevSubjectPrefix, prevSubject, prevVariantName); - - // set values - operation.details.csharp.subject = subjectReplacer ? subjectRegex ? prevSubject.replace(subjectRegex, subjectReplacer) : subjectReplacer : prevSubject; - operation.details.csharp.subjectPrefix = subjectPrefixReplacer !== undefined ? subjectPrefixRegex ? prevSubjectPrefix.replace(subjectPrefixRegex, subjectPrefixReplacer) : subjectPrefixReplacer : prevSubjectPrefix; - operation.details.csharp.verb = verbReplacer ? verbRegex ? prevVerb.replace(verbRegex, verbReplacer) : verbReplacer : prevVerb; - operation.details.csharp.name = variantReplacer ? variantRegex ? prevVariantName.replace(variantRegex, variantReplacer) : variantReplacer : prevVariantName; - operation.details.csharp.hidden = (directive.hide !== undefined) ? !!directive.hide : operation.details.csharp.hidden; - - const newSubject = operation.details.csharp.subject; - const newSubjectPrefix = operation.details.csharp.subjectPrefix; - const newVerb = operation.details.csharp.verb; - const newVariantName = operation.details.csharp.name; - const newCommandName = getCmdletName(newVerb, newSubjectPrefix, newSubject, newVariantName); - - // just the subject prefix can be an empty string - if (subjectPrefixReplacer !== undefined || subjectReplacer || verbReplacer || variantReplacer) { - const modificationMessage = `[DIRECTIVE] Changed command from ${oldCommandName} to ${newCommandName}. `; - state.message({ - Channel: Channel.Debug, Text: modificationMessage - }); - } - - if (clearAlias) { - operation.details.csharp.alias = []; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from command ${newCommandName}.` - }); - } - - if (alias) { - const getParsedAlias = (rawAlias: string) => { - return rawAlias.replace('${verb}', operation.details.csharp.verb) - .replace('${subject-prefix}', operation.details.csharp.subjectPrefix) - .replace('${subject}', operation.details.csharp.subject) - .replace('${variant}', operation.details.csharp.name); - }; - - const parsedAlias = new Array(); - for (const each of values(alias)) { - parsedAlias.push(getParsedAlias(each)); - } - - operation.details.csharp.alias = [...new Set(values(operation.details.csharp.alias, parsedAlias).toArray())]; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to command ${newCommandName}.` - }); - } - } - } - - continue; - } - - if (isWhereModelDirective(directive)) { - const selectType = directive.select; - const modelNameRegex = getPatternToMatch(directive.where['model-name']); - const modelFullNameRegex = getPatternToMatch(directive.where['model-fullname']); - const modelNamespaceRegex = getPatternToMatch(directive.where['model-namespace']); - const propertyNameRegex = getPatternToMatch(directive.where['property-name']); - - const modelNameReplacer = directive.set['model-name']; - const propertyNameReplacer = directive.set['property-name']; - const propertyDescriptionReplacer = directive.set['property-description']; - const formatTable = directive.set['format-table']; - const suppressFormat = directive.set['suppress-format']; - - // select all models - let models = values(state.model.schemas).toArray(); - if (modelNameRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.name}`.match(modelNameRegex)) - .toArray(); - } - - if (modelFullNameRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.fullname}`.match(modelFullNameRegex)) - .toArray(); - } - - if (modelNamespaceRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.namespace}`.match(modelNamespaceRegex)) - .toArray(); - } - - if (propertyNameRegex && selectType === 'model') { - models = values(models) - .where(model => values(allVirtualProperties(model.details.csharp.virtualProperties)) - .any(property => !!`${property.name}`.match(propertyNameRegex))) - .toArray(); - } - - if (propertyNameRegex && (selectType === undefined || selectType === 'property')) { - const properties = values(models) - .selectMany(model => allVirtualProperties(model.details.csharp.virtualProperties)) - .where(property => !!`${property.name}`.match(propertyNameRegex)) - .toArray(); - for (const property of values(properties)) { - const prevName = property.name; - property.name = propertyNameReplacer ? propertyNameRegex ? property.name.replace(propertyNameRegex, propertyNameReplacer) : propertyNameReplacer : property.name; - property.description = propertyDescriptionReplacer ? propertyDescriptionReplacer : property.description; - - if (!property.name) { - state.message({ Channel: Channel.Error, Text: `Directive '${directive.where['model-name'] || directive.where['model-fullname']}/${directive.where['property-name']}' attempted to change '${prevName}' to '' ` }); - } - if (propertyNameRegex) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed property-name from ${prevName} to ${property.name}.` - }); - } - } - - } else if (models) { - for (const model of values(models)) { - - if (suppressFormat) { - model.details.csharp.suppressFormat = true; - } - - if (formatTable !== undefined && !suppressFormat) { - const properties = allVirtualProperties(model.details.csharp.virtualProperties); - const propertiesToExclude = formatTable['exclude-properties']; - const propertiesToInclude = formatTable.properties; - const labels = formatTable.labels; - const widths = formatTable.width; - if (labels) { - const parsedLabels = new Dictionary(); - for (const label of items(labels)) { - parsedLabels[label.key.toLowerCase()] = label.value; - } - - for (const property of values(properties)) { - if (Object.keys(parsedLabels).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.label = parsedLabels[property.name.toLowerCase()]; - } - } - } - - if (widths) { - const parsedWidths = new Dictionary(); - for (const w of items(widths)) { - parsedWidths[w.key.toLowerCase()] = w.value; - } - - for (const property of values(properties)) { - if (Object.keys(parsedWidths).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.width = parsedWidths[property.name.toLowerCase()]; - } - } - } - - if (propertiesToInclude) { - const indexes = new Dictionary(); - for (const item of items(propertiesToInclude)) { - indexes[item.value.toLowerCase()] = item.key; - } - - for (const property of values(properties)) { - if (propertiesToInclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.index = indexes[property.name.toLowerCase()]; - } else { - property.format = { suppressFormat: true }; - } - } - } - - if (propertiesToExclude) { - for (const property of values(properties)) { - if (propertiesToExclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { - property.format = { suppressFormat: true }; - } - } - } - } - - const prevName = model.details.csharp.name; - model.details.csharp.name = modelNameReplacer ? modelNameRegex ? model.details.csharp.name.replace(modelNameRegex, modelNameReplacer) : modelNameReplacer : model.details.csharp.name; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed model-name from ${prevName} to ${model.details.csharp.name}.` - }); - } - } - - continue; - } - - if (isWhereEnumDirective(directive)) { - const enumNameRegex = getPatternToMatch(directive.where['enum-name']); - const enumValueNameRegex = getPatternToMatch(directive.where['enum-value-name']); - - const enumNameReplacer = directive.set['enum-name']; - const enumValueNameReplacer = directive.set['enum-value-name']; - - let enums = values(state.model.schemas) - .where(each => each.details.csharp.enum !== undefined) - .toArray(); - - if (enumNameRegex) { - enums = values(enums) - .where(each => !!`${each.details.csharp.name}`.match(enumNameRegex)) - .toArray(); - } - - if (enumValueNameRegex) { - const enumsValues = values(enums) - .selectMany(each => each.details.csharp.enum ? each.details.csharp.enum.values : []) - .where(each => !!`${each.name}`.match(enumValueNameRegex)) - .toArray(); - for (const enumValue of values(enumsValues)) { - const prevName = enumValue.name; - enumValue.name = enumValueNameReplacer ? enumNameRegex ? enumValue.name.replace(enumValueNameRegex, enumValueNameReplacer) : enumValueNameReplacer : prevName; - if (enumValueNameRegex) { - const enumNames = values(enums) - .select(each => each.details.csharp.name) - .toArray(); - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-value-name from ${prevName} to ${enumValue.name}. Enum: ${JSON.stringify(enumNames, null, 2)}` - }); - } - } - } else { - for (const each of values(enums)) { - const prevName = each.details.csharp.name; - each.details.csharp.name = enumNameReplacer ? enumNameRegex ? each.details.csharp.name.replace(enumNameRegex, enumNameReplacer) : enumNameReplacer : prevName; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-name from ${prevName} to ${each.details.csharp.name}.` - }); - } - } - - continue; - } - - - if (isRemoveCommandDirective(directive)) { - const selectType = directive.select; - const subjectRegex = getPatternToMatch(directive.where.subject); - const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); - const verbRegex = getPatternToMatch(directive.where.verb); - const variantRegex = getPatternToMatch(directive.where.variant); - const parameterRegex = getPatternToMatch(directive.where['parameter-name']); - - if (subjectRegex || subjectPrefixRegex || verbRegex || variantRegex || (parameterRegex && selectType === 'command')) { - // select all operations first then reduce by finding the intersection with selectors - let operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .select(operation => operation.key) - .toArray()); - - if (subjectRegex) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.subject}`.match(subjectRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (subjectPrefixRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.subjectPrefix}`.match(subjectPrefixRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (verbRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.verb}`.match(verbRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (variantRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.name}`.match(variantRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (parameterRegex && selectType === 'command' && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => values(allVirtualParameters(operation.value.details.csharp.virtualParameters)) - .any(parameter => !!`${parameter.name}`.match(parameterRegex))) - .where(operation => operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - for (const key of values(operationsToRemoveKeys)) { - const operationInfo = state.model.commands.operations[key].details.csharp; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Removed command ${operationInfo.verb}-${operationInfo.subjectPrefix}${operationInfo.subject}${operationInfo.name ? `_${operationInfo.name}` : ''}` - }); - - delete state.model.commands.operations[key]; - } - } - - continue; - } - } - - const operationIdentities = new Set(); - for (const operation of values(state.model.commands.operations)) { - const details = operation.details.csharp; - - let fname = `${details.verb} -${details.subject} -${details.name} `; - let n = 1; - - while (operationIdentities.has(fname)) { - details.name = pascalCase(`${details.name.replace(/\d*$/g, '')} ${n++}`); - fname = pascalCase(`${details.verb} -${details.subject} -${details.name}`); - } - operationIdentities.add(fname); - } - - return state.model; -} - -export async function applyModifiers(service: Host) { - // dolauli implement directives - const allDirectives = await service.GetValue('directive'); - directives = values(allDirectives) - // .select(directive => directive) - .where(directive => isWhereCommandDirective(directive) || isWhereModelDirective(directive) || isWhereEnumDirective(directive) || isRemoveCommandDirective(directive)) - .toArray(); - - return processCodeModel(tweakModel, service, 'modifiers'); -} diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 2d4227bd097..223d9c5f18a 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -11,7 +11,7 @@ import { Host, Session, startSession } from '@azure-tools/autorest-extension-bas //import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; import { CommandOperation } from '../utils/command-operation'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { VirtualParameter } from '../utils/command-operation'; import { VirtualProperty, getAllProperties, getAllPublicVirtualProperties } from '../utils/schema'; import { resolveParameterNames } from '../utils/resolve-conflicts'; @@ -23,7 +23,7 @@ function getPluralizationService(): EnglishPluralizationService { return result; } -type State = NewModelState; +type State = ModelState; export function singularize(word: string): string { return getPluralizationService().singularize(word); @@ -397,7 +397,7 @@ async function createVirtuals(state: State): Promise { export async function createInlinedPropertiesPlugin(service: Host) { //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-create-virtual-properties-v2.yaml', serialize(await createVirtuals(state)), undefined, 'code-model-v4'); //return processCodeModel(createVirtuals, service, 'create-virtual-properties-v2'); } diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index 3a50303699a..858c6f5f0ea 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -5,13 +5,13 @@ import { ArraySchema, CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { StatusCodes } from '../utils/http-definitions'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Host } from '@azure-tools/autorest-extension-base'; -type State = NewModelState; +type State = ModelState; let directives: Array = []; @@ -171,6 +171,6 @@ function recursiveRemoveM4DefaultDescription(schema: Schema, visited: Set(service).init(); + const state = await new ModelState(service).init(); service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/plugin-tweak-model-azure-v2.ts b/powershell/plugins/plugin-tweak-model-azure-v2.ts index 9dde68f7862..50f2ab18828 100644 --- a/powershell/plugins/plugin-tweak-model-azure-v2.ts +++ b/powershell/plugins/plugin-tweak-model-azure-v2.ts @@ -7,11 +7,11 @@ import { keys, length, values } from '@azure-tools/linq'; import { Channel, Host } from '@azure-tools/autorest-extension-base'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { PwshModel } from '../utils/PwshModel'; import { getAllProperties, ObjectSchema, Response, SchemaType, Schema } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; -type State = NewModelState; +type State = ModelState; const xmsPageable = 'x-ms-pageable'; @@ -197,6 +197,6 @@ function getSchema(response: Response): Schema { // Additional tweaks the code model to adjust things so that the code will generate better. export async function tweakModelAzurePluginV2(service: Host) { - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-tweakcodemodelazure-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/plugin-tweak-model-azure.ts b/powershell/plugins/plugin-tweak-model-azure.ts deleted file mode 100644 index 4fb91a2f8e1..00000000000 --- a/powershell/plugins/plugin-tweak-model-azure.ts +++ /dev/null @@ -1,175 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - -import { codemodel, JsonType, processCodeModel, ModelState, getAllProperties, HttpMethod, schema } from '@azure-tools/codemodel-v3'; -import { keys, length, values } from '@azure-tools/linq'; - -import { Channel, Host } from '@azure-tools/autorest-extension-base'; -type State = ModelState; - -const xmsPageable = 'x-ms-pageable'; - -async function tweakModel(state: State): Promise { - 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 operation of values(model.http.operations)) { - if (operation.extensions && operation.extensions[xmsPageable]) { - // it's marked pagable. - operation.details.default.pageable = { - responseType: 'pageable', - nextLinkName: operation.extensions[xmsPageable].nextLinkName || undefined, - itemName: operation.extensions[xmsPageable].itemName || 'value', - operationName: operation.extensions[xmsPageable].operationName || `${operation.operationId}Next`, - }; - continue; - } - - // let's just check to see if it looks like it's supposed to be a collection - for (const responses of values(operation.responses)) { - for (const response of values(responses)) { - // does the response have a schema? - if (response.schema) { - const schema = response.schema; - - // is this just an array response? - if (schema.type === JsonType.Array) { - operation.details.default.pageable = { - responseType: 'array', - }; - continue; - } - - // if it returns an object, let's see what's inside... - if (schema.type === JsonType.Object) { - - // does it have a single member that is an array (ie, value : [...]) - if (length(schema.properties) === 1 && length(schema.allOf) === 0) { - const propertyName = keys(schema.properties).first(); - if (propertyName) { - const property = schema.properties[propertyName]; - if (property.schema.type === JsonType.Array) { - // nested array! - operation.details.default.pageable = { - responseType: 'nested-array', - itemName: propertyName, - }; - } - continue; - } - } - - // does it kinda look like a x-ms-pagable (value/nextlink?) - if (length(schema.properties) === 2 && length(schema.allOf) === 0) { - if (schema.properties.nextLink) { - const propertyName = keys(schema.properties).where(each => each !== 'nextLink').first(); - if (propertyName) { - const property = schema.properties[propertyName]; - if (property.schema.type === JsonType.Array) { - // nested array! - operation.details.default.pageable = { - responseType: 'nested-array', - itemName: propertyName, - nextLinkName: 'nextLink' - }; - } - continue; - } - } - - } - - } - } - - } - } - } - - // make sure that all operations with lro have an options block. - for (const operation of values(model.http.operations)) { - if (operation.extensions && operation.extensions['x-ms-long-running-operation']) { - operation.details.default.asjob = true; - - operation.details.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 - delete operation.responses['201']; - delete operation.responses['202']; - } - } - - // 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 operation of values(model.http.operations)) { - const apiVersions = operation.pathExtensions && operation.pathExtensions['x-ms-metadata'] ? operation.pathExtensions['x-ms-metadata'].apiVersions : undefined; - for (const parameter of values(operation.parameters)) { - - if (parameter.name === '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 (length(apiVersions) === 1) { - parameter.details.default.constantValue = apiVersions[0]; - continue; - } - - // otherwise, the parameter can't have a constant value - parameter.details.default.constantValue = undefined; - - // mark it so that we can add profile support in the method generation - parameter.details.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 values(model.schemas)) { - // find schemas that have an 'id' and are not readonly - if (values(getAllProperties(schema)).any(prop => prop.serializedName === 'id' && !prop.details.default.readOnly)) { - - // look thru the operations, and the PUT methods - for (const op of values(model.http.operations).where(o => o.method === HttpMethod.Put)) { - - // see if any of the responses have the same schema as we are looking for - if (values(op.responses).any(rsps => values(rsps).any(resp => !!resp.schema && resp.schema.details.default.uid === schema.details.default.uid))) { - - // tell it not to inline that - schema.details.default.byReference = true; - } - - } - } - } - } - - return model; -} - -// Azure version - -// Additional tweaks the code model to adjust things so that the code will generate better. - -export async function tweakModelAzurePlugin(service: Host) { - return processCodeModel(tweakModel, service, 'tweakcodemodelazure-v2'); -} diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index bb2b2cdd569..837d3f32c83 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -3,16 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Property, SealedChoiceSchema, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema, ConditionalValue } from '@azure-tools/codemodel'; -//import { ModelState } from '@azure-tools/codemodel-v3'; -//import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; import { items, keys, values, Dictionary, length } from '@azure-tools/linq'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { defaultCipherList } from 'constants'; -import { NewString } from '../llcsharp/schema/string'; +import { String } from '../llcsharp/schema/string'; import { JsonType } from '../utils/schema'; export const HeaderProperty = 'HeaderProperty'; @@ -20,7 +18,7 @@ export enum HeaderPropertyType { Header = 'Header', HeaderAndBody = 'HeaderAndBody' } -type State = NewModelState; +type State = ModelState; // For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. @@ -637,7 +635,7 @@ async function tweakModelV2(state: State): Promise { export async function tweakModelPlugin(service: Host) { //const session = await startSession(service, {}, codeModelSchema); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); //const result = tweakModelV2(session); await service.WriteFile('code-model-v4-tweakcodemodel-v2.yaml', serialize(await tweakModelV2(state)), undefined, 'code-model-v4'); //return processCodeModel(tweakModelV2, service, 'tweakcodemodel-v2'); diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts index b92c5643a41..580fc183734 100644 --- a/powershell/plugins/powershell-v2.ts +++ b/powershell/plugins/powershell-v2.ts @@ -7,8 +7,7 @@ import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; import { Host } from '@azure-tools/autorest-extension-base'; import { join } from 'path'; -import { Project, NewProject } from '../internal/project'; -import { State } from '../internal/state'; +import { Project } from '../internal/project'; import { generatePsm1 } from '../generators/psm1'; import { generateCsproj } from '../generators/csproj'; import { generatePsm1Custom } from '../generators/psm1.custom'; @@ -23,7 +22,7 @@ const sourceFileCSharp = 'source-file-csharp'; const resources = `${__dirname}/../../resources`; -async function copyRequiredFiles(project: NewProject) { +async function copyRequiredFiles(project: Project) { const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; // Project assets @@ -49,7 +48,7 @@ export async function powershellV2(service: Host) { const debug = await service.GetValue('debug') || false; try { - const project = await new NewProject(service).init(); + const project = await new Project(service).init(); await project.writeFiles(async (filename, content) => project.state.writeFile(filename, applyOverrides(content, project.overrides), undefined, sourceFileCSharp)); diff --git a/powershell/plugins/powershell.ts b/powershell/plugins/powershell.ts deleted file mode 100644 index feffd74bee1..00000000000 --- a/powershell/plugins/powershell.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel } from '@azure-tools/codemodel-v3'; -import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; -import { Host } from '@azure-tools/autorest-extension-base'; -import { join } from 'path'; -import { Project } from '../internal/project'; -import { State } from '../internal/state'; -import { generatePsm1 } from '../generators/psm1'; -import { generateCsproj } from '../generators/csproj'; -import { generatePsm1Custom } from '../generators/psm1.custom'; -import { generatePsm1Internal } from '../generators/psm1.internal'; -import { generateNuspec } from '../generators/nuspec'; -import { generateGitIgnore } from '../generators/gitignore'; -import { generateGitAttributes } from '../generators/gitattributes'; -import { generateReadme } from '../generators/readme'; -import { generateScriptCmdlets } from '../generators/script-cmdlet'; -import { NewProject } from '../internal/project'; - -const sourceFileCSharp = 'source-file-csharp'; -const resources = `${__dirname}/../../resources`; - - -async function copyRequiredFiles(project: Project | NewProject) { - const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; - - // Project assets - await copyResources(join(resources, 'assets'), async (fname, content) => project.state.writeFile(fname, content, undefined, 'source-file-other'), undefined, transformOutput); - - // Runtime files - await copyResources(join(resources, 'psruntime'), async (fname, content) => project.state.writeFile(join(project.runtimeFolder, fname), content, undefined, sourceFileCSharp), project.overrides, transformOutput); - - // Modules files - await copyBinaryResources(join(resources, 'modules'), async (fname, content) => project.state.writeFile(join(project.dependencyModuleFolder, fname), content, undefined, 'binary-file')); - - if (project.azure) { - // Signing key file - await copyBinaryResources(join(resources, 'signing'), async (fname, content) => project.state.writeFile(join(project.baseFolder, fname), content, undefined, 'binary-file')); - } -} - - -export async function powershell(service: Host) { - const debug = await service.GetValue('debug') || false; - - try { - const project = await new Project(service).init(); - - await project.writeFiles(async (filename, content) => project.state.writeFile(filename, applyOverrides(content, project.overrides), undefined, sourceFileCSharp)); - - await service.ProtectFiles(project.psd1); - await service.ProtectFiles(project.readme); - await service.ProtectFiles(project.customFolder); - await service.ProtectFiles(project.testFolder); - await service.ProtectFiles(project.docsFolder); - await service.ProtectFiles(project.examplesFolder); - await service.ProtectFiles(project.resourcesFolder); - - // wait for all the generation to be done - await copyRequiredFiles(project); - await generateCsproj(project); - await generatePsm1(project); - await generatePsm1Custom(project); - await generatePsm1Internal(project); - await generateNuspec(project); - await generateGitIgnore(project); - await generateGitAttributes(project); - await generateReadme(project); - - await generateScriptCmdlets(project); - - } catch (E) { - if (debug) { - console.error(`${__filename} - FAILURE ${JSON.stringify(E)} ${E.stack}`); - } - throw E; - } -} - diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index 39f28aee11b..fdc15b97a90 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -11,10 +11,10 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import * as linq from '@azure-tools/linq'; import { singularize } from '../internal/name-inferrer'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames } from '../utils/resolve-conflicts'; -type State = NewModelState; +type State = ModelState; function getCmdletName(verb: string, subjectPrefix: string, subject: string): string { return `${verb}-${subjectPrefix}${subject}`; @@ -208,6 +208,6 @@ export async function namerV2(service: Host) { //return processCodeModel(tweakModel, service, 'psnamer'); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-psnamer-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } \ No newline at end of file diff --git a/powershell/plugins/ps-namer.ts b/powershell/plugins/ps-namer.ts deleted file mode 100644 index b01a9fce18d..00000000000 --- a/powershell/plugins/ps-namer.ts +++ /dev/null @@ -1,201 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Host, Channel } from '@azure-tools/autorest-extension-base'; -import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames, ModelState, ParameterLocation, isMediaTypeMultipartFormData, VirtualParameter } from '@azure-tools/codemodel-v3'; -import { deconstruct, removeProhibitedPrefix, removeSequentialDuplicates, pascalCase } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import * as linq from '@azure-tools/linq'; -import { singularize } from '../internal/name-inferrer'; - -type State = ModelState; - -function getCmdletName(verb: string, subjectPrefix: string, subject: string): string { - return `${verb}-${subjectPrefix}${subject}`; -} - -export function getDeduplicatedNoun(subjectPrefix: string, subject: string): { subjectPrefix: string; subject: string } { - // dedup parts - const dedupedPrefix = [...removeSequentialDuplicates(deconstruct(subjectPrefix))]; - const dedupedSubject = [...removeSequentialDuplicates(deconstruct(subject))]; - - // dedup the noun - const dedupedMerge = [...removeSequentialDuplicates([...dedupedPrefix, ...dedupedSubject])]; - - // figure out what belongs to the subject - const reversedFinalSubject = new Array(); - for (let mCount = length(dedupedMerge) - 1, sCount = length(dedupedSubject) - 1; sCount >= 0 && mCount >= 0; mCount--, sCount--) { - if (dedupedMerge[mCount] !== dedupedSubject[sCount]) { - break; - } - - reversedFinalSubject.push(dedupedMerge.pop()); - } - - // what's left belongs to the prefix - const finalPrefix = new Array(); - for (const each of dedupedMerge) { - finalPrefix.push(each); - } - - return { subjectPrefix: pascalCase(finalPrefix), subject: pascalCase(reversedFinalSubject.reverse()) }; -} - -async function tweakModel(state: State): Promise { - // get the value - const isAzure = await state.getValue('azure', false); - // without setting snitize-names, isAzure is applied - const shouldSanitize = await state.getValue('sanitize-names', isAzure); - - // make sure recursively that every details field has csharp - for (const { index, instance } of linq.visitor(state.model)) { - if (index === 'details' && instance.default && !instance.csharp) { - instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); - } - } - // dolauli sanitize name - if (shouldSanitize) { - for (const operation of values(state.model.commands.operations)) { - // clean the noun (i.e. subjectPrefix + subject) - const prevSubjectPrefix = operation.details.csharp.subjectPrefix; - const prevSubject = operation.details.csharp.subject; - const dedupedNounParts = getDeduplicatedNoun(operation.details.csharp.subjectPrefix, operation.details.csharp.subject); - if (prevSubjectPrefix !== dedupedNounParts.subjectPrefix || prevSubject !== dedupedNounParts.subject) { - const verb = operation.details.csharp.verb; - const variantName = operation.details.csharp.name; - const prevCmdletName = getCmdletName(verb, prevSubjectPrefix, prevSubject); - operation.details.csharp.subjectPrefix = dedupedNounParts.subjectPrefix; - operation.details.csharp.subject = dedupedNounParts.subject; - const newCmdletName = getCmdletName(verb, operation.details.csharp.subjectPrefix, operation.details.csharp.subject); - state.message( - { - Channel: Channel.Debug, - Text: `Sanitized cmdlet-name -> Changed cmdlet-name from ${prevCmdletName} to ${newCmdletName}: {subjectPrefix: ${operation.details.csharp.subjectPrefix}, subject: ${operation.details.csharp.subject}${variantName ? `, variant: ${variantName}}` : '}'}` - } - ); - } - - const virtualParameters = [...allVirtualParameters(operation.details.csharp.virtualParameters)]; - for (const parameter of virtualParameters) { - let prevName = parameter.name; - const otherParametersNames = values(virtualParameters) - .select(each => each.name) - .where(name => name !== parameter.name) - .toArray(); - - // first try to singularize the parameter - const singularName = singularize(parameter.name); - if (prevName != singularName) { - parameter.name = singularName; - state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to singular ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); - } - - // save the name again to compare in case it was modified - prevName = parameter.name; - - // now remove the subject from the beginning of the parameter - // to reduce naming redundancy, but just for path parameters - // e.g. get-vm -vmname ---> get-vm -name - if ((parameter.origin).in === ParameterLocation.Path) { - const sanitizedName = removeProhibitedPrefix( - parameter.name, - operation.details.csharp.subject, - otherParametersNames - ); - - if (prevName !== sanitizedName) { - if (parameter.alias === undefined) { - parameter.alias = []; - } - - // saved the prev name as alias - parameter.alias.push(parameter.name); - - // change name - parameter.name = sanitizedName; - state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); - state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); - } - } - } - } - - for (const schema of values(state.model.schemas)) { - const virtualProperties = [...allVirtualProperties(schema.details.csharp.virtualProperties)]; - - for (const property of virtualProperties) { - let prevName = property.name; - const otherPropertiesNames = values(virtualProperties) - .select(each => each.name) - .where(name => name !== property.name) - .toArray(); - - // first try to singularize the property - const singularName = singularize(property.name); - if (prevName != singularName) { - property.name = singularName; - state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to singular ${property.name} from model ${schema.details.csharp.name}` }); - } - - // save the name again to compare in case it was modified - prevName = property.name; - - // now remove the model=name from the beginning of the property-name - // to reduce naming redundancy - const sanitizedName = removeProhibitedPrefix( - property.name, - schema.details.csharp.name, - otherPropertiesNames - ); - - if (prevName !== sanitizedName) { - property.alias = property.alias || []; - - // saved the prev name as alias - property.alias.push(property.name); - - // change name - property.name = sanitizedName; - state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to ${property.name} from model ${schema.details.csharp.name}` }); - state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); - - // update shared properties too - if (property.sharedWith) { - for (const sharedProperty of property.sharedWith) { - if (sharedProperty.name !== sanitizedName) { - state.message({ Channel: Channel.Debug, Text: `Changing shared property ${sharedProperty.name} to ${sanitizedName}` }); - sharedProperty.alias = sharedProperty.alias || []; - sharedProperty.alias.push(sharedProperty.name); - sharedProperty.name = sanitizedName; - } - } - } - } - } - } - } - - // do collision detection work. - for (const command of values(state.model.commands.operations)) { - const vp = command.details.csharp.virtualParameters; - if (vp) { - resolveParameterNames([], vp); - } - } - - for (const schema of values(state.model.schemas)) { - const vp = schema.details.csharp.virtualProperties; - if (vp) { - resolvePropertyNames([schema.details.csharp.name], vp); - } - } - return state.model; -} - - -export async function namer(service: Host) { - // dolauli add csharp for cmdlets in the command->operation node - return processCodeModel(tweakModel, service, 'psnamer'); -} \ No newline at end of file diff --git a/powershell/test/noun-cleaning.ts b/powershell/test/noun-cleaning.ts index 0a6374f5aab..11e6cd28ffb 100644 --- a/powershell/test/noun-cleaning.ts +++ b/powershell/test/noun-cleaning.ts @@ -5,7 +5,7 @@ import { suite, test } from 'mocha-typescript'; import * as assert from 'assert'; -import { getDeduplicatedNoun } from '../plugins/ps-namer'; +import { getDeduplicatedNoun } from '../plugins/ps-namer-v2'; @suite class TestNounCleaning { diff --git a/powershell/test/operationId-inferring.ts b/powershell/test/operationId-inferring.ts index 981d69c548b..27d35348c08 100644 --- a/powershell/test/operationId-inferring.ts +++ b/powershell/test/operationId-inferring.ts @@ -6,8 +6,7 @@ import * as assert from 'assert'; import { suite, test } from 'mocha-typescript'; -import * as pp from '../plugins/create-commands'; -import { ModelState, JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, } from '@azure-tools/codemodel-v3'; +import * as pp from '../plugins/create-commands-v2'; import { Channel, JsonPath, Mapping, RawSourceMap, Message } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; require('source-map-support').install(); diff --git a/powershell/test/test-service-name.ts b/powershell/test/test-service-name.ts index 02ca436459f..5e780faae76 100644 --- a/powershell/test/test-service-name.ts +++ b/powershell/test/test-service-name.ts @@ -7,7 +7,7 @@ import { suite, test } from 'mocha-typescript'; import * as assert from 'assert'; import * as aio from '@azure-tools/async-io'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { titleToAzureServiceName } from '../plugins/create-commands'; +import { titleToAzureServiceName } from '../plugins/create-commands-v2'; @suite class TestServiceName { diff --git a/powershell/utils/PwshModel.ts b/powershell/utils/PwshModel.ts index 2f200bc7df6..acacaaa7d0f 100644 --- a/powershell/utils/PwshModel.ts +++ b/powershell/utils/PwshModel.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -//import { CommandComponents } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; import { DeepPartial } from '@azure-tools/codegen'; import { CommandComponents } from '../utils/command-operation'; diff --git a/powershell/utils/model-state.ts b/powershell/utils/model-state.ts index c51ff1e84e6..d809d798f1b 100644 --- a/powershell/utils/model-state.ts +++ b/powershell/utils/model-state.ts @@ -7,7 +7,7 @@ import { Channel, Host, JsonPath, Mapping, RawSourceMap, Message } from '@azure- import { safeEval, deserialize, Initializer, DeepPartial } from '@azure-tools/codegen'; import { Dictionary } from '@azure-tools/linq'; -export class NewModelState> extends Initializer { +export class ModelState> extends Initializer { public model!: T; protected documentName!: string; protected currentPath: JsonPath = new Array(); @@ -15,13 +15,13 @@ export class NewModelState> extends Initializer { private _debug = false; private _verbose = false; - public constructor(protected service: Host, objectInitializer?: DeepPartial>) { + public constructor(protected service: Host, objectInitializer?: DeepPartial>) { super(); this.apply(objectInitializer); } async init(project?: any) { - const m = await NewModelState.getModel(this.service); + const m = await ModelState.getModel(this.service); this.model = m.model; this.documentName = m.filename; this.initContext(project); diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index b5ccf61d851..77a0ac62ece 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -9,9 +9,9 @@ import { DeepPartial, } from '@azure-tools/codegen'; import { Dictionary, values } from '@azure-tools/linq'; import { uid } from './uid'; import { Schema, ObjectSchema, Property, SchemaType, isObjectSchema } from '@azure-tools/codemodel'; -import { NewEnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; -import { NewModelClass } from '../llcsharp/model/model-class'; -import { NewModelInterface } from '../llcsharp/model/interface'; +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; @@ -97,10 +97,10 @@ export interface SchemaDetails extends ImplementationDetails { suppressFormat?: boolean; - typeDeclaration?: NewEnhancedTypeDeclaration; - classImplementation?: NewModelClass; - interfaceImplementation?: NewModelInterface; - internalInterfaceImplementation?: NewModelInterface; + typeDeclaration?: EnhancedTypeDeclaration; + classImplementation?: ModelClass; + interfaceImplementation?: ModelInterface; + internalInterfaceImplementation?: ModelInterface; interfaceName?: string; internalInterfaceName?: string; fullInternalInterfaceName?: string; From c9b0f55d98d3f2910823f90b7092196e11205016 Mon Sep 17 00:00:00 2001 From: derek Date: Fri, 16 Oct 2020 13:47:10 +0800 Subject: [PATCH 60/61] upgrade version to 3.0.0 --- powershell/package.json | 4 +- powershell/plugins/cs-namer.ts | 242 --------------------------------- 2 files changed, 2 insertions(+), 244 deletions(-) delete mode 100644 powershell/plugins/cs-namer.ts diff --git a/powershell/package.json b/powershell/package.json index 1579cc13cf0..cfaae555cd8 100644 --- a/powershell/package.json +++ b/powershell/package.json @@ -1,6 +1,6 @@ { "name": "@autorest/powershell", - "version": "2.1.0", + "version": "3.0.0", "description": "AutoRest PowerShell Cmdlet Generator", "main": "dist/exports.js", "typings": "dist/exports.d.ts", @@ -66,4 +66,4 @@ "source-map-support": "0.5.13", "xmlbuilder": "10.1.1" } -} +} \ No newline at end of file diff --git a/powershell/plugins/cs-namer.ts b/powershell/plugins/cs-namer.ts deleted file mode 100644 index 3c59d06d59e..00000000000 --- a/powershell/plugins/cs-namer.ts +++ /dev/null @@ -1,242 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; - -import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { System } from '@azure-tools/codegen-csharp'; - -import { Host } from '@azure-tools/autorest-extension-base'; -import { Schema, SchemaDetails } from '../llcsharp/code-model'; -import { SchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; - -type State = ModelState; - -function setPropertyNames(schema: Schema) { - // name each property in this schema - for (const propertySchema of values(schema.properties)) { - const propertyDetails = propertySchema.details.default; - - const className = schema.details.csharp.name; - - let pname = getPascalIdentifier(propertyDetails.name); - if (pname === className) { - pname = `${pname}Property`; - } - - if (pname === 'default') { - pname = '@default'; - } - - propertySchema.details.csharp = { - ...propertyDetails, - name: pname // and so are the propertyNmaes - }; - - if (propertyDetails.isNamedStream) { - propertySchema.details.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); - } - } - -} - - -function setSchemaNames(schemas: Dictionary, azure: boolean, serviceNamespace: string) { - const baseNamespace = new Set(); - const subNamespace = new Map>(); - - // in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion. - // otherwise, we just want to differientiate with a simple incremental numbering scheme. - - for (const schema of values(schemas)) { - let thisNamespace = baseNamespace; - let thisApiversion = ''; - - // create the namespace if required - if (azure) { - const metadata = schema.extensions && schema.extensions['x-ms-metadata']; - if (metadata) { - const apiVersions = | undefined>metadata.apiVersions; - if (apiVersions && length(apiVersions) > 0) { - thisApiversion = minimum(apiVersions); - thisNamespace = subNamespace.get(thisApiversion) || new Set(); - subNamespace.set(thisApiversion, thisNamespace); - } - } - } - - // for each schema, we're going to set the name - // to the suggested name, unless we have collisions - // at which point, we're going to add a number (for now?) - const details = schema.details.default; - let schemaName = getPascalIdentifier(details.name); - const apiName = (!thisApiversion) ? '' : getPascalIdentifier(`Api ${thisApiversion}`); - const ns = (!thisApiversion) ? [] : ['.', apiName]; - - - let n = 1; - while (thisNamespace.has(schemaName)) { - schemaName = getPascalIdentifier(`${details.name}_${n++}`); - } - thisNamespace.add(schemaName); - - // object types. - if (schema.type === JsonType.Object) { - schema.details.csharp = { - ...details, - apiversion: thisApiversion, - apiname: apiName, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), // objects have an interfaceName - internalInterfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal'])), // objects have an ineternal interfaceName for setting private members. - fullInternalInterfaceName: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal']))}`, - name: getPascalIdentifier(schemaName), - namespace: pascalCase([serviceNamespace, '.', 'Models', ...ns]), // objects have a namespace - fullname: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${getPascalIdentifier(schemaName)}`, - }; - } else if (schema.type === JsonType.String && schema.details.default.enum) { - // oh, it's an enum type - schema.details.csharp = { - ...details, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), - name: getPascalIdentifier(schema.details.default.enum.name), - namespace: pascalCase([serviceNamespace, '.', 'Support']), - fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schema.details.default.enum.name)}`, - enum: { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name), - values: schema.details.default.enum.values.map(each => { - return { - ...each, - name: getPascalIdentifier(each.name), - description: each.description - }; - }) - } - }; - } else { - schema.details.csharp = { - ...details, - interfaceName: '', - internalInterfaceName: '', - name: schemaName, - namespace: '', - fullname: '' - }; - } - - // name each property in this schema - setPropertyNames(schema); - - // fix enum names - if (schema.details.default.enum) { - schema.details.csharp.enum = { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name) - }; - - // and the value names themselves - for (const value of values(schema.details.csharp.enum.values)) { - value.name = getPascalIdentifier(value.name); - } - } - } - -} - -async function setOperationNames(state: State, resolver: SchemaDefinitionResolver) { - // keep a list of operation names that we've assigned. - const operationNames = new Set(); - - for (const operation of values(state.model.http.operations)) { - const details = operation.details.default; - - // come up with a name - const oName = getPascalIdentifier(details.name); - let i = 1; - let operationName = oName; - while (operationNames.has(operationName)) { - // if we have used that name, try again. - operationName = `${oName}${i++}`; - } - operationNames.add(operationName); - - operation.details.csharp = { - ...details, // inherit - name: operationName, - }; - - // parameters are camelCased. - for (const parameter of values(operation.parameters)) { - const parameterDetails = parameter.details.default; - - let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name))); - - if (propName === 'default') { - propName = '@default'; - } - - parameter.details.csharp = { - ...parameterDetails, - name: propName - }; - } - - for (const responses of values(operation.responses)) { - // per responseCode - for (const response of values(responses)) { - const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state.path('schemas', response.schema.details.default.name)) : undefined; - const headerTypeDefinition = response.headerSchema ? resolver.resolveTypeDeclaration(response.headerSchema, true, state.path('schemas', response.headerSchema.details.default.name)) : undefined; - let code = (System.Net.HttpStatusCode[response.responseCode] ? System.Net.HttpStatusCode[response.responseCode].value : response.responseCode).replace('global::System.Net.HttpStatusCode', ''); - let rawValue = code.replace(/\./, ''); - if (response.responseCode === 'default' || rawValue === 'default' || '') { - rawValue = 'any response code not handled elsewhere'; - code = 'default'; - } - response.details.csharp = { - ...response.details.default, - responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '', - headerType: headerTypeDefinition ? headerTypeDefinition.declaration : '', - name: (length(responses) <= 1) ? - camelCase(fixLeadingNumber(deconstruct(`on ${code}`))) : // the common type (or the only one.) - camelCase(fixLeadingNumber(deconstruct(`on ${code} ${response.mimeTypes[0]}`))), - description: (length(responses) <= 1) ? - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}).` : - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}) with a Content-Type matching ${response.mimeTypes.join(',')}.` - - }; - } - } - } -} - -async function nameStuffRight(state: State): Promise { - const resolver = new SchemaDefinitionResolver(); - const model = state.model; - - // set the namespace for the service - const serviceNamespace = await state.getValue('namespace', 'Sample.API'); - const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false); - const clientName = getPascalIdentifier(model.details.default.name); - - // set c# client details (name) - model.details.csharp = { - ...model.details.default, // copy everything by default - name: clientName, - namespace: serviceNamespace, - fullname: `${serviceNamespace}.${clientName}` - }; - - setSchemaNames(>model.schemas, azure, serviceNamespace); - await setOperationNames(state, resolver); - - return model; -} - - -export async function csnamer(service: Host) { - return processCodeModel(nameStuffRight, service, 'csnamer'); -} - From aa638531278123bc13c4444eb0b18f0b93407247 Mon Sep 17 00:00:00 2001 From: Xiaogang Date: Fri, 16 Oct 2020 15:05:57 +0800 Subject: [PATCH 61/61] Remove some useless comments --- powershell/main.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/powershell/main.ts b/powershell/main.ts index 21590a6993a..9eebe7b6292 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -4,13 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { AutoRestExtension, } from '@azure-tools/autorest-extension-base'; -//import { applyModifiers } from './plugins/modifiers'; -//import { createCommands } from './plugins/create-commands'; -//import { namer } from './plugins/ps-namer'; -//import { powershell } from './plugins/powershell'; -//import { addCompleter } from './plugins/add-azure-completers'; -//import { csnamer } from './plugins/cs-namer'; -//import { llcsharp } from './plugins/llcsharp'; import { createInlinedPropertiesPlugin } from './plugins/plugin-create-inline-properties'; import { tweakModelPlugin } from './plugins/plugin-tweak-model'; import { tweakModelAzurePluginV2 } from './plugins/plugin-tweak-model-azure-v2';

`tYFqJHow)GoDN^TB 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 delta 66896 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�S|4v>a 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 None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + DefaultProfile @@ -547,6 +571,30 @@ None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + DefaultProfile @@ -768,6 +816,30 @@ None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + BatchEndpointResourceId @@ -1062,6 +1134,8 @@ AzureOperationalInsightsEndpoint : AzureAnalysisServicesEndpointSuffix : AzureAttestationServiceEndpointSuffix : AzureAttestationServiceEndpointResourceId : +AzureSynapseAnalyticsEndpointSuffix : +AzureSynapseAnalyticsEndpointResourceId : VersionProfiles : {} ExtendedProperties : {} BatchEndpointResourceId : @@ -1283,7 +1357,7 @@ In this example we are creating a new Azure environment with sample endpoints us - --------------------- Clear global context --------------------- + --------------- Example 1: Clear global context --------------- PS C:\> Clear-AzContext -Scope CurrentUser Remove all account, subscription, and credential information for any powershell session. @@ -1521,7 +1595,7 @@ In this example we are creating a new Azure environment with sample endpoints us - -------------------------- Example 1 -------------------------- + -------------------------- Example 2 -------------------------- PS C:\> Clear-AzDefault -ResourceGroup This command removes the default resource group set by the user in the current context. @@ -1543,11 +1617,11 @@ In this example we are creating a new Azure environment with sample endpoints us Connect AzAccount - Connect to Azure with an authenticated account for use with Azure Resource Manager cmdlet requests. + Connect to Azure with an authenticated account for use with cmdlets from the Az PowerShell modules. - The Connect-AzAccount cmdlet connects to Azure with an authenticated account for use with Azure Resource Manager cmdlet requests. You can use this authenticated account only with Azure Resource Manager cmdlets. To add an authenticated account for use with Service Management cmdlets, use the Add-AzAccount or the Import-AzPublishSettingsFile cmdlet. If no context is found for the current user, this command will populate the user's context list with a context for each of their (first 25) subscriptions. The list of contexts created for the user can be found by running "Get-AzContext -ListAvailable". To skip this context population, you can run this command with the "-SkipContextPopulation" switch parameter. After executing this cmdlet, you can disconnect from an Azure account using Disconnect-AzAccount. + The `Connect-AzAccount` cmdlet connects to Azure with an authenticated account for use with cmdlets from the Az PowerShell modules. You can use this authenticated account only with Azure Resource Manager requests. To add an authenticated account for use with Service Management, use the `Add-AzureAccount` cmdlet from the Azure PowerShell module. If no context is found for the current user, the user's context list is populated with a context for each of their first 25 subscriptions. The list of contexts created for the user can be found by running `Get-AzContext -ListAvailable`. To skip this context population, specify the SkipContextPopulation switch parameter. After executing this cmdlet, you can disconnect from an Azure account using `Disconnect-AzAccount`. @@ -1556,6 +1630,7 @@ In this example we are creating a new Azure environment with sample endpoints us AccessToken Specifies an access token. + > [!CAUTION] > Access tokens are a type of credential. You should take the appropriate security precautions to > keep them confidential. Access tokens also timeout and may prevent long running tasks from > completing. System.String @@ -1567,7 +1642,7 @@ In this example we are creating a new Azure environment with sample endpoints us AccountId - Account Id for access token in AccessToken parameter set. Account Id for managed service in ManagedService parameter set. Can be a managed service resource Id, or the associated client id. To use the SystemAssigned identity, leave this field blank. + Account ID for access token in AccessToken parameter set. Account ID for managed service in ManagedService parameter set. Can be a managed service resource ID, or the associated client ID. To use the system assigned identity, leave this field blank. System.String @@ -1579,7 +1654,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -1591,7 +1666,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -1603,7 +1678,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -1615,7 +1690,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -1626,7 +1701,7 @@ In this example we are creating a new Azure environment with sample endpoints us GraphAccessToken - AccessToken for Graph Service + AccessToken for Graph Service. System.String @@ -1638,7 +1713,7 @@ In this example we are creating a new Azure environment with sample endpoints us KeyVaultAccessToken - AccessToken for KeyVault Service + AccessToken for KeyVault Service. System.String @@ -1677,7 +1752,7 @@ In this example we are creating a new Azure environment with sample endpoints us SkipValidation - Skip validation for access token + Skip validation for access token. System.Management.Automation.SwitchParameter @@ -1688,7 +1763,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -1700,7 +1775,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -1737,7 +1813,7 @@ In this example we are creating a new Azure environment with sample endpoints us AccountId - Account Id for access token in AccessToken parameter set. Account Id for managed service in ManagedService parameter set. Can be a managed service resource Id, or the associated client id. To use the SystemAssigned identity, leave this field blank. + Account ID for access token in AccessToken parameter set. Account ID for managed service in ManagedService parameter set. Can be a managed service resource ID, or the associated client ID. To use the system assigned identity, leave this field blank. System.String @@ -1749,7 +1825,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -1761,7 +1837,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -1773,7 +1849,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -1785,7 +1861,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -1796,7 +1872,7 @@ In this example we are creating a new Azure environment with sample endpoints us Identity - Login using managed service identity in the current environment. + Login using a Managed Service Identity. System.Management.Automation.SwitchParameter @@ -1807,7 +1883,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServiceHostName - Host name for managed service login + Host name for the managed service. System.String @@ -1819,7 +1895,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServicePort - Port number for managed service login + Port number for the managed service. System.Int32 @@ -1831,7 +1907,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServiceSecret - Secret, used for some kinds of managed service login. + Token for the managed service login. System.Security.SecureString @@ -1870,7 +1946,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -1882,7 +1958,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -1919,7 +1996,7 @@ In this example we are creating a new Azure environment with sample endpoints us ApplicationId - SPN + Application ID of the service principal. System.String @@ -1931,7 +2008,7 @@ In this example we are creating a new Azure environment with sample endpoints us CertificateThumbprint - Certificate Hash (Thumbprint) + Certificate Hash or Thumbprint. System.String @@ -1943,7 +2020,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -1955,7 +2032,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -1967,7 +2044,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -1979,7 +2056,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -2028,7 +2105,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -2040,7 +2117,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -2077,7 +2155,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -2089,7 +2167,7 @@ In this example we are creating a new Azure environment with sample endpoints us Credential - Specifies a PSCredential object. For more information about the PSCredential object, type Get-Help Get-Credential. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. + Specifies a PSCredential object. For more information about the PSCredential object, type `Get-Help Get-Credential`. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. System.Management.Automation.PSCredential @@ -2101,7 +2179,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -2113,7 +2191,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -2125,7 +2203,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -2174,7 +2252,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -2186,7 +2264,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -2223,7 +2302,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -2235,7 +2314,7 @@ In this example we are creating a new Azure environment with sample endpoints us Credential - Specifies a PSCredential object. For more information about the PSCredential object, type Get-Help Get-Credential. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. + Specifies a PSCredential object. For more information about the PSCredential object, type `Get-Help Get-Credential`. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. System.Management.Automation.PSCredential @@ -2247,7 +2326,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -2259,7 +2338,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -2271,7 +2350,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -2309,7 +2388,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -2321,7 +2400,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -2358,7 +2438,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -2370,7 +2450,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -2382,7 +2462,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -2394,7 +2474,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -2432,7 +2512,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -2444,7 +2524,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -2456,7 +2537,7 @@ In this example we are creating a new Azure environment with sample endpoints us UseDeviceAuthentication - Use device code authentication instead of a browser control + Use device code authentication instead of a browser control. This is the default authentication type for PowerShell version 6 and higher. System.Management.Automation.SwitchParameter @@ -2493,6 +2574,7 @@ In this example we are creating a new Azure environment with sample endpoints us AccessToken Specifies an access token. + > [!CAUTION] > Access tokens are a type of credential. You should take the appropriate security precautions to > keep them confidential. Access tokens also timeout and may prevent long running tasks from > completing. System.String @@ -2504,7 +2586,7 @@ In this example we are creating a new Azure environment with sample endpoints us AccountId - Account Id for access token in AccessToken parameter set. Account Id for managed service in ManagedService parameter set. Can be a managed service resource Id, or the associated client id. To use the SystemAssigned identity, leave this field blank. + Account ID for access token in AccessToken parameter set. Account ID for managed service in ManagedService parameter set. Can be a managed service resource ID, or the associated client ID. To use the system assigned identity, leave this field blank. System.String @@ -2516,7 +2598,7 @@ In this example we are creating a new Azure environment with sample endpoints us ApplicationId - SPN + Application ID of the service principal. System.String @@ -2528,7 +2610,7 @@ In this example we are creating a new Azure environment with sample endpoints us CertificateThumbprint - Certificate Hash (Thumbprint) + Certificate Hash or Thumbprint. System.String @@ -2540,7 +2622,7 @@ In this example we are creating a new Azure environment with sample endpoints us ContextName - Name of the default context from this login. You will be able to select this context by this name after login. + Name of the default Azure context for this login. For more information about Azure contexts, see Azure PowerShell context objects (/powershell/azure/context-persistence). System.String @@ -2552,7 +2634,7 @@ In this example we are creating a new Azure environment with sample endpoints us Credential - Specifies a PSCredential object. For more information about the PSCredential object, type Get-Help Get-Credential. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. + Specifies a PSCredential object. For more information about the PSCredential object, type `Get-Help Get-Credential`. The PSCredential object provides the user ID and password for organizational ID credentials, or the application ID and secret for service principal credentials. System.Management.Automation.PSCredential @@ -2564,7 +2646,7 @@ In this example we are creating a new Azure environment with sample endpoints us DefaultProfile - The credentials, account, tenant, and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -2576,7 +2658,7 @@ In this example we are creating a new Azure environment with sample endpoints us Environment - Environment containing the account to log into + Environment containing the Azure account. System.String @@ -2588,7 +2670,7 @@ In this example we are creating a new Azure environment with sample endpoints us Force - Overwrite the existing context with the same name, if any. + Overwrite the existing context with the same name without prompting. System.Management.Automation.SwitchParameter @@ -2600,7 +2682,7 @@ In this example we are creating a new Azure environment with sample endpoints us GraphAccessToken - AccessToken for Graph Service + AccessToken for Graph Service. System.String @@ -2612,7 +2694,7 @@ In this example we are creating a new Azure environment with sample endpoints us Identity - Login using managed service identity in the current environment. + Login using a Managed Service Identity. System.Management.Automation.SwitchParameter @@ -2624,7 +2706,7 @@ In this example we are creating a new Azure environment with sample endpoints us KeyVaultAccessToken - AccessToken for KeyVault Service + AccessToken for KeyVault Service. System.String @@ -2636,7 +2718,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServiceHostName - Host name for managed service login + Host name for the managed service. System.String @@ -2648,7 +2730,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServicePort - Port number for managed service login + Port number for the managed service. System.Int32 @@ -2660,7 +2742,7 @@ In this example we are creating a new Azure environment with sample endpoints us ManagedServiceSecret - Secret, used for some kinds of managed service login. + Token for the managed service login. System.Security.SecureString @@ -2708,7 +2790,7 @@ In this example we are creating a new Azure environment with sample endpoints us SkipValidation - Skip validation for access token + Skip validation for access token. System.Management.Automation.SwitchParameter @@ -2720,7 +2802,7 @@ In this example we are creating a new Azure environment with sample endpoints us Subscription - Subscription Name or ID + Subscription Name or ID. System.String @@ -2732,7 +2814,8 @@ In this example we are creating a new Azure environment with sample endpoints us Tenant - Optional tenant name or ID + Optional tenant name or ID. + > [!NOTE] > Due to limitations of the current API, you must use a tenant ID instead of a tenant name when > connecting with a business-to-business (B2B) account. System.String @@ -2744,7 +2827,7 @@ In this example we are creating a new Azure environment with sample endpoints us UseDeviceAuthentication - Use device code authentication instead of a browser control + Use device code authentication instead of a browser control. This is the default authentication type for PowerShell version 6 and higher. System.Management.Automation.SwitchParameter @@ -2805,111 +2888,93 @@ In this example we are creating a new Azure environment with sample endpoints us - Example 1: Use an interactive login to connect to an Azure account - PS C:\> Connect-AzAccount + ------------ Example 1: Connect to an Azure account ------------ + Connect-AzAccount Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - This command connects to an Azure account. To run Azure Resource Manager cmdlets with this account, you must provide Microsoft account or organizational ID credentials at the prompt. If multi-factor authentication is enabled for your credentials, you must log in using the interactive option or use service principal authentication. + - Example 2: (Windows PowerShell 5.1 only) Connect to an Azure account using organizational ID credentials - PS C:\> $Credential = Get-Credential -PS C:\> Connect-AzAccount -Credential $Credential + Example 2: (Windows PowerShell 5.1 only) Connect to Azure using organizational ID credentials + $Credential = Get-Credential +Connect-AzAccount -Credential $Credential Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - This scenario works only in Windows PowerShell 5.1. The first command will prompt for user credentials (username and password), and then stores them in the $Credential variable. The second command connects to an Azure account using the credentials stored in $Credential. This account authenticates with Azure Resource Manager using organizational ID credentials. You cannot use multi-factor authentication or Microsoft account credentials to run Azure Resource Manager cmdlets with this account. + - --- Example 3: Connect to an Azure service principal account --- - PS C:\> $Credential = Get-Credential -PS C:\> Connect-AzAccount -Credential $Credential -Tenant "xxxx-xxxx-xxxx-xxxx" -ServicePrincipal + Example 3: Connect to Azure using a service principal account + $Credential = Get-Credential +Connect-AzAccount -Credential $Credential -Tenant 'xxxx-xxxx-xxxx-xxxx' -ServicePrincipal Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- xxxx-xxxx-xxxx-xxxx Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - The first command gets the service principal credentials (application id and service principal secret), and then stores them in the $Credential variable. The second command connect to Azure using the service principal credentials stored in $Credential for the specified Tenant. The ServicePrincipal switch parameter indicates that the account authenticates as a service principal. + - Example 4: Use an interactive login to connect to an account for a specific tenant and subscription - PS C:\> Connect-AzAccount -Tenant "xxxx-xxxx-xxxx-xxxx" -SubscriptionId "yyyy-yyyy-yyyy-yyyy" + Example 4: Use an interactive login to connect to a specific tenant and subscription + Connect-AzAccount -Tenant 'xxxx-xxxx-xxxx-xxxx' -SubscriptionId 'yyyy-yyyy-yyyy-yyyy' Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - This command connects to an Azure account and configured AzureRM PowerShell to run cmdlets for the specified tenant and subscription by default. + - Example 5: Add an Account Using Managed Service Identity Login - PS C:\> Connect-AzAccount -Identity + ----- Example 5: Connect using a Managed Service Identity ----- + Connect-AzAccount -Identity Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- MSI@50342 Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - This command connects using the managed service identity of the host environment (for example, if executed on a VirtualMachine with an assigned Managed Service Identity, this will allow the code to login using that assigned identity) - - - - - - Example 6: Add an Account Using Managed Service Identity Login and ClientId - PS C:\> $identity = Get-AzUserAssignedIdentity -ResourceGroupName "myResourceGroup" -Name "myUserAssignedIdentity" -PS C:\> Get-AzVM -ResourceGroupName contoso -Name testvm | Update-AzVM -IdentityType UserAssigned -IdentityId $identity.Id -PS C:\> Connect-AzAccount -Identity -AccountId $identity.ClientId # Run on the "testvm" virtual machine - -Account SubscriptionName TenantId Environment -------- ---------------- -------- ----------- -yyyy-yyyy-yyyy-yyyy Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - - This command connects using the managed service identity of "myUserAssignedIdentity" by adding the User Assigned Identity to the Virtual Machine, then connecting using the ClientId of the User Assigned Identity. More information about configuring Managed Identities can be found here: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-powershell-windows-vm. + - Example 7: Add an Account Using Managed Service Identity Login and ClientId - PS C:\> $identity = Get-AzUserAssignedIdentity -ResourceGroupName "myResourceGroup" -Name "myUserAssignedIdentity" -PS C:\> Get-AzVM -ResourceGroupName contoso -Name testvm | Update-AzVM -IdentityType UserAssigned -IdentityId $identity.Id -PS C:\> Connect-AzAccount -Identity -AccountId $identity.Id # Run on the "testvm" virtual machine + Example 6: Connect using Managed Service Identity login and ClientId + $identity = Get-AzUserAssignedIdentity -ResourceGroupName 'myResourceGroup' -Name 'myUserAssignedIdentity' +Get-AzVM -ResourceGroupName contoso -Name testvm | Update-AzVM -IdentityType UserAssigned -IdentityId $identity.Id +Connect-AzAccount -Identity -AccountId $identity.ClientId # Run on the virtual machine Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- yyyy-yyyy-yyyy-yyyy Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - This command connects using the managed service identity of "myUserAssignedIdentity" by adding the User Assigned Identity to the Virtual Machine, then connecting using the Id of the User Assigned Identity. More information about configuring Managed Identities can be found here: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-powershell-windows-vm. + - --------- Example 8: Add an account using certificates --------- - # For more information on creating a self-signed certificate -# and giving it proper permissions, please see the following: -# https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-authenticate-service-principal-powershell -PS C:\> $Thumbprint = "0SZTNJ34TCCMUJ5MJZGR8XQD3S0RVHJBA33Z8ZXV" -PS C:\> $TenantId = "4cd76576-b611-43d0-8f2b-adcb139531bf" -PS C:\> $ApplicationId = "3794a65a-e4e4-493d-ac1d-f04308d712dd" -PS C:\> Connect-AzAccount -CertificateThumbprint $Thumbprint -ApplicationId $ApplicationId -Tenant $TenantId -ServicePrincipal + ------------ Example 7: Connect using certificates ------------ + $Thumbprint = '0SZTNJ34TCCMUJ5MJZGR8XQD3S0RVHJBA33Z8ZXV' +$TenantId = '4cd76576-b611-43d0-8f2b-adcb139531bf' +$ApplicationId = '3794a65a-e4e4-493d-ac1d-f04308d712dd' +Connect-AzAccount -CertificateThumbprint $Thumbprint -ApplicationId $ApplicationId -Tenant $TenantId -ServicePrincipal Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- @@ -2921,28 +2986,7 @@ SubscriptionId : 85f0f653-1f86-4d2c-a9f1-042efc00085c TenantId : 4cd76576-b611-43d0-8f2b-adcb139531bf Environment : AzureCloud - This command connects to an Azure account using certificate-based service principal authentication. The service principal used for authentication should have been created with the given certificate. - - - - - - -- Example 9: Add an account using AccessToken authentication -- - PS C:\> $url = "https://login.windows.net/<TenantId>/oauth2/token" -PS C:\> $body = "grant_type=refresh_token&refresh_token=<refreshtoken>" # Refresh token obtained from ~/.azure/TokenCache.dat -PS C:\> $response = Invoke-RestMethod $url -Method POST -Body $body -PS C:\> $AccessToken = $response.access_token -PS C:\> $body1 = $body + "&resource=https%3A%2F%2Fvault.azure.net" -PS C:\> $response = Invoke-RestMethod $url -Method POST -Body $body1 -PS C:\> $body2 = $body + "&resource=https%3A%2F%2Fgraph.windows.net" -PS C:\> $GraphAccessToken = $response.access_token -PS C:\> Connect-AzAccount -AccountId "azureuser@contoso.com" -AccessToken $AccessToken -KeyVaultAccessToken $KeyVaultAccessToken -GraphAccessToken $GraphAccessToken -Tenant "xxxx-xxxx-xxxx-xxxx" -SubscriptionId "yyyy-yyyy-yyyy-yyyy" - -Account SubscriptionName TenantId Environment -------- ---------------- -------- ----------- -azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - - This command connects to an Azure account specified in "AccountId" using the AccessToken and KeyVaultAccessToken provided. + @@ -3099,11 +3143,21 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - ---------------- Disable autosaving the context ---------------- + ---------- Example 1: Disable autosaving the context ---------- PS C:\> Disable-AzContextAutosave Disable autosave for the current user. + + + + + -------------------------- Example 2 -------------------------- + <!-- Aladdin Generated Example --> +Disable-AzContextAutosave -Scope Process + + + @@ -3121,11 +3175,11 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloudDisable AzDataCollection - Opts out of collecting data to improve the AzurePowerShell cmdlets. Data is not collected unless you explicitly opt in. + Opts out of collecting data to improve the Azure PowerShell cmdlets. Data is collected by default unless you explicitly opt out. - You can improve the experience of using the Microsoft Cloud and Azure PowerShell by opting in to data collection. Azure PowerShell does not collect data without your consent - you must explicitly opt in by executing Enable-AzDataCollection, or by answering yes when Azure PowerShell prompts you about collecting data the first time you execute a cmdlet. Microsoft aggregates collected data to identify patterns of usage, to identify common issues and to improve the experience of using Azure PowerShell. Microsoft Azure PowerShell does not collect any private data, or any personally identifiable information. Run the Disable-AzDataCollection cmdlet to disable data collection for the current user. This will prevent the current user from being prompted about data collection the first time cmdlets are executed. To enable data collection for the current user, run the Enable-AzDataCollection cmdlet. + The `Disable-AzDataCollection` cmdlet is used to opt out of data collection. Azure PowerShell automatically collects telemetry data by default. To disable data collection, you must explicitly opt-out. Microsoft aggregates collected data to identify patterns of usage, to identify common issues, and to improve the experience of Azure PowerShell. Microsoft Azure PowerShell doesn't collect any private or personal data. If you've previously opted out, run the `Enable-AzDataCollection` cmdlet to re-enable data collection for the current user on the current machine. @@ -3133,7 +3187,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud DefaultProfile - The credentials, account, tenant and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -3170,7 +3224,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud DefaultProfile - The credentials, account, tenant and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -3232,9 +3286,9 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud -- Example 1: Disabling data collection for the current user -- - PS C:\> Disable-AzDataCollection + Disable-AzDataCollection - This example shows how to disable data collection for the current user. + @@ -3976,7 +4030,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - ---------------- Logout of the current account ---------------- + ----------- Example 1: Logout of the current account ----------- PS C:\> Disconnect-AzAccount Logs out of the Azure account associated with the current context. @@ -3985,7 +4039,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - -- Logout of the account associated with a particular context -- + Example 2: Logout of the account associated with a particular context PS C:\> Get-AzContext "Work" | Disconnect-AzAccount -Scope CurrentUser Logs out the account associated with the given context (named 'Work'). Because this uses the 'CurrentUser' scope, all credentials and contexts will be permanently deleted. @@ -3994,7 +4048,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - ------------------ Log out a particular user ------------------ + ------------- Example 3: Log out a particular user ------------- PS C:\> Disconnect-AzAccount -Username 'user1@contoso.org' Logs out the 'user1@contoso.org' user - all credentials and all contexts associated with this user will be removed. @@ -4154,11 +4208,21 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - ------ Enable autosaving credentials for the current user ------ + Example 1: Enable autosaving credentials for the current user PS C:\> Enable-AzContextAutosave Turn on credential autosave for the current user. Whenever a powershell window is opened, your current context will be remembered without logging in. + + + + + -------------------------- Example 2 -------------------------- + <!-- Aladdin Generated Example --> +Enable-AzContextAutosave -Scope Process + + + @@ -4176,11 +4240,11 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloudEnable AzDataCollection - Enables Azure PowerShell to collect data to improve the user experience with AzurePowerShell cmdlets. Executing this cmdlet opts in to data collection for the current user on the current machine. No data is collected unless you explicitly opt in. + Enables Azure PowerShell to collect data to improve the user experience with the Azure PowerShell cmdlets. Executing this cmdlet opts in to data collection for the current user on the current machine. Data is collected by default unless you explicitly opt out. - You can improve the experience of using the Microsoft Cloud and Azure PowerShell by opting in to data collection. Azure PowerShell does not collect data without your consent - you must explicitly opt in by executing Enable-AzDataCollection, or by answering yes when Azure PowerShell prompts you about collecting data the first time you execute a cmdlet. Microsoft aggregates collected data to identify patterns of usage, to identify common issues and to improve the experience of using Azure PowerShell. Microsoft Azure PowerShell does not collect any private data, or any personally identifiable information. Run the Enable-AzDataCollection cmdlet to enable data collection for the current user on the current machine. This will prevent the current user from being prompted about data collection the first time cmdlets are executed. To disable data collection for the current user, run the Disable-AzDataCollection cmdlet. + The `Enable-AzDataCollection` cmdlet is used to opt in to data collection. Azure PowerShell automatically collects telemetry data by default. Microsoft aggregates collected data to identify patterns of usage, to identify common issues, and to improve the experience of Azure PowerShell. Microsoft Azure PowerShell doesn't collect any private or personal data. To disable data collection, you must explicitly opt out by executing `Disable-AzDataCollection`. @@ -4188,7 +4252,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud DefaultProfile - The credentials, account, tenant and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -4225,7 +4289,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud DefaultProfile - The credentials, account, tenant and subscription used for communication with azure. + The credentials, account, tenant, and subscription used for communication with Azure. Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer @@ -4287,9 +4351,9 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud --- Example 1: Enabling data collection for the current user --- - PS C:\> Enable-AzDataCollection + Enable-AzDataCollection - This example shows how to enable data collection for the current user. + @@ -4508,7 +4572,7 @@ azureuser@contoso.com Subscription1 xxxx-xxxx-xxxx-xxxx AzureCloud - -------------------------- Example 1 -------------------------- + -------------------------- Example 2 -------------------------- PS C:\> Enable-AzureRmAlias -Module Az.Accounts -Scope CurrentUser Enables AzureRm aliases for the Az.Accounts module for both the current process and for the current user. @@ -6926,7 +6990,7 @@ TestEnvironment TestRMEndpoint TestADEndpoint/ - ----------- Rename a context using named parameters ----------- + ------ Example 1: Rename a context using named parameters ------ PS C:\> Rename-AzContext -SourceName "[user1@contoso.org; 12345-6789-2345-3567890]" -TargetName "Work" Rename the context for 'user1@contoso.org' with subscription '12345-6789-2345-3567890' to 'Work'. After this command, you will be able to target the context using 'Select-AzContext Work'. Note that you can tab through the values for 'SourceName' using tab completion. @@ -6935,7 +6999,7 @@ TestEnvironment TestRMEndpoint TestADEndpoint/ - --------- Rename a context using positional parameters --------- + --- Example 2: Rename a context using positional parameters --- PS C:\> Rename-AzContext "My context" "Work" Rename the context named "My context" to "Work". After this command, you will be able to target the context using Select-AzContext Work @@ -7706,7 +7770,7 @@ PS C:\> Save-AzContext -Path C:\test.json - -------------- Example 1 : Target a named context -------------- + -------------- Example 1: Target a named context -------------- PS C:\> Select-AzContext "Work" Name Account SubscriptionName Environment TenantId @@ -7715,6 +7779,16 @@ Work test@outlook.com Subscription1 AzureCloud xxxxxxxx-x.. Target future Azure PowerShell cmdlets at the account, tenant, and subscription in the 'Work' context. + + + + + -------------------------- Example 2 -------------------------- + <!-- Aladdin Generated Example --> +Select-AzContext -Name TestEnvironment -Scope Process + + + @@ -9274,6 +9348,30 @@ Tags : None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + DefaultProfile @@ -9483,6 +9581,30 @@ Tags : None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + DefaultProfile @@ -9704,6 +9826,30 @@ Tags : None + + AzureSynapseAnalyticsEndpointResourceId + + The The resource identifier of the Azure Synapse Analytics that is the recipient of the requested token. + + System.String + + System.String + + + None + + + AzureSynapseAnalyticsEndpointSuffix + + Dns suffix of Azure Synapse Analytics. + + System.String + + System.String + + + None + BatchEndpointResourceId @@ -9995,7 +10141,9 @@ BatchEndpointResourceId : AzureOperationalInsightsEndpoint : AzureOperationalInsightsEndpointResourceId : AzureAttestationServiceEndpointSuffix : -AzureAttestationServiceEndpointResourceId : +AzureAttestationServiceEndpointResourceId : +AzureSynapseAnalyticsEndpointSuffix : +AzureSynapseAnalyticsEndpointResourceId : In this example we are creating a new Azure environment with sample endpoints using Add-AzEnvironment, and then we are changing the value of the ActiveDirectoryEndpoint and GraphEndpoint attributes of the created environment using the cmdlet Set-AzEnvironment. diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Common.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Common.dll similarity index 56% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Common.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Common.dll index c8fba6b2c747be20b95dfad37921c51f11b2f7fc..2df8d994f8f6d72273c95e32425bd1995d54dbb7 100644 GIT binary patch delta 66203 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 Ap#T5? diff --git a/powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Storage.dll b/powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Storage.dll similarity index 72% rename from powershell/resources/modules/Az.Accounts/1.7.4/Microsoft.Azure.PowerShell.Storage.dll rename to powershell/resources/modules/Az.Accounts/1.8.1/Microsoft.Azure.PowerShell.Storage.dll index 21d897a1f59b3cfb5a69588903d7c77cb78a4651..b36dd7d8d93eb95a1825df9e9a2f18b114810caa 100644 GIT binary patch delta 3391 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 Qrf`d(!?|B&g_p-a01lg!EC2ui delta 3556 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 C$GL_8 delta 3548 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 MomJEI3oIf24{w;^kN^Mx literal 0 HcmV?d00001 diff --git a/powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/Microsoft.Bcl.AsyncInterfaces.dll b/powershell/resources/modules/Az.Accounts/1.8.1/NetCoreAssemblies/Microsoft.Bcl.AsyncInterfaces.dll new file mode 100644 index 0000000000000000000000000000000000000000..0a784888baf18341861adeed296adc47cb8e153c GIT binary patch literal 20856 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