@microsoft/kiota
Version:
npm package exposing Kiota CLI functionality to TypeScript
232 lines • 9.61 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureKiotaIsPresent = ensureKiotaIsPresent;
exports.ensureKiotaIsPresentInPath = ensureKiotaIsPresentInPath;
exports.getKiotaPath = getKiotaPath;
exports.getRuntimeDependenciesPackages = getRuntimeDependenciesPackages;
exports.getCurrentPlatform = getCurrentPlatform;
const adm_zip_1 = __importDefault(require("adm-zip"));
const crypto_1 = require("crypto");
const https = __importStar(require("https"));
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const config_1 = require("./config");
const runtime_json_1 = __importDefault(require("./runtime.json"));
const kiotaInstallStatusKey = "kiotaInstallStatus";
const installDelayInMs = 30000; // 30 seconds
const state = {};
let kiotaPath;
const binariesRootDirectory = '.kiotabin';
const baseDownloadUrl = "https://github.com/microsoft/kiota/releases/download";
const windowsPlatform = 'win';
const osxPlatform = 'osx';
const linuxPlatform = 'linux';
/**
* Checks if a file or directory exists asynchronously
* @param filePath Path to check
* @returns Promise<boolean> true if exists, false otherwise
*/
async function checkFileExists(filePath) {
try {
await fs.promises.access(filePath);
return true;
}
catch {
return false;
}
}
/**
* Checks if a directory is empty asynchronously
* @param dirPath Directory path to check
* @returns Promise<boolean> true if directory is empty or doesn't exist, false otherwise
*/
async function isDirectoryEmpty(dirPath) {
try {
const files = await fs.promises.readdir(dirPath);
return files.length === 0;
}
catch {
// If directory doesn't exist, consider it as "empty" for our use case
return true;
}
}
async function runIfNotLocked(action) {
const installStartTimeStamp = state[kiotaInstallStatusKey];
const currentTimeStamp = new Date().getTime();
if (!installStartTimeStamp || (currentTimeStamp - installStartTimeStamp) > installDelayInMs) {
//locking the context to prevent multiple downloads across multiple instances
//overriding after 30 seconds to prevent stale locks
state[kiotaInstallStatusKey] = currentTimeStamp;
try {
await action();
}
finally {
state[kiotaInstallStatusKey] = undefined;
}
}
}
async function ensureKiotaIsPresent() {
const installPath = getKiotaPathInternal(false);
if (installPath) {
const runtimeDependencies = getRuntimeDependenciesPackages();
const currentPlatform = getCurrentPlatform();
await ensureKiotaIsPresentInPath(installPath, runtimeDependencies, currentPlatform);
}
}
async function ensureKiotaIsPresentInPath(installPath, runtimeDependencies, currentPlatform) {
if (installPath) {
if (!await checkFileExists(installPath) || await isDirectoryEmpty(installPath)) {
await runIfNotLocked(async () => {
try {
const packageToInstall = runtimeDependencies.find((p) => p.platformId === currentPlatform);
if (!packageToInstall) {
throw new Error("Could not find package to install");
}
fs.mkdirSync(installPath, { recursive: true });
const zipFilePath = `${installPath}.zip`;
// If env variable that points to kiota binary zip exists, use it to copy the file instead of downloading it
const kiotaBinaryZip = process.env.KIOTA_SIDELOADING_BINARY_ZIP_PATH;
if (kiotaBinaryZip && await checkFileExists(kiotaBinaryZip)) {
fs.copyFileSync(kiotaBinaryZip, zipFilePath);
}
else {
const downloadUrl = getDownloadUrl(currentPlatform);
await downloadFileFromUrl(downloadUrl, zipFilePath);
if (!await doesFileHashMatch(zipFilePath, packageToInstall.sha256)) {
throw new Error("Hash validation of the downloaded file mismatch");
}
}
unzipFile(zipFilePath, installPath);
if ((currentPlatform.startsWith(linuxPlatform) || currentPlatform.startsWith(osxPlatform)) && installPath) {
const fileName = getKiotaFileName();
const kiotaFilePath = path.join(installPath, fileName);
makeExecutable(kiotaFilePath);
}
}
catch (error) {
fs.rmSync(installPath, { recursive: true, force: true });
throw new Error("Kiota download failed. Check the logs for more information.");
}
});
}
}
}
function getKiotaPath() {
if (!kiotaPath) {
kiotaPath = getKiotaPathInternal();
if (!kiotaPath) {
throw new Error("Could not find kiota");
}
}
return kiotaPath;
}
function makeExecutable(path) {
fs.chmodSync(path, 0o755);
}
function getBaseDir() {
return (0, config_1.getKiotaConfig)().binaryLocation || path.resolve(__dirname);
}
function getRuntimeVersion() {
return (0, config_1.getKiotaConfig)().binaryVersion || runtime_json_1.default.kiotaVersion;
}
function getKiotaFileName() {
return process.platform === 'win32' ? 'kiota.exe' : 'kiota';
}
function getKiotaPathInternal(withFileName = true) {
const fileName = getKiotaFileName();
const runtimeDependencies = getRuntimeDependenciesPackages();
const currentPlatform = getCurrentPlatform();
const packageToInstall = runtimeDependencies.find((p) => p.platformId === currentPlatform);
const baseDir = getBaseDir();
const runtimeVersion = getRuntimeVersion();
if (packageToInstall) {
const installPath = path.join(baseDir, binariesRootDirectory);
const directoryPath = path.join(installPath, runtimeVersion, currentPlatform);
if (withFileName) {
return path.join(directoryPath, fileName);
}
return directoryPath;
}
return undefined;
}
function unzipFile(zipFilePath, destinationPath) {
const zip = new adm_zip_1.default(zipFilePath);
zip.extractAllTo(destinationPath, true);
}
async function doesFileHashMatch(destinationPath, hashValue) {
const hash = (0, crypto_1.createHash)('sha256');
return new Promise((resolve, reject) => {
fs.createReadStream(destinationPath).pipe(hash).on('finish', () => {
const computedValue = hash.digest('hex');
hash.destroy();
resolve(computedValue.toUpperCase() === hashValue.toUpperCase());
});
});
}
function downloadFileFromUrl(url, destinationPath) {
return new Promise((resolve) => {
https.get(url, (response) => {
if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
resolve(downloadFileFromUrl(response.headers.location, destinationPath));
}
else {
const filePath = fs.createWriteStream(destinationPath);
response.pipe(filePath);
filePath.on('finish', () => {
filePath.close();
resolve(undefined);
});
}
});
});
}
function getDownloadUrl(platform) {
return `${baseDownloadUrl}/v${getRuntimeVersion()}/${platform}.zip`;
}
function getRuntimeDependenciesPackages() {
if (runtime_json_1.default.runtimeDependencies) {
return JSON.parse(JSON.stringify(runtime_json_1.default.runtimeDependencies));
}
throw new Error("No runtime dependencies found");
}
function getCurrentPlatform() {
const binPathSegmentOS = process.platform === 'win32' ? windowsPlatform : process.platform === 'darwin' ? osxPlatform : linuxPlatform;
return `${binPathSegmentOS}-${process.arch}`;
}
//# sourceMappingURL=install.js.map