Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to converter #4868

Merged
merged 12 commits into from
Feb 1, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@autorest/openapi-to-typespec",
"comment": "Add support for custom resource, enhance doc conversion and fix default value issue",
"type": "minor"
}
],
"packageName": "@autorest/openapi-to-typespec"
}
331 changes: 195 additions & 136 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/extensions/openapi-to-typespec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ tsproject.yaml - Contains configuration for the TypeSpec compiler
package.json - Configuration of the TypeSpec project

```yaml
version: 3.6.6
version: 3.10.1
use-extension:
"@autorest/modelerfour": "^4.23.5"
"@autorest/modelerfour": "^4.27.0"

modelerfour:
# this runs a pre-namer step to clean up names
Expand Down
4 changes: 2 additions & 2 deletions packages/extensions/openapi-to-typespec/convert.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ param(
function GenerateMetadata ()
{
Write-Host "##Generating metadata with csharp codegen in $outputFolder with $csharpCodegen"
$cmd = "autorest --csharp --isAzureSpec --isArm --max-memory-size=8192 --use=`"$csharpCodegen`" --output-folder=$outputFolder --mgmt-debug.only-generate-metadata --azure-arm --skip-csproj $swaggerConfigFile"
$cmd = "autorest --version=3.10.1 --csharp --isAzureSpec --isArm --max-memory-size=8192 --use=`"$csharpCodegen`" --output-folder=$outputFolder --mgmt-debug.only-generate-metadata --azure-arm --skip-csproj $swaggerConfigFile"
Write-Host "$cmd"
Invoke-Expression $cmd
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Expand All @@ -42,7 +42,7 @@ function GenerateMetadata ()
function DoConvert ()
{
Write-Host "##Converting from swagger to tsp with in $outputFolder with $converterCodegen"
$cmd = "autorest --openapi-to-typespec --isAzureSpec --isArm --use=`"$converterCodegen`" --output-folder=$outputFolder --src-path=tsp-output $swaggerConfigFile"
$cmd = "autorest --version=3.10.1 --openapi-to-typespec --isAzureSpec --isArm --use=`"$converterCodegen`" --output-folder=$outputFolder $swaggerConfigFile"
Write-Host "$cmd"
Invoke-Expression $cmd
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Expand Down
22 changes: 11 additions & 11 deletions packages/extensions/openapi-to-typespec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@
"@azure-tools/codegen": "~2.10.0",
"@autorest/extension-base": "~3.6.0",
"@autorest/codemodel": "~4.20.0",
"@typespec/compiler": "^0.51.0",
"@typespec/rest": "^0.51.0",
"@typespec/http": "^0.51.0",
"@typespec/versioning": "^0.51.0",
"@typespec/prettier-plugin-typespec": "^0.51.0",
"@azure-tools/typespec-azure-core": "^0.37.2",
"@azure-tools/typespec-autorest": "^0.37.2",
"@azure-tools/typespec-azure-resource-manager": "^0.37.1",
"@typespec/openapi": "^0.50.0",
"@typespec/openapi3": "^0.50.0",
"@typespec/compiler": "^0.52.0",
"@typespec/rest": "^0.52.0",
"@typespec/http": "^0.52.0",
"@typespec/versioning": "^0.52.0",
"@typespec/prettier-plugin-typespec": "^0.52.0",
"@azure-tools/typespec-azure-core": "^0.38.0",
"@azure-tools/typespec-autorest": "^0.38.0",
"@azure-tools/typespec-azure-resource-manager": "^0.38.0",
"@typespec/openapi": "^0.52.0",
"@typespec/openapi3": "^0.52.0",
"prettier": "~3.1.0",
"lodash": "~4.17.20",
"pluralize": "^8.0.0",
Expand All @@ -67,7 +67,7 @@
"fs-extra": "^10.1.0",
"@types/fs-extra": "^9.0.13",
"chalk": "^4.1.0",
"@azure-tools/typespec-autorest": "^0.37.2",
"@azure-tools/typespec-autorest": "^0.38.0",
"webpack-cli": "~5.1.4",
"webpack": "~5.89.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@ import { Case } from "change-case-all";
import { TypespecOperation, TspArmResource } from "interfaces";
import _ from "lodash";
import pluralize from "pluralize";
import { getArmCommonTypeVersion } from "../autorest-session";
import { replaceGeneratedResourceObject } from "../transforms/transform-arm-resources";
import { generateDecorators } from "../utils/decorators";
import { generateDocs } from "../utils/docs";
import { getModelPropertiesDeclarations } from "../utils/model-generation";
import { generateOperation } from "./generate-operations";

export function generateArmResource(resource: TspArmResource): string {
const definitions: string[] = [];

definitions.push(generateArmResourceModel(resource));

definitions.push("\n");

definitions.push(generateArmResourceOperation(resource));

definitions.push("\n");

for (const o of resource.resourceOperations) {
for (const d of o.augmentedDecorators ?? []) {
definitions.push(`${d}`);
}
}

return definitions.join("\n");
}

function generateArmResourceModel(resource: TspArmResource): string {
let definitions: string[] = [];

for (const fixme of resource.fixMe ?? []) {
Expand All @@ -25,28 +46,54 @@ export function generateArmResource(resource: TspArmResource): string {
definitions.push(`@parentResource(${resource.resourceParent.name})`);
}

definitions.push(`model ${resource.name} is ${resource.resourceKind}<${resource.propertiesModelName}> {`);
if (
getArmCommonTypeVersion() &&
!resource.propertiesPropertyRequired &&
resource.propertiesPropertyVisibility.length === 2 &&
resource.propertiesPropertyVisibility.includes("read") &&
resource.propertiesPropertyVisibility.includes("create")
) {
definitions.push(`model ${resource.name} is ${resource.resourceKind}<${resource.propertiesModelName}> {`);

definitions = [...definitions, ...getModelPropertiesDeclarations(resource.properties)];
definitions = [...definitions, ...getModelPropertiesDeclarations(resource.properties)];
} else {
definitions.push(
`#suppress "@azure-tools/typespec-azure-core/composition-over-inheritance" "For backward compatibility"`,
);
definitions.push(
`#suppress "@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property" "For backward compatibility"`,
);
definitions.push(`@includeInapplicableMetadataInPayload(false)`);

for (const p of resource.optionalStandardProperties) {
definitions.push(`\n...${p}`);
}
if (!getArmCommonTypeVersion()) {
if (resource.baseModelName) {
definitions.push(`model ${resource.name} extends ${resource.baseModelName} {`);
} else {
definitions.push(`model ${resource.name} {`);
}
} else {
definitions.push(`@Azure.ResourceManager.Private.armResourceInternal(${resource.propertiesModelName})`);
definitions.push(`model ${resource.name} extends ${resource.resourceKind}Base {`);
}

definitions.push("}\n");
definitions = [...definitions, ...getModelPropertiesDeclarations(resource.properties)];

definitions.push("\n");
const propertyDoc = generateDocs({ doc: resource.propertiesPropertyDescription });
propertyDoc && definitions.push(propertyDoc);

definitions.push(generateArmResourceOperation(resource));
definitions.push(`@extension("x-ms-client-flatten", true)`);
if (resource.propertiesPropertyVisibility.length > 0) {
definitions.push(`@visibility("${resource.propertiesPropertyVisibility.join(",")}")`);
}

definitions.push("\n");
definitions.push(`properties${resource.propertiesPropertyRequired ? "" : "?"}: ${resource.propertiesModelName}`);
}

for (const o of resource.resourceOperations) {
for (const d of o.augmentedDecorators ?? []) {
definitions.push(`${d}`);
}
for (const p of resource.optionalStandardProperties) {
definitions.push(`\n...${p}`);
}

definitions.push("}\n");
return definitions.join("\n");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TypespecParameter } from "../interfaces";
import { generateDecorators } from "../utils/decorators";
import { generateDocs } from "../utils/docs";
import { transformDefaultValue } from "../utils/values";

export function generateParameter(parameter: TypespecParameter): string {
const definitions: string[] = [];
Expand All @@ -12,7 +11,7 @@ export function generateParameter(parameter: TypespecParameter): string {
decorators && definitions.push(decorators);
let defaultValue = "";
if (parameter.defaultValue) {
defaultValue = ` = ${transformDefaultValue(parameter.type, parameter.defaultValue)}`;
defaultValue = ` = ${parameter.defaultValue}`;
}
definitions.push(`"${parameter.name}"${parameter.isOptional ? "?" : ""}: ${parameter.type}${defaultValue}`);

Expand Down
4 changes: 4 additions & 0 deletions packages/extensions/openapi-to-typespec/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,12 @@ export interface TspArmResourceExistsOperation extends TspArmResourceOperationBa
export interface TspArmResource extends TypespecObject {
resourceKind: ArmResourceKind;
propertiesModelName: string;
propertiesPropertyRequired: boolean;
propertiesPropertyVisibility: string[];
propertiesPropertyDescription: string;
resourceParent?: TspArmResource;
resourceOperations: TspArmResourceOperation[];
normalOperations: TypespecOperation[];
optionalStandardProperties: string[];
baseModelName?: string;
}
2 changes: 1 addition & 1 deletion packages/extensions/openapi-to-typespec/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function processDetector(host: AutorestExtensionHost) {
for (const v of Object.values(session.model.components.schemas)) {
if (v["x-ms-metadata"]?.originalLocations) {
for (const p of v["x-ms-metadata"].originalLocations) {
const result = p.match(/\/specification\/common-types\/resource-management\/(v\d)\//);
const result = p.match(/\/common-types\/resource-management\/(v\d)\//);
if (result) {
setArmCommonTypeVersion(result[1]);
return;
Expand Down
Loading
Loading