@autorest/openapi-to-typespec
Version:
Autorest plugin to scaffold a Typespec definition from an OpenAPI document
127 lines (114 loc) • 4.31 kB
text/typescript
import { join } from "path";
import { getSession } from "../autorest-session";
import { generateServiceInformation } from "../generate/generate-service-information";
import { TypespecProgram } from "../interfaces";
import { getOptions } from "../options";
import { formatTypespecFile } from "../utils/format";
import { getMainImports } from "../utils/imports";
import { Metadata } from "../utils/resource-discovery";
const packageInfo = require("../../package.json");
export async function emitMain(
program: TypespecProgram,
metadata: Metadata | undefined,
basePath: string,
): Promise<void> {
const { isArm } = getOptions();
const content = `${getHeaders()}\n${
isArm ? getArmServiceInformation(program, metadata!) : getServiceInformation(program)
}${
isArm && program.listOperation !== undefined
? "\n\ninterface Operations extends Azure.ResourceManager.Operations {}"
: ""
}`;
const filePath = join(basePath, "main.tsp");
const session = getSession();
session.writeFile({ filename: filePath, content: await formatTypespecFile(content, filePath) });
if (program.listOperation?.examples) {
emitExamples(program.listOperation.examples, program.serviceInformation.versions, basePath);
}
}
function getHeaders() {
const { isTest, isFullCompatible, guessResourceKey } = getOptions();
return [
`/**`,
`* PLEASE DO NOT REMOVE - USED FOR CONVERTER METRICS`,
`* Generated by package: ${packageInfo.name}`,
`* Parameters used:`,
`* isFullCompatible: ${isFullCompatible}`,
`* guessResourceKey: ${guessResourceKey}`,
`* Version: ${isTest ? "Not generated in test" : packageInfo.version}`,
`* Date: ${isTest ? "Not generated in test" : new Date().toISOString()}`,
`*/`,
].join("\n");
}
function getServiceInformation(program: TypespecProgram) {
const { modules, namespaces: namespacesSet } = getMainImports(program);
const imports = [
...new Set<string>([`import "@typespec/rest";`, `import "@typespec/http";`, ...modules, `import "./routes.tsp"`]),
].join("\n");
const namespaces = [
...new Set<string>([
`using TypeSpec.Rest;`,
`using TypeSpec.Http;`,
`using TypeSpec.Versioning;`,
...namespacesSet,
]),
].join("\n");
return [imports, "\n", namespaces, "\n", generateServiceInformation(program)].join("\n");
}
function getArmServiceInformation(program: TypespecProgram, metadata: Metadata) {
const { isFullCompatible } = getOptions();
const imports = [
`import "@typespec/rest";`,
`import "@typespec/versioning";`,
`import "@azure-tools/typespec-azure-core";`,
`import "@azure-tools/typespec-azure-resource-manager";`,
`import "./models.tsp";`,
];
if (isFullCompatible) {
imports.push(`import "./back-compatible.tsp";`);
}
imports.push(
...[
...getArmResourceImports(program, metadata),
``,
`using TypeSpec.Rest;`,
`using TypeSpec.Http;`,
`using Azure.ResourceManager.Foundations;`,
`using Azure.Core;`,
`using Azure.ResourceManager;`,
`using TypeSpec.Versioning;`,
],
);
const content = generateServiceInformation(program);
return [...imports, content].join("\n");
}
function getArmResourceImports(program: TypespecProgram, metadata: Metadata): string[] {
const imports: string[] = [];
for (const resource in metadata.Resources) {
const fileName = metadata.Resources[resource][0].SwaggerModelName;
if (fileName) {
imports.push(`import "./${fileName}.tsp";`);
}
}
if (program.operationGroups.length > 0) {
imports.push(`import "./routes.tsp";`);
}
if (Object.keys(metadata.Resources).find((key) => metadata.Resources[key].length > 1)) {
imports.push(`import "./legacy.tsp";`);
}
return imports;
}
export function emitExamples(examples: Record<string, string>, versions: string[] | undefined, basePath: string): void {
const session = getSession();
for (const [filename, content] of Object.entries(examples)) {
if (versions) {
session.writeFile({
filename: join(basePath, "examples", versions[0], filename), // TODO: how to handle multiple versions?
content,
});
} else {
session.writeFile({ filename: join(basePath, "examples", "unknown", filename), content });
}
}
}