diff --git a/.github/workflows/build-vscode-extension.yml b/.github/workflows/build-vscode-extension.yml index dd7e049b60..baefd989c8 100644 --- a/.github/workflows/build-vscode-extension.yml +++ b/.github/workflows/build-vscode-extension.yml @@ -63,6 +63,8 @@ jobs: shell: pwsh - name: Install dependencies + env: + SKIP_POSTINSTALL: "true" run: npm install working-directory: vscode @@ -145,6 +147,8 @@ jobs: shell: pwsh - name: Install dependencies + env: + SKIP_POSTINSTALL: "true" run: npm install working-directory: vscode diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index faed940697..6a5b2d856e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -92,6 +92,8 @@ jobs: - name: Restore dependencies run: dotnet restore - name: Build + env: + SKIP_POSTINSTALL: "true" run: dotnet build --no-restore -c Release - name: Perform CodeQL Analysis diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 3baeda962c..200527adef 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,11 +16,34 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: 9.x + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x - name: Restore dependencies run: dotnet restore kiota.sln - name: Check formatting run: dotnet format --verify-no-changes + - run: | + scripts/get-version-from-csproj.ps1 -isGHA $true -csprojPath "$PWD/src/kiota/kiota.csproj" + name: "Get Kiota's version-number from .csproj" + id: get_version + shell: pwsh + + - run: | + $runtimeFilePath = "./vscode/packages/npm-package/runtime.json" + # decrease the minor version by 1 to avoid issues with binaries that are not published + $versionParts = "${{ steps.get_version.outputs.version }}".Split('.') + $versionParts[1] = [int]$versionParts[1] - 1 + $versionParts = $versionParts -join '.' + $runtimeJson = Get-Content $runtimeFilePath | ConvertFrom-Json + $runtimeJson.kiotaVersion = $versionParts + $runtimeJson | ConvertTo-Json | Set-Content $runtimeFilePath + shell: pwsh + name: "Update runtime.json with Kiota's version for install unit test" - name: Build + env: + SKIP_POSTINSTALL: "true" run: dotnet build kiota.sln --no-restore - name: Test run: dotnet test kiota.sln --no-build --verbosity normal --collect:"XPlat Code Coverage" @@ -37,7 +60,14 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest, windows-11-arm, ubuntu-24.04-arm] + os: + [ + ubuntu-latest, + macos-latest, + windows-latest, + windows-11-arm, + ubuntu-24.04-arm, + ] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index a40b84017b..14e9badeea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added support for calling kiota as npx command. [#6642](https://github.com/microsoft/kiota/issues/6642) + ### Changed ## [1.28.0] - 2025-07-11 @@ -1675,4 +1677,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial GitHub release - diff --git a/kiota.sln b/kiota.sln index 0f9857aaac..f4376c4343 100644 --- a/kiota.sln +++ b/kiota.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30804.86 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35931.197 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "kiota", "src\kiota\kiota.csproj", "{944FCE5E-0CFA-4018-B353-E14FA1395007}" EndProject @@ -19,6 +19,28 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EAAC5CEA-33B EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KiotaGenerated", "src\Kiota.Generated\KiotaGenerated.csproj", "{01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kiota.NPM.IntegrationTests", "tests\Kiota.NPM.IntegrationTests\Kiota.NPM.IntegrationTests.csproj", "{51296EA6-7A4A-2A93-5060-1FBD4CB31CC5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NPMProjects", "NPMProjects", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "npm-package", "vscode\packages\npm-package\npm-package.esproj", "{C6BFB632-723D-238A-EA11-44E78644612E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{099BEFDC-D101-4DB6-B028-E24376B6DC50}" + ProjectSection(SolutionItems) = preProject + .github\workflows\auto-merge-dependabot.yml = .github\workflows\auto-merge-dependabot.yml + .github\workflows\build-vscode-extension.yml = .github\workflows\build-vscode-extension.yml + .github\workflows\check-translations.yml = .github\workflows\check-translations.yml + .github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml + .github\workflows\codeql-required-workaround.yml = .github\workflows\codeql-required-workaround.yml + .github\workflows\dotnet-required-workaround.yml = .github\workflows\dotnet-required-workaround.yml + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml + .github\workflows\idempotency-tests.yml = .github\workflows\idempotency-tests.yml + .github\workflows\integration-tests.yml = .github\workflows\integration-tests.yml + .github\workflows\load-tests.yml = .github\workflows\load-tests.yml + .github\workflows\project-auto-add.yml = .github\workflows\project-auto-add.yml + .github\workflows\sonarcloud.yml = .github\workflows\sonarcloud.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,15 +71,32 @@ Global {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Release|Any CPU.Build.0 = Release|Any CPU + {51296EA6-7A4A-2A93-5060-1FBD4CB31CC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51296EA6-7A4A-2A93-5060-1FBD4CB31CC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51296EA6-7A4A-2A93-5060-1FBD4CB31CC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51296EA6-7A4A-2A93-5060-1FBD4CB31CC5}.Release|Any CPU.Build.0 = Release|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Release|Any CPU.Build.0 = Release|Any CPU + {C6BFB632-723D-238A-EA11-44E78644612E}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {85C3AE3B-2D83-4457-B2F9-E56D64F4E443} - EndGlobalSection GlobalSection(NestedProjects) = preSolution + {944FCE5E-0CFA-4018-B353-E14FA1395007} = {EAAC5CEA-33B8-495D-9CD0-B36794B8AFE7} + {1F5FC53F-061A-4CED-8B53-FC5C63DBEBFF} = {EAAC5CEA-33B8-495D-9CD0-B36794B8AFE7} + {A2B2F620-BC5D-47EA-8B98-5A942EC9CA9A} = {2DF34BB8-B19F-4623-9E3D-9F59A14C0660} + {019E5612-7663-40A2-A2EA-46E39D31F0A2} = {2DF34BB8-B19F-4623-9E3D-9F59A14C0660} {E4C108A5-A13F-4C3F-B32A-86210A4EC52A} = {2DF34BB8-B19F-4623-9E3D-9F59A14C0660} {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8} = {EAAC5CEA-33B8-495D-9CD0-B36794B8AFE7} + {51296EA6-7A4A-2A93-5060-1FBD4CB31CC5} = {2DF34BB8-B19F-4623-9E3D-9F59A14C0660} + {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {EAAC5CEA-33B8-495D-9CD0-B36794B8AFE7} + {C6BFB632-723D-238A-EA11-44E78644612E} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {85C3AE3B-2D83-4457-B2F9-E56D64F4E443} EndGlobalSection EndGlobal diff --git a/tests/Kiota.NPM.IntegrationTests/.runsettings b/tests/Kiota.NPM.IntegrationTests/.runsettings new file mode 100644 index 0000000000..feaf6cde62 --- /dev/null +++ b/tests/Kiota.NPM.IntegrationTests/.runsettings @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/tests/Kiota.NPM.IntegrationTests/Assets/package.json b/tests/Kiota.NPM.IntegrationTests/Assets/package.json new file mode 100644 index 0000000000..8a99d48358 --- /dev/null +++ b/tests/Kiota.NPM.IntegrationTests/Assets/package.json @@ -0,0 +1,13 @@ +{ + "name": "kiota-consumer", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT", + "dependencies": { + "@microsoft/kiota": "file:./microsoft-kiota-1.0.0.tgz" + } +} diff --git a/tests/Kiota.NPM.IntegrationTests/InstallTests.cs b/tests/Kiota.NPM.IntegrationTests/InstallTests.cs new file mode 100644 index 0000000000..a1875ef22c --- /dev/null +++ b/tests/Kiota.NPM.IntegrationTests/InstallTests.cs @@ -0,0 +1,245 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text.Json; +using System.Text.Json.Nodes; +using Xunit; +using Xunit.Abstractions; + + +namespace Kiota.NPM.IntegrationTests; + +public class InstallTests +{ + private readonly ITestOutputHelper _outputHelper; + + public InstallTests(ITestOutputHelper outputHelper) + { + _outputHelper = outputHelper ?? throw new ArgumentNullException(nameof(outputHelper)); + } + private string FindFileFromWildCard(string path) + { + if (path.Contains('*')) + { + var directory = Path.GetDirectoryName(path); + if (directory != null && Directory.Exists(directory.Replace("*", ""))) + { + // Get the highest version directory + var dirs = Directory.GetDirectories(directory.Replace("*", "")); + if (dirs.Length > 0) + { + var exactPath = Path.Combine(dirs[^1], Path.GetFileName(path)); + if (File.Exists(exactPath)) + { + _outputHelper.WriteLine($"Found {Path.GetFileName(path)} at {exactPath}"); + return exactPath; + } + } + } + } + return null; + } + + [Fact] + public void Install_Creates_Working_Bin_Command() + { + // This test first compiles then packs the Kiota project to a local folder created for + // the individual test run, such that there is a tarball waiting in the folder. + // Then it copies the package.json file from the Assets folder to the test folder. + // Then it runs npm install in the test folder. + // Finally, it asserts two things: + // Firstly, if the kiota command is available in the node_modules/.bin folder. + // Secondly, if the npx command can be used to run the kiota command successfully + // with the '--version' command line option which must successfully return a string which conforms to a pattern expressing the version of kiota. + + // Create a temporary directory for the test + var testDir = Path.Combine(Path.GetTempPath(), $"kiota-npm-test-{Guid.NewGuid()}"); + Directory.CreateDirectory(testDir); + + try + { + // Pack the project using npm + var projectDir = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../vscode/packages/npm-package")); + _outputHelper.WriteLine($"Running pack in {projectDir}"); + var npmPackProcess = RunProcess("npm", $"pack --pack-destination {testDir}", projectDir); + _outputHelper.WriteLine("Checking if npm pack process exited successfully."); + Assert.Equal(0, npmPackProcess.exitCode); + + // get package version from the package.json + var packageJsonPath = Path.Combine(projectDir, "package.json"); + _outputHelper.WriteLine($"Reading package.json from {packageJsonPath}"); + var packageJson = File.ReadAllText(packageJsonPath); + var packageVersion = JsonNode.Parse(packageJson).AsObject().TryGetPropertyValue("version", out var versionNode) ? versionNode.GetValue() : null; + _outputHelper.WriteLine($"Found package version: {packageVersion}"); + + // Copy package.json from Assets folder to test directory + var assetsDir = Path.Combine(AppContext.BaseDirectory, "../../../Assets"); + var packageJsonTestPath = Path.Combine(testDir, "package.json"); + File.Copy(Path.Combine(assetsDir, "package.json"), packageJsonTestPath); + + // Update package.json with the correct version + _outputHelper.WriteLine($"Updating package.json at {packageJsonTestPath} with version {packageVersion}"); + var packageJsonTest = File.ReadAllText(packageJsonTestPath); + var packageJsonNode = JsonNode.Parse(packageJsonTest).AsObject(); + var dependencies = packageJsonNode["dependencies"].AsObject(); + dependencies["@microsoft/kiota"] = $"file:./microsoft-kiota-{packageVersion}.tgz"; // Set the kiota dependency to the version from the packed tarball + var serializedPackageJson = packageJsonNode.ToJsonString(new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllText(packageJsonTestPath, serializedPackageJson); + + // Run npm install in the test directory + var npmProcess = RunProcess("npm", "install", testDir); + _outputHelper.WriteLine("Checking if npm install process exited successfully."); + Assert.Equal(0, npmProcess.exitCode); + + // Assert 1: Check if kiota exists in node_modules/.bin + var kiotaPath = Path.Combine(testDir, "node_modules", ".bin", "kiota"); + if (OperatingSystem.IsWindows()) + { + kiotaPath += ".cmd"; // On Windows, the bin command is a .cmd file + } + _outputHelper.WriteLine($"Checking if Kiota command exists at {kiotaPath}."); + Assert.True(File.Exists(kiotaPath), $"Kiota command not found at {kiotaPath}"); + + // Assert 2: Run kiota --version using npx and check output + var npxProcess = RunProcess("npx", "kiota --version", testDir); + _outputHelper.WriteLine("Checking if npx process to run 'kiota --version' exited successfully."); + Assert.Equal(0, npxProcess.exitCode); + + // Check if output matches version pattern (e.g., 1.2.3 or 1.2.3-preview.4) + var versionPattern = @"^\d+\.\d+\.\d+.*$"; + _outputHelper.WriteLine("Checking if the output of 'kiota --version' matches the expected version pattern."); + Assert.Matches(versionPattern, npxProcess.output); + } + finally + { + // Clean up + try + { + Directory.Delete(testDir, true); + } + catch + { + // Best effort cleanup + } + } + } + + private (int exitCode, string output) RunProcess(string fileName, string arguments, string workingDirectory) + { + // Try to find npm or npx in standard locations if not found directly + if ((fileName == "npm" || fileName == "npx") && OperatingSystem.IsWindows()) + { + // Check common locations for npm/npx on Windows + string commandExtension = ".cmd"; + string[] possiblePaths = new[] + { + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "nodejs", $"{fileName}{commandExtension}"), + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "nodejs", $"{fileName}{commandExtension}"), + // Add from npm global prefix + Path.Combine(Environment.GetEnvironmentVariable("APPDATA") ?? "", "npm", $"{fileName}{commandExtension}"), + // Try npm global installation path + Path.Combine(Environment.GetEnvironmentVariable("APPDATA") ?? "", "npm", "node_modules", "npm", "bin", $"{fileName}{commandExtension}"), + // Check nvm installation if available + Path.Combine(Environment.GetEnvironmentVariable("NVM_HOME") ?? "", "*", $"{fileName}{commandExtension}"), + + }; + + foreach (var path in possiblePaths) + { + // Handle wildcard paths (for nvm) + if (FindFileFromWildCard(path) is string foundPath && !string.IsNullOrEmpty(foundPath)) + { + _outputHelper.WriteLine($"Found {fileName} at {foundPath}"); + fileName = foundPath; + break; + } + + if (File.Exists(path)) + { + _outputHelper.WriteLine($"Found {fileName} at {path}"); + fileName = path; + break; + } + } + } + else if ((fileName == "npm" || fileName == "npx") && (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())) + { + // Check common locations for npm/npx on Linux/macOS + string[] possiblePaths = new[] + { + $"/usr/bin/{fileName}", + $"/usr/local/bin/{fileName}", + $"/opt/homebrew/bin/{fileName}", // Common on macOS with Homebrew + $"{Environment.GetEnvironmentVariable("HOME")}/.npm/bin/{fileName}", // User's npm bin directory + $"{Environment.GetEnvironmentVariable("HOME")}/.nvm/versions/node/*/bin/{fileName}" // nvm installations + }; + + foreach (var path in possiblePaths) + { + // Handle wildcard paths (for nvm) + if (FindFileFromWildCard(path) is string foundPath && !string.IsNullOrEmpty(foundPath)) + { + _outputHelper.WriteLine($"Found {fileName} at {foundPath}"); + fileName = foundPath; + break; + } + + if (File.Exists(path)) + { + _outputHelper.WriteLine($"Found {fileName} at {path}"); + fileName = path; + break; + } + } + } + + // Fall back to PATH environment if still using the short name + if (fileName == "npm" || fileName == "npx") + { + // Log that we're using PATH resolution + _outputHelper.WriteLine($"Using PATH environment to resolve {fileName}"); + } + + using (var process = new Process()) + { + process.StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = arguments, + WorkingDirectory = workingDirectory, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + var outputBuilder = new StringWriter(); + + process.OutputDataReceived += (sender, args) => + { + if (args.Data != null) + { + outputBuilder.WriteLine(args.Data); + } + }; + + process.ErrorDataReceived += (sender, args) => + { + if (args.Data != null) + { + outputBuilder.WriteLine($"Error: {args.Data}"); + } + }; + + if (!process.Start()) + { + throw new InvalidOperationException($"Failed to start process '{fileName}' in directory '{workingDirectory}'"); + } + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + process.WaitForExit(); + return (process.ExitCode, outputBuilder.ToString().Trim()); + } + } +} diff --git a/tests/Kiota.NPM.IntegrationTests/Kiota.NPM.IntegrationTests.csproj b/tests/Kiota.NPM.IntegrationTests/Kiota.NPM.IntegrationTests.csproj new file mode 100644 index 0000000000..42a5b8d5d7 --- /dev/null +++ b/tests/Kiota.NPM.IntegrationTests/Kiota.NPM.IntegrationTests.csproj @@ -0,0 +1,19 @@ + + + + net9.0 + + false + true + ..\..\src\Microsoft.OpenApi.snk + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + \ No newline at end of file diff --git a/vscode/.gitignore b/vscode/.gitignore index 4e7c8d73fa..4bbbb06946 100644 --- a/vscode/.gitignore +++ b/vscode/.gitignore @@ -1,8 +1,9 @@ node_modules/ .kiota .kiotabin +*.tgz !packages/**/* packages/*/node_modules/ packages/*/dist/ packages/npm-package/.kiotabin/ -packages/npm-package/.kiota/ \ No newline at end of file +packages/npm-package/.kiota/ diff --git a/vscode/packages/npm-package/eslint.config.mjs b/vscode/packages/npm-package/eslint.config.mjs index c9f39933e1..06768032eb 100644 --- a/vscode/packages/npm-package/eslint.config.mjs +++ b/vscode/packages/npm-package/eslint.config.mjs @@ -1,4 +1,4 @@ -import stylisticTs from '@stylistic/eslint-plugin-ts'; +import stylisticTs from '@stylistic/eslint-plugin'; import typescriptEslint from "@typescript-eslint/eslint-plugin"; import tsParser from "@typescript-eslint/parser"; diff --git a/vscode/packages/npm-package/install.ts b/vscode/packages/npm-package/install.ts index 2a87650667..09d7e7f08b 100644 --- a/vscode/packages/npm-package/install.ts +++ b/vscode/packages/npm-package/install.ts @@ -95,7 +95,7 @@ export async function ensureKiotaIsPresentInPath(installPath: string, runtimeDep } else { const downloadUrl = getDownloadUrl(currentPlatform); await downloadFileFromUrl(downloadUrl, zipFilePath); - if (!await doesFileHashMatch(zipFilePath, packageToInstall.sha256)) { + if (packageToInstall.sha256 !== "0000000000000000000000000000000000000000000000000000000000000000" && !await doesFileHashMatch(zipFilePath, packageToInstall.sha256)) { throw new Error("Hash validation of the downloaded file mismatch"); } } @@ -106,7 +106,7 @@ export async function ensureKiotaIsPresentInPath(installPath: string, runtimeDep makeExecutable(kiotaFilePath); } } catch (error) { - fs.rmdirSync(installPath, { recursive: true }); + fs.rmSync(installPath, { recursive: true }); throw new Error("Kiota download failed. Check the logs for more information."); } }); diff --git a/vscode/packages/npm-package/npm-package.esproj b/vscode/packages/npm-package/npm-package.esproj new file mode 100644 index 0000000000..9372ce1a3f --- /dev/null +++ b/vscode/packages/npm-package/npm-package.esproj @@ -0,0 +1,14 @@ + + + + true + + + + npm pack + + true + tests\ + Jest + + \ No newline at end of file diff --git a/vscode/packages/npm-package/package.json b/vscode/packages/npm-package/package.json index 8526c2eae5..a10e6ae2cc 100644 --- a/vscode/packages/npm-package/package.json +++ b/vscode/packages/npm-package/package.json @@ -22,6 +22,9 @@ "default": "./dist/cjs/index.js" } }, + "bin": { + "kiota": "./scripts/cli.js" + }, "types": "dist/esm/types/index.d.ts", "typesVersions": { "*": { @@ -35,7 +38,8 @@ }, "files": [ "dist", - "runtime.json" + "runtime.json", + "scripts" ], "scripts": { "lint": "eslint", @@ -50,7 +54,8 @@ "generate-readme": "node scripts/generate-readme.js", "test:coverage": "jest --coverage --runInBand", "prepack": "npm run build", - "package": "npm pack" + "package": "npm pack", + "postinstall": "node scripts/bootstrap.js" }, "keywords": [ "Kiota" @@ -66,10 +71,14 @@ "devDependencies": { "@types/adm-zip": "^0.5.7", "@types/jest": "^30.0.0", + "eslint": "^9.24.0", + "@stylistic/eslint-plugin": "^4.2.0", + "@typescript-eslint/eslint-plugin": "^8.29.1", "glob": "^11.0.3", "jest": "^30.0.4", + "jest-editor-support": "^32.0.0-beta.1", "rimraf": "^6.0.1", "ts-jest": "^29.3.1", "ts-loader": "^9.5.2" } -} +} \ No newline at end of file diff --git a/vscode/packages/npm-package/readme.md b/vscode/packages/npm-package/readme.md index 80998d83e9..0b153bd5ac 100644 --- a/vscode/packages/npm-package/readme.md +++ b/vscode/packages/npm-package/readme.md @@ -11,6 +11,7 @@ npm install @microsoft/kiota ``` ## Usage +The following JS/TS functions are made available. Once installed, you can use the available functions to generate and interact with Kiota clients. Below is a reference for each function, including parameters and return values. diff --git a/vscode/packages/npm-package/scripts/bootstrap.js b/vscode/packages/npm-package/scripts/bootstrap.js new file mode 100644 index 0000000000..4944479001 --- /dev/null +++ b/vscode/packages/npm-package/scripts/bootstrap.js @@ -0,0 +1,14 @@ +if (process.env.SKIP_POSTINSTALL === 'true') { + process.exit(0); +} + +const { getKiotaVersion } = require('../dist/cjs/lib/getKiotaVersion.js'); + +(async () => { + try { + const result = await getKiotaVersion(); + console.log(`Kiota version ${result} installed successfully!`); + } catch (error) { + console.error("An error occurred while bootstrapping Kiota.", error); + } +})(); \ No newline at end of file diff --git a/vscode/packages/npm-package/scripts/cli.js b/vscode/packages/npm-package/scripts/cli.js new file mode 100644 index 0000000000..4fb1662080 --- /dev/null +++ b/vscode/packages/npm-package/scripts/cli.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node +const { execFileSync } = require('child_process'); +const { getKiotaPath } = require('../dist/cjs/install.js'); + +const binaryPath = getKiotaPath(); + +try { + execFileSync(binaryPath, process.argv.slice(2), { stdio: 'inherit' }); +} catch (err) { + if (err.code === 'ENOENT') { + console.error(`Error: Unable to find the specified executable ${binaryPath}.`); + } else { + console.error(`Error: ${err.message}`); + } + process.exit(1); // Exit with a failure code +} diff --git a/vscode/packages/npm-package/tsconfig.json b/vscode/packages/npm-package/tsconfig.json index 9f89f94649..e21536675d 100644 --- a/vscode/packages/npm-package/tsconfig.json +++ b/vscode/packages/npm-package/tsconfig.json @@ -18,7 +18,7 @@ "resolveJsonModule": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, - "skipLibCheck": true, + "skipLibCheck": true }, "exclude": [ "dist", diff --git a/vscode/packages/npm-package/types.ts b/vscode/packages/npm-package/types.ts index eaed5534a9..6e99879189 100644 --- a/vscode/packages/npm-package/types.ts +++ b/vscode/packages/npm-package/types.ts @@ -34,11 +34,16 @@ export interface KiotaLogEntry { } export enum OpenApiAuthType { - None = 0, - ApiKey = 1, - Http = 2, - OAuth2 = 3, - OpenIdConnect = 4, + // eslint-disable-next-line @typescript-eslint/naming-convention + None = 0, + // eslint-disable-next-line @typescript-eslint/naming-convention + ApiKey = 1, + // eslint-disable-next-line @typescript-eslint/naming-convention + Http = 2, + // eslint-disable-next-line @typescript-eslint/naming-convention + OAuth2 = 3, + // eslint-disable-next-line @typescript-eslint/naming-convention + OpenIdConnect = 4, } // key is the security scheme name, value is array of scopes @@ -309,7 +314,9 @@ export interface GeneratePluginResult extends KiotaResult { export interface PluginManifestResult extends KiotaResult { isValid: boolean; + // eslint-disable-next-line @typescript-eslint/naming-convention schema_version: string; + // eslint-disable-next-line @typescript-eslint/naming-convention name_for_human: string; functions: PluginFunction[]; runtime: PluginRuntime[]; @@ -328,6 +335,7 @@ export interface PluginAuth { export interface PluginRuntime { type: string; auth: PluginAuth; + // eslint-disable-next-line @typescript-eslint/naming-convention run_for_functions: string[]; }