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[];
}