From ba9658eacfdce95ad572bb77d098fa692bfb9ccc Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Fri, 20 Dec 2024 19:02:48 -0800 Subject: [PATCH 01/11] add new command --- tools/tsp-client/src/commands.ts | 45 ++++++++++++++++++++++++++++++++ tools/tsp-client/src/index.ts | 21 +++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index 0dc3a35a826..a6998de358a 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -400,6 +400,51 @@ export async function convertCommand(argv: any): Promise { } } +export async function generateConfigFilesCommand(argv: any) { + const outputDir = argv["output-dir"]; + const repoRoot = await getRepoRoot(outputDir); + const packageJsonPath = normalizePath(resolve(argv["package-json"])); + + if (packageJsonPath === undefined || !(await doesFileExist(packageJsonPath))) { + throw new Error(`package.json not found in: ${packageJsonPath ?? "[Not Specified]"}`); + } + Logger.info("Generating emitter-package.json file..."); + const content = await readFile(packageJsonPath); + const packageJson: Record = JSON.parse(content.toString()); + const emitterPackageJson: Record = { + name: "dist/src/index.js", + dependencies: {}, + }; + + // Add emitter as dependency + emitterPackageJson["dependencies"][packageJson["name"]] = packageJson["version"]; + + const devDependencies: Record = {}; + + const possiblyPinnedPackages = + packageJson["azure-sdk/emitter-package-json-pinning"] ?? packageJson["peerDependencies"]; + + for (const pinnedPackage in possiblyPinnedPackages) { + const pinnedVersion = packageJson["devDependencies"][pinnedPackage]; + if (pinnedVersion) { + Logger.info(`Pinning ${pinnedPackage} to ${pinnedVersion}`); + devDependencies[pinnedPackage] = pinnedVersion; + } else { + devDependencies[pinnedPackage] = possiblyPinnedPackages[pinnedPackage]; + } + } + + emitterPackageJson["devDependencies"] = devDependencies; + + await writeFile( + joinPaths(repoRoot, "eng", "emitter-package.json"), + JSON.stringify(emitterPackageJson, null, 2), + ); + Logger.info(`emitter-package.json file generated in '${joinPaths(repoRoot, "eng")}' directory`); + + generateLockFileCommand(argv); +} + export async function generateLockFileCommand(argv: any) { const outputDir = argv["output-dir"]; const repoRoot = await getRepoRoot(outputDir); diff --git a/tools/tsp-client/src/index.ts b/tools/tsp-client/src/index.ts index 4765a0c6fbd..0f4a64b8003 100644 --- a/tools/tsp-client/src/index.ts +++ b/tools/tsp-client/src/index.ts @@ -5,6 +5,7 @@ import { compareCommand, convertCommand, generateCommand, + generateConfigFilesCommand, generateLockFileCommand, initCommand, sortSwaggerCommand, @@ -210,6 +211,26 @@ const parser = yargs(hideBin(process.argv)) await convertCommand(argv); }, ) + .command( + "generate-config-files", + "Generate emitter-package.json and emitter-package-lock.json files from a TypeSpec emitter's package.json", + (yargs: any) => { + return yargs + .option("package-json", { + type: "string", + description: "Path to the emitter's package.json file", + demandOption: true, + }) + .option("override-config", { + type: "string", + description: "Path to an override config file for pinning specific dependencies", + }); + }, + async (argv: any) => { + argv["output-dir"] = resolveOutputDir(argv); + await generateConfigFilesCommand(argv); + }, + ) .command( "generate-lock-file", "Generate a lock file under the eng/ directory from an existing emitter-package.json", From ac0241aeab183b853cf3932d0831db76e46aa7c0 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Fri, 20 Dec 2024 19:11:39 -0800 Subject: [PATCH 02/11] update docs --- tools/tsp-client/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/tsp-client/README.md b/tools/tsp-client/README.md index a589c32e517..7c573c9c9d7 100644 --- a/tools/tsp-client/README.md +++ b/tools/tsp-client/README.md @@ -5,7 +5,7 @@ A simple command line tool to facilitate generating client libraries from TypeSp ## Installation ``` -npm install @azure-tools/typespec-client-generator-cli +npm install -g @azure-tools/typespec-client-generator-cli ``` ## Prerequisites @@ -63,6 +63,10 @@ correspond to differences in the service, allowing you to focus only on differen Sort an existing swagger specification to be the same content order with TypeSpec generated swagger. This will allow you to easily compare and identify differences between the existing swagger and TypeSpec generated one. You should run this command on existing swagger files and check them in prior to creating converted TypeSpec PRs. +### generate-config-files + +Generate the `emitter-package.json` and `emitter-package-lock.json` used for tsp-client commands under the eng/ directory of your current repository. + ### generate-lock-file Generate an emitter-package-lock.json under the eng/ directory based on existing `/eng/emitter-package.json`. From c90655a3b44c9a7d030bea39350e359cb306ee98 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Wed, 8 Jan 2025 18:51:01 -0800 Subject: [PATCH 03/11] update command --- tools/tsp-client/src/commands.ts | 22 ++++++++++++++++------ tools/tsp-client/src/index.ts | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index a0ced982960..f044d7ef6b2 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -409,6 +409,7 @@ export async function generateConfigFilesCommand(argv: any) { const outputDir = argv["output-dir"]; const repoRoot = await getRepoRoot(outputDir); const packageJsonPath = normalizePath(resolve(argv["package-json"])); + const overridePath = argv["overrides"] ?? undefined; if (packageJsonPath === undefined || !(await doesFileExist(packageJsonPath))) { throw new Error(`package.json not found in: ${packageJsonPath ?? "[Not Specified]"}`); @@ -421,9 +422,16 @@ export async function generateConfigFilesCommand(argv: any) { dependencies: {}, }; + let overrideJson: Record = {}; + if (overridePath) { + overrideJson = JSON.parse((await readFile(overridePath)).toString()) ?? {}; + } + // Add emitter as dependency - emitterPackageJson["dependencies"][packageJson["name"]] = packageJson["version"]; + emitterPackageJson["dependencies"][packageJson["name"]] = + overrideJson[packageJson["name"]] ?? packageJson["version"]; + delete overrideJson[packageJson["name"]]; const devDependencies: Record = {}; const possiblyPinnedPackages = @@ -431,16 +439,18 @@ export async function generateConfigFilesCommand(argv: any) { for (const pinnedPackage in possiblyPinnedPackages) { const pinnedVersion = packageJson["devDependencies"][pinnedPackage]; - if (pinnedVersion) { + if (pinnedVersion && !overrideJson[pinnedPackage]) { Logger.info(`Pinning ${pinnedPackage} to ${pinnedVersion}`); devDependencies[pinnedPackage] = pinnedVersion; - } else { - devDependencies[pinnedPackage] = possiblyPinnedPackages[pinnedPackage]; } } - emitterPackageJson["devDependencies"] = devDependencies; - + if (Object.keys(devDependencies).length > 0) { + emitterPackageJson["devDependencies"] = devDependencies; + } + if (Object.keys(overrideJson).length > 0) { + emitterPackageJson["overrides"] = overrideJson; + } await writeFile( joinPaths(repoRoot, "eng", "emitter-package.json"), JSON.stringify(emitterPackageJson, null, 2), diff --git a/tools/tsp-client/src/index.ts b/tools/tsp-client/src/index.ts index 0f4a64b8003..5de3ec13aad 100644 --- a/tools/tsp-client/src/index.ts +++ b/tools/tsp-client/src/index.ts @@ -221,7 +221,7 @@ const parser = yargs(hideBin(process.argv)) description: "Path to the emitter's package.json file", demandOption: true, }) - .option("override-config", { + .option("overrides", { type: "string", description: "Path to an override config file for pinning specific dependencies", }); From 2567eb8d1b3d21d02c06cc0f5120bd13d104c6d5 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Fri, 10 Jan 2025 12:04:56 -0800 Subject: [PATCH 04/11] tests + fixes --- tools/tsp-client/src/commands.ts | 2 +- tools/tsp-client/test/commands.spec.ts | 44 +++++++++++++- tools/tsp-client/test/overrides.json | 4 ++ tools/tsp-client/test/package.json | 80 ++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tools/tsp-client/test/overrides.json create mode 100644 tools/tsp-client/test/package.json diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index f044d7ef6b2..54369c5b167 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -457,7 +457,7 @@ export async function generateConfigFilesCommand(argv: any) { ); Logger.info(`emitter-package.json file generated in '${joinPaths(repoRoot, "eng")}' directory`); - generateLockFileCommand(argv); + await generateLockFileCommand(argv); } export async function generateLockFileCommand(argv: any) { diff --git a/tools/tsp-client/test/commands.spec.ts b/tools/tsp-client/test/commands.spec.ts index f29afb14369..6f02f9b80dc 100644 --- a/tools/tsp-client/test/commands.spec.ts +++ b/tools/tsp-client/test/commands.spec.ts @@ -1,10 +1,11 @@ -import { cp, stat, rm } from "node:fs/promises"; +import { cp, stat, rm, readFile } from "node:fs/promises"; import { initCommand, generateCommand, syncCommand, updateCommand, generateLockFileCommand, + generateConfigFilesCommand, } from "../src/commands.js"; import { afterAll, beforeAll, describe, it } from "vitest"; import { assert } from "chai"; @@ -12,6 +13,7 @@ import { getRepoRoot } from "../src/git.js"; import { cwd } from "node:process"; import { joinPaths } from "@typespec/compiler"; import { readTspLocation, removeDirectory } from "../src/fs.js"; +import { doesFileExist } from "../src/network.js"; describe.sequential("Verify commands", () => { let repoRoot; @@ -238,4 +240,44 @@ describe.sequential("Verify commands", () => { assert.fail("Failed to init. Error: " + error); } }); + + it("Generate config files", async () => { + try { + const args = { + "package-json": joinPaths(cwd(), "./test/package.json"), + }; + repoRoot = await getRepoRoot(cwd()); + await generateConfigFilesCommand(args); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package.json"))); + const emitterJson = JSON.parse( + await readFile(joinPaths(repoRoot, "eng", "emitter-package.json"), "utf8"), + ); + assert.equal(emitterJson["dependencies"]["@azure-tools/typespec-python"], "0.37.3"); + assert.isUndefined(emitterJson["overrides"]); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package-lock.json"))); + } catch (error: any) { + assert.fail("Failed to generate tsp-client config files. Error: " + error); + } + }); + + it("Generate config files with overrides", async () => { + try { + const args = { + "package-json": joinPaths(cwd(), "test", "package.json"), + overrides: joinPaths(cwd(), "test", "overrides.json"), + }; + repoRoot = await getRepoRoot(cwd()); + await generateConfigFilesCommand(args); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package.json"))); + const emitterJson = JSON.parse( + await readFile(joinPaths(repoRoot, "eng", "emitter-package.json"), "utf8"), + ); + assert.equal(emitterJson["dependencies"]["@azure-tools/typespec-python"], "0.36.0"); + assert.exists(emitterJson["overrides"]); + assert.equal(emitterJson["overrides"]["@typespec/compiler"], "0.61.0"); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package-lock.json"))); + } catch (error: any) { + assert.fail("Failed to generate tsp-client config files. Error: " + error); + } + }); }); diff --git a/tools/tsp-client/test/overrides.json b/tools/tsp-client/test/overrides.json new file mode 100644 index 00000000000..c555239aa1b --- /dev/null +++ b/tools/tsp-client/test/overrides.json @@ -0,0 +1,4 @@ +{ + "@azure-tools/typespec-python": "0.36.0", + "@typespec/compiler": "0.61.0" +} \ No newline at end of file diff --git a/tools/tsp-client/test/package.json b/tools/tsp-client/test/package.json new file mode 100644 index 00000000000..712fa95d5e4 --- /dev/null +++ b/tools/tsp-client/test/package.json @@ -0,0 +1,80 @@ +{ + "name": "@azure-tools/typespec-python", + "version": "0.37.3", + "author": "Microsoft Corporation", + "description": "Example package.json for tsp-client", + "license": "MIT", + "type": "module", + "main": "dist/src/index.js", + "exports": { + ".": "./dist/src/index.js", + "./testing": "./dist/src/testing/index.js" + }, + "tspMain": "dist/src/index.js", + "engines": { + "node": ">=14.0.0" + }, + "scripts": { + "clean": "rimraf ./dist ./temp ./venv ./node_modules", + "build": "tsc -p .", + "watch": "tsc -p . --watch", + "install": "tsx ./scripts/run-python3.ts ./scripts/install.py", + "prepare": "tsx ./scripts/run-python3.ts ./scripts/prepare.py", + "lint": "tsx ./scripts/eng/lint.ts", + "lint:fix": "eslint . --fix --ext .ts", + "format": "npx prettier **/*.ts --write && tsx ./scripts/eng/format.ts", + "regenerate": "tsx ./scripts/eng/regenerate.ts", + "test": "tsx ./scripts/eng/run-tests.ts" + }, + "files": [ + "dist/**", + "!dist/test/**", + "scripts/**", + "generator/**" + ], + "peerDependencies": { + "@typespec/compiler": ">=0.63.0 <1.0.0", + "@typespec/http": ">=0.63.0 <1.0.0", + "@typespec/rest": ">=0.63.0 <1.0.0", + "@typespec/versioning": ">=0.63.0 <1.0.0", + "@typespec/openapi": ">=0.63.0 <1.0.0", + "@azure-tools/typespec-azure-core": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-azure-resource-manager": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-autorest": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-azure-rulesets": ">=0.49.0 <3.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.49.1 <1.0.0" + }, + "dependencies": { + "js-yaml": "~4.1.0", + "semver": "~7.6.2", + "tsx": "~4.19.1", + "@typespec/http-client-python": "~0.5.1", + "fs-extra": "~11.2.0" + }, + "devDependencies": { + "@typespec/compiler": "~0.63.0", + "@typespec/http": "~0.63.0", + "@typespec/rest": "~0.63.0", + "@typespec/versioning": "~0.63.0", + "@typespec/openapi": "~0.63.0", + "@azure-tools/typespec-azure-resource-manager": "~0.49.0", + "@azure-tools/typespec-azure-core": "~0.49.0", + "@azure-tools/typespec-azure-rulesets": "~0.49.0", + "@azure-tools/typespec-autorest": "~0.49.0", + "@azure-tools/typespec-client-generator-core": "~0.49.1", + "@azure-tools/azure-http-specs": "0.1.0-alpha.4", + "@typespec/http-specs": "0.1.0-alpha.5", + "@types/js-yaml": "~4.0.5", + "@types/node": "~22.5.4", + "@types/yargs": "~17.0.33", + "@types/semver": "7.5.8", + "c8": "^10.1.2", + "vitest": "^2.1.2", + "rimraf": "~6.0.1", + "typescript": "~5.6.3", + "typescript-eslint": "^8.8.1", + "yargs": "~17.7.2", + "chalk": "5.3.0", + "@types/fs-extra": "11.0.4" + } +} From 45c91919141e70895606fa8b5d2be203c795d055 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Wed, 15 Jan 2025 19:03:28 -0800 Subject: [PATCH 05/11] update tests --- tools/tsp-client/test/commands.spec.ts | 7 +- .../test/{ => examples}/overrides.json | 0 .../test/examples/package-sdk-pinning.json | 84 +++++++++++++++++++ .../test/{ => examples}/package.json | 0 4 files changed, 88 insertions(+), 3 deletions(-) rename tools/tsp-client/test/{ => examples}/overrides.json (100%) create mode 100644 tools/tsp-client/test/examples/package-sdk-pinning.json rename tools/tsp-client/test/{ => examples}/package.json (100%) diff --git a/tools/tsp-client/test/commands.spec.ts b/tools/tsp-client/test/commands.spec.ts index 6f02f9b80dc..2f8e35df7c9 100644 --- a/tools/tsp-client/test/commands.spec.ts +++ b/tools/tsp-client/test/commands.spec.ts @@ -244,7 +244,7 @@ describe.sequential("Verify commands", () => { it("Generate config files", async () => { try { const args = { - "package-json": joinPaths(cwd(), "./test/package.json"), + "package-json": joinPaths(cwd(), "test", "examples", "package.json"), }; repoRoot = await getRepoRoot(cwd()); await generateConfigFilesCommand(args); @@ -253,6 +253,7 @@ describe.sequential("Verify commands", () => { await readFile(joinPaths(repoRoot, "eng", "emitter-package.json"), "utf8"), ); assert.equal(emitterJson["dependencies"]["@azure-tools/typespec-python"], "0.37.3"); + assert.equal(emitterJson["devDependencies"]["@typespec/compiler"], "~0.63.0"); assert.isUndefined(emitterJson["overrides"]); assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package-lock.json"))); } catch (error: any) { @@ -263,8 +264,8 @@ describe.sequential("Verify commands", () => { it("Generate config files with overrides", async () => { try { const args = { - "package-json": joinPaths(cwd(), "test", "package.json"), - overrides: joinPaths(cwd(), "test", "overrides.json"), + "package-json": joinPaths(cwd(), "test", "examples", "package.json"), + overrides: joinPaths(cwd(), "test", "examples", "overrides.json"), }; repoRoot = await getRepoRoot(cwd()); await generateConfigFilesCommand(args); diff --git a/tools/tsp-client/test/overrides.json b/tools/tsp-client/test/examples/overrides.json similarity index 100% rename from tools/tsp-client/test/overrides.json rename to tools/tsp-client/test/examples/overrides.json diff --git a/tools/tsp-client/test/examples/package-sdk-pinning.json b/tools/tsp-client/test/examples/package-sdk-pinning.json new file mode 100644 index 00000000000..bde53c84d33 --- /dev/null +++ b/tools/tsp-client/test/examples/package-sdk-pinning.json @@ -0,0 +1,84 @@ +{ + "name": "@azure-tools/typespec-python", + "version": "0.37.3", + "author": "Microsoft Corporation", + "description": "Example package.json for tsp-client", + "license": "MIT", + "type": "module", + "main": "dist/src/index.js", + "exports": { + ".": "./dist/src/index.js", + "./testing": "./dist/src/testing/index.js" + }, + "tspMain": "dist/src/index.js", + "engines": { + "node": ">=14.0.0" + }, + "scripts": { + "clean": "rimraf ./dist ./temp ./venv ./node_modules", + "build": "tsc -p .", + "watch": "tsc -p . --watch", + "install": "tsx ./scripts/run-python3.ts ./scripts/install.py", + "prepare": "tsx ./scripts/run-python3.ts ./scripts/prepare.py", + "lint": "tsx ./scripts/eng/lint.ts", + "lint:fix": "eslint . --fix --ext .ts", + "format": "npx prettier **/*.ts --write && tsx ./scripts/eng/format.ts", + "regenerate": "tsx ./scripts/eng/regenerate.ts", + "test": "tsx ./scripts/eng/run-tests.ts" + }, + "files": [ + "dist/**", + "!dist/test/**", + "scripts/**", + "generator/**" + ], + "peerDependencies": { + "@typespec/compiler": ">=0.63.0 <1.0.0", + "@typespec/http": ">=0.63.0 <1.0.0", + "@typespec/rest": ">=0.63.0 <1.0.0", + "@typespec/versioning": ">=0.63.0 <1.0.0", + "@typespec/openapi": ">=0.63.0 <1.0.0", + "@azure-tools/typespec-azure-core": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-azure-resource-manager": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-autorest": ">=0.49.0 <1.0.0", + "@azure-tools/typespec-azure-rulesets": ">=0.49.0 <3.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.49.1 <1.0.0" + }, + "dependencies": { + "js-yaml": "~4.1.0", + "semver": "~7.6.2", + "tsx": "~4.19.1", + "@typespec/http-client-python": "~0.5.1", + "fs-extra": "~11.2.0" + }, + "devDependencies": { + "@typespec/compiler": "~0.63.0", + "@typespec/http": "~0.63.0", + "@typespec/rest": "~0.63.0", + "@typespec/versioning": "~0.63.0", + "@typespec/openapi": "~0.63.0", + "@azure-tools/typespec-azure-resource-manager": "~0.49.0", + "@azure-tools/typespec-azure-core": "~0.49.0", + "@azure-tools/typespec-azure-rulesets": "~0.49.0", + "@azure-tools/typespec-autorest": "~0.49.0", + "@azure-tools/typespec-client-generator-core": "~0.49.1", + "@azure-tools/azure-http-specs": "0.1.0-alpha.4", + "@typespec/http-specs": "0.1.0-alpha.5", + "@types/js-yaml": "~4.0.5", + "@types/node": "~22.5.4", + "@types/yargs": "~17.0.33", + "@types/semver": "7.5.8", + "c8": "^10.1.2", + "vitest": "^2.1.2", + "rimraf": "~6.0.1", + "typescript": "~5.6.3", + "typescript-eslint": "^8.8.1", + "yargs": "~17.7.2", + "chalk": "5.3.0", + "@types/fs-extra": "11.0.4" + }, + "azure-sdk/emitter-package-json-pinning": { + "@typespec/compiler": ">=0.63.0 <1.0.0", + "@typespec/http": ">=0.63.0 <1.0.0" + } +} diff --git a/tools/tsp-client/test/package.json b/tools/tsp-client/test/examples/package.json similarity index 100% rename from tools/tsp-client/test/package.json rename to tools/tsp-client/test/examples/package.json From 3c92556d4aba1f7c50479cae3b8b050582639347 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Wed, 15 Jan 2025 19:03:53 -0800 Subject: [PATCH 06/11] update azure-sdk/emitter-package-json-pinning logic --- tools/tsp-client/src/commands.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index 54369c5b167..4e5a4859a94 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -433,11 +433,11 @@ export async function generateConfigFilesCommand(argv: any) { delete overrideJson[packageJson["name"]]; const devDependencies: Record = {}; - + const peerDependencies = packageJson["peerDependencies"] ?? {}; const possiblyPinnedPackages = - packageJson["azure-sdk/emitter-package-json-pinning"] ?? packageJson["peerDependencies"]; + packageJson["azure-sdk/emitter-package-json-pinning"] ?? Object.keys(peerDependencies); - for (const pinnedPackage in possiblyPinnedPackages) { + for (const pinnedPackage of possiblyPinnedPackages) { const pinnedVersion = packageJson["devDependencies"][pinnedPackage]; if (pinnedVersion && !overrideJson[pinnedPackage]) { Logger.info(`Pinning ${pinnedPackage} to ${pinnedVersion}`); From f2d966b7a60e288c709b3d514039780b53983e15 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Wed, 15 Jan 2025 19:42:10 -0800 Subject: [PATCH 07/11] add azure-sdk/emitter-package-json-pinning test --- tools/tsp-client/src/commands.ts | 4 ++-- tools/tsp-client/test/commands.spec.ts | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index 4e5a4859a94..19316719ce8 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -434,10 +434,10 @@ export async function generateConfigFilesCommand(argv: any) { delete overrideJson[packageJson["name"]]; const devDependencies: Record = {}; const peerDependencies = packageJson["peerDependencies"] ?? {}; - const possiblyPinnedPackages = + const possiblyPinnedPackages: Array = packageJson["azure-sdk/emitter-package-json-pinning"] ?? Object.keys(peerDependencies); - for (const pinnedPackage of possiblyPinnedPackages) { + for (const pinnedPackage in possiblyPinnedPackages) { const pinnedVersion = packageJson["devDependencies"][pinnedPackage]; if (pinnedVersion && !overrideJson[pinnedPackage]) { Logger.info(`Pinning ${pinnedPackage} to ${pinnedVersion}`); diff --git a/tools/tsp-client/test/commands.spec.ts b/tools/tsp-client/test/commands.spec.ts index 2f8e35df7c9..e0de0b9f733 100644 --- a/tools/tsp-client/test/commands.spec.ts +++ b/tools/tsp-client/test/commands.spec.ts @@ -281,4 +281,24 @@ describe.sequential("Verify commands", () => { assert.fail("Failed to generate tsp-client config files. Error: " + error); } }); + + it("Generate config files using azure-sdk/emitter-package-json-pinning", async () => { + try { + const args = { + "package-json": joinPaths(cwd(), "test", "examples", "package-sdk-pinning.json"), + }; + repoRoot = await getRepoRoot(cwd()); + await generateConfigFilesCommand(args); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package.json"))); + const emitterJson = JSON.parse( + await readFile(joinPaths(repoRoot, "eng", "emitter-package.json"), "utf8"), + ); + assert.equal(emitterJson["dependencies"]["@azure-tools/typespec-python"], "0.37.3"); + assert.equal(Object.keys(emitterJson["devDependencies"]).length, 1); + assert.equal(emitterJson["devDependencies"]["@typespec/compiler"], "~0.64.0"); + assert.isTrue(await doesFileExist(joinPaths(repoRoot, "eng", "emitter-package-lock.json"))); + } catch (error: any) { + assert.fail("Failed to generate tsp-client config files. Error: " + error); + } + }); }); From 63a9bfdebc90b11ed676e30cee06e2e20acc46a8 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Wed, 15 Jan 2025 19:46:27 -0800 Subject: [PATCH 08/11] update example file --- tools/tsp-client/test/examples/package-sdk-pinning.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/tsp-client/test/examples/package-sdk-pinning.json b/tools/tsp-client/test/examples/package-sdk-pinning.json index bde53c84d33..316e2838356 100644 --- a/tools/tsp-client/test/examples/package-sdk-pinning.json +++ b/tools/tsp-client/test/examples/package-sdk-pinning.json @@ -52,7 +52,7 @@ "fs-extra": "~11.2.0" }, "devDependencies": { - "@typespec/compiler": "~0.63.0", + "@typespec/compiler": "~0.64.0", "@typespec/http": "~0.63.0", "@typespec/rest": "~0.63.0", "@typespec/versioning": "~0.63.0", @@ -78,7 +78,6 @@ "@types/fs-extra": "11.0.4" }, "azure-sdk/emitter-package-json-pinning": { - "@typespec/compiler": ">=0.63.0 <1.0.0", - "@typespec/http": ">=0.63.0 <1.0.0" + "@typespec/compiler": ">=0.63.0 <1.0.0" } } From 990791279bd39a8115892a6b523a152884116900 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Thu, 16 Jan 2025 12:10:19 -0800 Subject: [PATCH 09/11] fixes --- tools/tsp-client/src/commands.ts | 2 +- tools/tsp-client/test/examples/package-sdk-pinning.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/tsp-client/src/commands.ts b/tools/tsp-client/src/commands.ts index 19316719ce8..f768d432fd4 100644 --- a/tools/tsp-client/src/commands.ts +++ b/tools/tsp-client/src/commands.ts @@ -437,7 +437,7 @@ export async function generateConfigFilesCommand(argv: any) { const possiblyPinnedPackages: Array = packageJson["azure-sdk/emitter-package-json-pinning"] ?? Object.keys(peerDependencies); - for (const pinnedPackage in possiblyPinnedPackages) { + for (const pinnedPackage of possiblyPinnedPackages) { const pinnedVersion = packageJson["devDependencies"][pinnedPackage]; if (pinnedVersion && !overrideJson[pinnedPackage]) { Logger.info(`Pinning ${pinnedPackage} to ${pinnedVersion}`); diff --git a/tools/tsp-client/test/examples/package-sdk-pinning.json b/tools/tsp-client/test/examples/package-sdk-pinning.json index 316e2838356..2aaa8c853b2 100644 --- a/tools/tsp-client/test/examples/package-sdk-pinning.json +++ b/tools/tsp-client/test/examples/package-sdk-pinning.json @@ -77,7 +77,7 @@ "chalk": "5.3.0", "@types/fs-extra": "11.0.4" }, - "azure-sdk/emitter-package-json-pinning": { - "@typespec/compiler": ">=0.63.0 <1.0.0" - } + "azure-sdk/emitter-package-json-pinning": [ + "@typespec/compiler" + ] } From 77021986ccb6d1c0f789ff038b923e59036fbe32 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Thu, 16 Jan 2025 12:18:28 -0800 Subject: [PATCH 10/11] increase timeout in case npm install takes longer --- tools/tsp-client/test/commands.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/tsp-client/test/commands.spec.ts b/tools/tsp-client/test/commands.spec.ts index e0de0b9f733..46959dcda3d 100644 --- a/tools/tsp-client/test/commands.spec.ts +++ b/tools/tsp-client/test/commands.spec.ts @@ -259,7 +259,7 @@ describe.sequential("Verify commands", () => { } catch (error: any) { assert.fail("Failed to generate tsp-client config files. Error: " + error); } - }); + }, 120000); it("Generate config files with overrides", async () => { try { @@ -280,7 +280,7 @@ describe.sequential("Verify commands", () => { } catch (error: any) { assert.fail("Failed to generate tsp-client config files. Error: " + error); } - }); + }, 120000); it("Generate config files using azure-sdk/emitter-package-json-pinning", async () => { try { @@ -300,5 +300,5 @@ describe.sequential("Verify commands", () => { } catch (error: any) { assert.fail("Failed to generate tsp-client config files. Error: " + error); } - }); + }, 120000); }); From f5a1ba422c0f55de8b217937321cb9b694139f11 Mon Sep 17 00:00:00 2001 From: catalinaperalta Date: Fri, 17 Jan 2025 15:08:22 -0800 Subject: [PATCH 11/11] update readme --- tools/tsp-client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tsp-client/README.md b/tools/tsp-client/README.md index 26dd0c07f03..238da377ab6 100644 --- a/tools/tsp-client/README.md +++ b/tools/tsp-client/README.md @@ -65,7 +65,7 @@ Sort an existing swagger specification to be the same content order with TypeSpe ### generate-config-files -Generate the `emitter-package.json` and `emitter-package-lock.json` used for tsp-client commands under the eng/ directory of your current repository. +Generate the `emitter-package.json` and `emitter-package-lock.json` used for tsp-client commands under the eng/ directory of your current repository. Run this command from the target repository and pass in the path to the package.json file of the emitter you want to use generate the configuration files. ### generate-lock-file