/** * 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 moment from "moment-timezone"; import path from "path"; import os from "os"; import { ThemeStore } from "../../renderer/theme.store"; import { getAppVersion, ObservableToggleSet } from "../utils"; import type { editor } from "monaco-editor"; import merge from "lodash/merge"; import { SemVer } from "semver"; export interface KubeconfigSyncEntry extends KubeconfigSyncValue { filePath: string; } export interface KubeconfigSyncValue { } export type EditorConfiguration = Pick; export const defaultEditorConfig: EditorConfiguration = { tabSize: 2, lineNumbers: "on", minimap: { enabled: true, side: "right", }, }; interface PreferenceDescription { fromStore(val: T | undefined): R; toStore(val: R): T | undefined; } const httpsProxy: PreferenceDescription = { fromStore(val) { return val; }, toStore(val) { return val || undefined; }, }; const shell: PreferenceDescription = { fromStore(val) { return val; }, toStore(val) { return val || undefined; }, }; const colorTheme: PreferenceDescription = { fromStore(val) { return val || ThemeStore.defaultTheme; }, toStore(val) { if (!val || val === ThemeStore.defaultTheme) { return undefined; } return val; }, }; const localeTimezone: PreferenceDescription = { fromStore(val) { return val || moment.tz.guess(true) || "UTC"; }, toStore(val) { if (!val || val === moment.tz.guess(true) || val === "UTC") { return undefined; } return val; }, }; const allowUntrustedCAs: PreferenceDescription = { fromStore(val) { return val ?? false; }, toStore(val) { if (!val) { return undefined; } return val; }, }; const allowTelemetry: PreferenceDescription = { fromStore(val) { return val ?? true; }, toStore(val) { if (val === true) { return undefined; } return val; }, }; const allowErrorReporting: PreferenceDescription = { fromStore(val) { return val ?? true; }, toStore(val) { if (val === true) { return undefined; } return val; }, }; export interface DownloadMirror { url: string; label: string; platforms: Set; } export const defaultPackageMirror = "default"; export const packageMirrors = new Map([ [defaultPackageMirror, { url: "https://storage.googleapis.com/kubernetes-release/release", label: "Default (Google)", platforms: new Set(["darwin", "win32", "linux"]), }], ["china", { url: "https://mirror.azure.cn/kubernetes/kubectl", label: "China (Azure)", platforms: new Set(["win32", "linux"]), }], ]); const downloadMirror: PreferenceDescription = { fromStore(val) { return packageMirrors.has(val) ? val : defaultPackageMirror; }, toStore(val) { if (!val || val === defaultPackageMirror) { return undefined; } return val; }, }; const downloadKubectlBinaries: PreferenceDescription = { fromStore(val) { return val ?? true; }, toStore(val) { if (val === true) { return undefined; } return val; }, }; const downloadBinariesPath: PreferenceDescription = { fromStore(val) { return val; }, toStore(val) { if (!val) { return undefined; } return val; }, }; const kubectlBinariesPath: PreferenceDescription = { fromStore(val) { return val; }, toStore(val) { if (!val) { return undefined; } return val; }, }; const openAtLogin: PreferenceDescription = { fromStore(val) { return val ?? false; }, toStore(val) { if (!val) { return undefined; } return val; }, }; const terminalCopyOnSelect: PreferenceDescription = { fromStore(val) { return val ?? false; }, toStore(val) { if (!val) { return undefined; } return val; }, }; const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map>> = { fromStore(val) { return new Map( (val ?? []).map(([tableId, columnIds]) => [tableId, new ObservableToggleSet(columnIds)]), ); }, toStore(val) { const res: [string, string[]][] = []; for (const [table, columns] of val) { if (columns.size) { res.push([table, Array.from(columns)]); } } return res.length ? res : undefined; }, }; const mainKubeFolder = path.join(os.homedir(), ".kube"); const syncKubeconfigEntries: PreferenceDescription> = { fromStore(val) { return new Map( val ?.map(({ filePath, ...rest }) => [filePath, rest]) ?? [[mainKubeFolder, {}]], ); }, toStore(val) { if (val.size === 1 && val.has(mainKubeFolder)) { return undefined; } return Array.from(val, ([filePath, rest]) => ({ filePath, ...rest })); }, }; const editorConfiguration: PreferenceDescription = { fromStore(val) { return merge(defaultEditorConfig, val); }, toStore(val) { return val; }, }; const updateChannels = new Map([ ["latest", { label: "Stable", }], ["beta", { label: "Beta", }], ["alpha", { label: "Alpha", }], ]); const defaultUpdateChannel = new SemVer(getAppVersion()).prerelease[0]?.toString() || "latest"; const updateChannel: PreferenceDescription = { fromStore(val) { return updateChannels.has(val) ? val : defaultUpdateChannel; }, toStore(val) { if (!updateChannels.has(val) || val === defaultUpdateChannel) { return undefined; } return val; }, }; export enum ExtensionRegistryLocation { DEFAULT = "default", NPMRC = "npmrc", CUSTOM = "custom", } export type ExtensionRegistry = { location: ExtensionRegistryLocation.DEFAULT | ExtensionRegistryLocation.NPMRC; customUrl?: undefined; } | { location: ExtensionRegistryLocation.CUSTOM, customUrl: string; }; export const defaultExtensionRegistryUrl = "https://registry.npmjs.org"; const extensionRegistryUrl: PreferenceDescription = { fromStore(val) { return val ?? { location: ExtensionRegistryLocation.DEFAULT, }; }, toStore(val) { if (val.location === ExtensionRegistryLocation.DEFAULT) { return undefined; } return val; }, }; type PreferencesModelType = typeof DESCRIPTORS[field] extends PreferenceDescription ? T : never; type UserStoreModelType = typeof DESCRIPTORS[field] extends PreferenceDescription ? T : never; export type UserStoreFlatModel = { [field in keyof typeof DESCRIPTORS]: UserStoreModelType; }; export type UserPreferencesModel = { [field in keyof typeof DESCRIPTORS]: PreferencesModelType; }; export const DESCRIPTORS = { httpsProxy, shell, colorTheme, localeTimezone, allowUntrustedCAs, allowTelemetry, allowErrorReporting, downloadMirror, downloadKubectlBinaries, downloadBinariesPath, kubectlBinariesPath, openAtLogin, hiddenTableColumns, syncKubeconfigEntries, editorConfiguration, terminalCopyOnSelect, updateChannel, extensionRegistryUrl, }; export const CONSTANTS = { updateChannels, };