1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/renderer/components/+extensions/attempt-install-by-info/attempt-install-by-info.tsx
Janne Savolainen c92c8f8a11
Replace global state usages of ExtensionLoader with DI
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
2021-12-15 15:37:36 +02:00

124 lines
3.9 KiB
TypeScript

/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { ExtensionInstallationStateStore } from "../extension-install.store";
import { downloadFile, downloadJson, ExtendableDisposer } from "../../../../common/utils";
import { Notifications } from "../../notifications";
import { ConfirmDialog } from "../../confirm-dialog";
import React from "react";
import path from "path";
import { SemVer } from "semver";
import URLParse from "url-parse";
import type { InstallRequest } from "../attempt-install/install-request";
import lodash from "lodash";
export interface ExtensionInfo {
name: string;
version?: string;
requireConfirmation?: boolean;
}
export interface Dependencies {
attemptInstall: (request: InstallRequest, d: ExtendableDisposer) => Promise<void>
}
export const attemptInstallByInfo = ({ attemptInstall }: Dependencies) => async ({
name,
version,
requireConfirmation = false,
}: ExtensionInfo) => {
const disposer = ExtensionInstallationStateStore.startPreInstall();
const registryUrl = new URLParse("https://registry.npmjs.com")
.set("pathname", name)
.toString();
const { promise } = downloadJson({ url: registryUrl });
const json = await promise.catch(console.error);
if (
!json ||
json.error ||
typeof json.versions !== "object" ||
!json.versions
) {
const message = json?.error ? `: ${json.error}` : "";
Notifications.error(
`Failed to get registry information for that extension${message}`,
);
return disposer();
}
if (version) {
if (!json.versions[version]) {
if (json["dist-tags"][version]) {
version = json["dist-tags"][version];
} else {
Notifications.error(
<p>
The <em>{name}</em> extension does not have a version or tag{" "}
<code>{version}</code>.
</p>,
);
return disposer();
}
}
} else {
const versions = Object.keys(json.versions)
.map(
version =>
new SemVer(version, { loose: true, includePrerelease: true }),
)
// ignore pre-releases for auto picking the version
.filter(version => version.prerelease.length === 0);
version = lodash.reduce(versions, (prev, curr) =>
prev.compareMain(curr) === -1 ? curr : prev,
).format();
}
if (requireConfirmation) {
const proceed = await ConfirmDialog.confirm({
message: (
<p>
Are you sure you want to install{" "}
<b>
{name}@{version}
</b>
?
</p>
),
labelCancel: "Cancel",
labelOk: "Install",
});
if (!proceed) {
return disposer();
}
}
const url = json.versions[version].dist.tarball;
const fileName = path.basename(url);
const { promise: dataP } = downloadFile({ url, timeout: 10 * 60 * 1000 });
return attemptInstall({ fileName, dataP }, disposer);
};