Skip to content

Commit

Permalink
[tsp-client] Add support for arm swagger->tsp conversion (#7881)
Browse files Browse the repository at this point in the history
* add support for arm swagger->tsp

* update docs

* feedback
  • Loading branch information
catalinaperalta authored Mar 19, 2024
1 parent 3008573 commit a4b178e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 23 deletions.
3 changes: 2 additions & 1 deletion tools/tsp-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Convert an existing swagger specification to a TypeSpec project. This command sh

## Options
```
--arm Convert ARM swagger specification to TypeSpec [boolean]
-c, --tsp-config The tspconfig.yaml file to use [string]
--commit Commit to be used for project init or update [string]
-d, --debug Enable debug logging [boolean]
Expand All @@ -55,7 +56,7 @@ Convert an existing swagger specification to a TypeSpec project. This command sh
--skip-sync-and-generate Skip sync and generate during project init [boolean]
--swagger-readme Path or url to swagger readme file [string]
-o, --output-dir Specify an alternate output directory for the
generated files. Default is your local directory. [string]
generated files. Default is your current directory [string]
--repo Repository where the project is defined for init
or update [string]
-v, --version Show version number [boolean]
Expand Down
44 changes: 22 additions & 22 deletions tools/tsp-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { npmCommand } from "./npm.js";
import { npmCommand, npxCommand } from "./npm.js";
import { createTempDirectory, removeDirectory, readTspLocation, getEmitterFromRepoConfig } from "./fs.js";
import { Logger, printBanner, enableDebug, printVersion } from "./log.js";
import { TspLocation, compileTsp, discoverMainFile, resolveTspConfigUrl } from "./typespec.js";
import { getOptions } from "./options.js";
import { mkdir, writeFile, cp, readFile, access, stat } from "node:fs/promises";
import { mkdir, writeFile, cp, readFile, access, stat, rename } from "node:fs/promises";
import { addSpecFiles, checkoutCommit, cloneRepo, getRepoRoot, sparseCheckout } from "./git.js";
import { doesFileExist } from "./network.js";
import { parse as parseYaml } from "yaml";
import { joinPaths, normalizePath, resolvePath } from "@typespec/compiler";
import { formatAdditionalDirectories, getAdditionalDirectoryName } from "./utils.js";
import { resolve } from "node:path";
import { spawn } from "node:child_process";
import { config as dotenvConfig } from "dotenv";


Expand Down Expand Up @@ -240,24 +239,25 @@ async function generate({
}


async function convert(readme: string, outputDir: string): Promise<void> {
return new Promise((resolve, reject) => {
const autorest = spawn("npx", ["autorest", readme, "--openapi-to-typespec", "--use=@autorest/openapi-to-typespec", `--output-folder=${outputDir}`], {
cwd: outputDir,
stdio: "inherit",
shell: true,
});
autorest.once("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`openapi to typespec conversion failed exited with code ${code}`));
}
});
autorest.once("error", (err) => {
reject(new Error(`openapi to typespec conversion failed with error: ${err}`));
});
});
async function convert(readme: string, outputDir: string, arm?: boolean): Promise<void> {
const args = ["autorest", "--openapi-to-typespec", "--csharp=false", `--output-folder="${outputDir}"`, "--use=@autorest/openapi-to-typespec", `"${readme}"`];
if (arm) {
const generateMetadataCmd = ["autorest", "--csharp", "--max-memory-size=8192", '--use="https://aka.ms/azsdk/openapi-to-typespec-csharp"', `--output-folder="${outputDir}"`, "--mgmt-debug.only-generate-metadata", "--azure-arm", "--skip-csproj", `"${readme}"`];
try {
await npxCommand(outputDir, generateMetadataCmd);
} catch (err) {
Logger.error(`Error occurred while attempting to generate ARM metadata: ${err}`);
process.exit(1);
}
try {
await rename(joinPaths(outputDir, "metadata.json"), joinPaths(outputDir, "resources.json"));
} catch (err) {
Logger.error(`Error occurred while attempting to rename metadata.json to resources.json: ${err}`);
process.exit(1);
}
args.push("--isArm");
}
return await npxCommand(outputDir, args);
}


Expand Down Expand Up @@ -330,7 +330,7 @@ async function main() {
if (await doesFileExist(readme)) {
readme = normalizePath(resolve(readme));
}
await convert(readme, rootUrl);
await convert(readme, rootUrl, options.arm);
break;
default:
throw new Error(`Unknown command: ${options.command}`);
Expand Down
1 change: 1 addition & 0 deletions tools/tsp-client/src/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Commands:
convert Convert a swagger specification to TypeSpec [string]
Options:
--arm Convert ARM swagger specification to TypeSpec [boolean]
-c, --tsp-config The tspconfig.yaml file to use [string]
--commit Commit to be used for project init or update [string]
-d, --debug Enable debug logging [boolean]
Expand Down
20 changes: 20 additions & 0 deletions tools/tsp-client/src/npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ export async function npmCommand(workingDir: string, args: string[]): Promise<vo
});
}

export async function npxCommand(workingDir: string, args: string[]): Promise<void> {
return new Promise((resolve, reject) => {
const npm = spawn("npx", args, {
cwd: workingDir,
stdio: "inherit",
shell: true,
});
npm.once("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`npx ${args[0]} failed exited with code ${code}`));
}
});
npm.once("error", (err) => {
reject(new Error(`npx ${args[0]} failed with error: ${err}`));
});
});
}

let packageVersion: string;
export async function getPackageVersion(): Promise<string> {
if (!packageVersion) {
Expand Down
5 changes: 5 additions & 0 deletions tools/tsp-client/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface Options {
localSpecRepo?: string;
emitterOptions?: string;
swaggerReadme?: string;
arm: boolean;
}

export async function getOptions(): Promise<Options> {
Expand Down Expand Up @@ -64,6 +65,9 @@ export async function getOptions(): Promise<Options> {
},
["swagger-readme"]: {
type: "string",
},
arm: {
type: "boolean",
}
},
});
Expand Down Expand Up @@ -165,5 +169,6 @@ export async function getOptions(): Promise<Options> {
localSpecRepo: values["local-spec-repo"],
emitterOptions: values["emitter-options"],
swaggerReadme: values["swagger-readme"],
arm: values.arm ?? false,
};
}

0 comments on commit a4b178e

Please sign in to comment.