Restructure to monorepo (#6907)

* wip: restructure to monorepo

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* refactor create-release-pr to a package

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* build fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* github workflow fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix typo

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* add webpack-env types to core

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix github workflows

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* refactor/fix integration tests

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* lint fix

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* yarn run dev

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* eslint settings for vscode

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* move templates to right package

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* open-lens build fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* integration test fix

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix nx task dependencies

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* use bash shell for unit tests in test workflow

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix test:unit for windows

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix win-ca webpack error in open-lens

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix win-ca webpack error in open-lens

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix build:app on windows

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remove ELECTRON_BUILDER_EXTRA_ARGS

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* sync src/ from master

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remove Makefile from core

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen authored and GitHub committed 2023-01-24 10:46:26 -08:00
1 parent 0066ca4ea2
commit 2657df2293
3321 files changed
+28699 -11447

No files matched your search

@@ -0,0 +1,9 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../test-utils/get-global-override";
import currentTimezoneInjectable from "./current-timezone.injectable";
export default getGlobalOverride(currentTimezoneInjectable, () => "Etc/GMT");
@@ -0,0 +1,14 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import moment from "moment-timezone";
const currentTimezoneInjectable = getInjectable({
id: "current-timezone",
instantiate: () => moment.tz.guess(true),
causesSideEffects: true,
});
export default currentTimezoneInjectable;
@@ -0,0 +1,9 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../test-utils/get-global-override";
import userStoreFileNameMigrationInjectable from "./file-name-migration.injectable";
export default getGlobalOverride(userStoreFileNameMigrationInjectable, () => async () => {});
@@ -0,0 +1,41 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import fse from "fs-extra";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { isErrnoException } from "../utils";
import { getInjectable } from "@ogre-tools/injectable";
import joinPathsInjectable from "../path/join-paths.injectable";
export type UserStoreFileNameMigration = () => Promise<void>;
const userStoreFileNameMigrationInjectable = getInjectable({
id: "user-store-file-name-migration",
instantiate: (di): UserStoreFileNameMigration => {
const userDataPath = di.inject(directoryForUserDataInjectable);
const joinPaths = di.inject(joinPathsInjectable);
const configJsonPath = joinPaths(userDataPath, "config.json");
const lensUserStoreJsonPath = joinPaths(userDataPath, "lens-user-store.json");
return async () => {
try {
await fse.move(configJsonPath, lensUserStoreJsonPath);
} catch (error) {
if (error instanceof Error && error.message === "dest already exists.") {
await fse.remove(configJsonPath);
} else if (isErrnoException(error) && error.code === "ENOENT" && error.path === configJsonPath) {
// (No such file or directory)
return; // file already moved
} else {
// pass other errors along
throw error;
}
}
};
},
causesSideEffects: true,
});
export default userStoreFileNameMigrationInjectable;
@@ -0,0 +1,18 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
const httpsProxyConfigurationInjectable = getInjectable({
id: "https-proxy-configuration",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
return computed(() => userStore.httpsProxy);
},
});
export default httpsProxyConfigurationInjectable;
@@ -0,0 +1,7 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export * from "./user-store";
export type { KubeconfigSyncEntry, KubeconfigSyncValue, UserPreferencesModel } from "./preferences-helpers";
@@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import userStoreInjectable from "./user-store.injectable";
const kubeconfigSyncsInjectable = getInjectable({
id: "kubeconfig-syncs",
instantiate: (di) => di.inject(userStoreInjectable).syncKubeconfigEntries,
});
export default kubeconfigSyncsInjectable;
@@ -0,0 +1,37 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
export type LensColorThemePreference = {
useSystemTheme: true;
} | {
useSystemTheme: false;
lensThemeId: string;
};
const lensColorThemePreferenceInjectable = getInjectable({
id: "lens-color-theme-preference",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
return computed((): LensColorThemePreference => {
// TODO: remove magic strings
if (userStore.colorTheme === "system") {
return {
useSystemTheme: true,
};
}
return {
useSystemTheme: false,
lensThemeId: userStore.colorTheme,
};
});
},
});
export default lensColorThemePreferenceInjectable;
@@ -0,0 +1,11 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { MigrationDeclaration } from "../base-store/migrations.injectable";
export const userStoreMigrationInjectionToken = getInjectionToken<MigrationDeclaration>({
id: "user-store-migration-token",
});
@@ -0,0 +1,143 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { merge } from "lodash";
import type { ObservableMap } from "mobx";
import { observable } from "mobx";
import homeDirectoryPathInjectable from "../os/home-directory-path.injectable";
import joinPathsInjectable from "../path/join-paths.injectable";
import { defaultThemeId } from "../vars";
import currentTimezoneInjectable from "./current-timezone.injectable";
import type { EditorConfiguration, ExtensionRegistry, KubeconfigSyncEntry, KubeconfigSyncValue, TerminalConfig } from "./preferences-helpers";
import { defaultExtensionRegistryUrlLocation, defaultEditorConfig, defaultTerminalConfig, defaultPackageMirror, getPreferenceDescriptor, packageMirrors } from "./preferences-helpers";
export type PreferenceDescriptors = ReturnType<typeof userStorePreferenceDescriptorsInjectable["instantiate"]>;
const userStorePreferenceDescriptorsInjectable = getInjectable({
id: "user-store-preference-descriptors",
instantiate: (di) => {
const currentTimezone = di.inject(currentTimezoneInjectable);
const joinPaths = di.inject(joinPathsInjectable);
const homeDirectoryPath = di.inject(homeDirectoryPathInjectable);
const mainKubeFolderPath = joinPaths(homeDirectoryPath, ".kube");
return ({
httpsProxy: getPreferenceDescriptor<string | undefined>({
fromStore: val => val,
toStore: val => val || undefined,
}),
shell: getPreferenceDescriptor<string | undefined>({
fromStore: val => val,
toStore: val => val || undefined,
}),
colorTheme: getPreferenceDescriptor<string>({
fromStore: val => val || defaultThemeId,
toStore: val => !val || val === defaultThemeId
? undefined
: val,
}),
terminalTheme: getPreferenceDescriptor<string>({
fromStore: val => val || "",
toStore: val => val || undefined,
}),
localeTimezone: getPreferenceDescriptor<string>({
fromStore: val => val || currentTimezone,
toStore: val => !val || val === currentTimezone
? undefined
: val,
}),
allowUntrustedCAs: getPreferenceDescriptor<boolean>({
fromStore: val => val ?? false,
toStore: val => !val
? undefined
: val,
}),
allowErrorReporting: getPreferenceDescriptor<boolean>({
fromStore: val => val ?? true,
toStore: val => val
? undefined
: val,
}),
downloadMirror: getPreferenceDescriptor<string>({
fromStore: val => !val || !packageMirrors.has(val)
? defaultPackageMirror
: val,
toStore: val => val === defaultPackageMirror
? undefined
: val,
}),
downloadKubectlBinaries: getPreferenceDescriptor<boolean>({
fromStore: val => val ?? true,
toStore: val => val
? undefined
: val,
}),
downloadBinariesPath: getPreferenceDescriptor<string | undefined>({
fromStore: val => val,
toStore: val => val || undefined,
}),
kubectlBinariesPath: getPreferenceDescriptor<string | undefined>({
fromStore: val => val,
toStore: val => val || undefined,
}),
openAtLogin: getPreferenceDescriptor<boolean>({
fromStore: val => val ?? false,
toStore: val => !val
? undefined
: val,
}),
terminalCopyOnSelect: getPreferenceDescriptor<boolean>({
fromStore: val => val ?? false,
toStore: val => !val
? undefined
: val,
}),
hiddenTableColumns: getPreferenceDescriptor<[string, string[]][], Map<string, Set<string>>>({
fromStore: (val = []) => new Map(
val.map(([tableId, columnIds]) => [tableId, new Set(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;
},
}),
syncKubeconfigEntries: getPreferenceDescriptor<KubeconfigSyncEntry[], ObservableMap<string, KubeconfigSyncValue>>({
fromStore: val => observable.map(
val?.map(({ filePath, ...rest }) => [filePath, rest])
?? [[mainKubeFolderPath, {}]],
),
toStore: val => val.size === 1 && val.has(mainKubeFolderPath)
? undefined
: Array.from(val, ([filePath, rest]) => ({ filePath, ...rest })),
}),
editorConfiguration: getPreferenceDescriptor<Partial<EditorConfiguration>, EditorConfiguration>({
fromStore: val => merge(defaultEditorConfig, val),
toStore: val => val,
}),
terminalConfig: getPreferenceDescriptor<Partial<TerminalConfig>, TerminalConfig>({
fromStore: val => merge(defaultTerminalConfig, val),
toStore: val => val,
}),
extensionRegistryUrl: getPreferenceDescriptor<ExtensionRegistry>({
fromStore: val => val ?? {
location: defaultExtensionRegistryUrlLocation,
},
toStore: val => val.location === defaultExtensionRegistryUrlLocation
? undefined
: val,
}),
}) as const;
},
});
export default userStorePreferenceDescriptorsInjectable;
@@ -0,0 +1,99 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { editor } from "monaco-editor";
import { defaultEditorFontFamily, defaultFontSize, defaultTerminalFontFamily } from "../vars";
import type { PreferenceDescriptors } from "./preference-descriptors.injectable";
export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
filePath: string;
}
export interface KubeconfigSyncValue {
}
export interface TerminalConfig {
fontSize: number;
fontFamily: string;
}
export const defaultTerminalConfig: TerminalConfig = {
fontSize: defaultFontSize,
fontFamily: defaultTerminalFontFamily,
};
interface BaseEditorConfiguration extends Required<Pick<editor.IStandaloneEditorConstructionOptions, "minimap" | "tabSize" | "fontSize" | "fontFamily">> {
lineNumbers: NonNullable<Exclude<editor.IStandaloneEditorConstructionOptions["lineNumbers"], Function>>;
}
export type EditorConfiguration = Required<BaseEditorConfiguration>;
export const defaultEditorConfig: EditorConfiguration = {
tabSize: 2,
lineNumbers: "on",
fontSize: defaultFontSize,
fontFamily: defaultEditorFontFamily,
minimap: {
enabled: true,
side: "right",
},
};
export type StoreType<P> = P extends PreferenceDescription<unknown, infer Store>
? Store
: never;
export interface PreferenceDescription<T, R = T> {
fromStore(val: T | undefined): R;
toStore(val: R): T | undefined;
}
export const getPreferenceDescriptor = <T, R = T>(desc: PreferenceDescription<T, R>) => desc;
export interface DownloadMirror {
url: string;
label: string;
platforms: Set<NodeJS.Platform>;
}
export const defaultPackageMirror = "default";
const defaultDownloadMirrorData: DownloadMirror = {
url: "https://storage.googleapis.com/kubernetes-release/release",
label: "Default (Google)",
platforms: new Set(["darwin", "win32", "linux"]),
};
export const packageMirrors = new Map<string, DownloadMirror>([
[defaultPackageMirror, defaultDownloadMirrorData],
["china", {
url: "https://mirror.azure.cn/kubernetes/kubectl",
label: "China (Azure)",
platforms: new Set(["win32", "linux"]),
}],
]);
export type ExtensionRegistryLocation = "default" | "npmrc" | "custom";
export type ExtensionRegistry = {
location: "default" | "npmrc";
customUrl?: undefined;
} | {
location: "custom";
customUrl: string;
};
export const defaultExtensionRegistryUrlLocation = "default";
export const defaultExtensionRegistryUrl = "https://registry.npmjs.org";
type PreferencesModelType<field extends keyof PreferenceDescriptors> = PreferenceDescriptors[field] extends PreferenceDescription<infer T, any> ? T : never;
type UserStoreModelType<field extends keyof PreferenceDescriptors> = PreferenceDescriptors[field] extends PreferenceDescription<any, infer T> ? T : never;
export type UserStoreFlatModel = {
[field in keyof PreferenceDescriptors]: UserStoreModelType<field>;
};
export type UserPreferencesModel = {
[field in keyof PreferenceDescriptors]: PreferencesModelType<field>;
} & { updateChannel: string };
@@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userInfoInjectable from "./user-info.injectable";
import userStoreInjectable from "./user-store.injectable";
const userShellSettingInjectable = getInjectable({
id: "user-shell-setting",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
const userInfo = di.inject(userInfoInjectable);
return computed(() => userStore.shell || userInfo.shell);
},
});
export default userShellSettingInjectable;
@@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import { toJS } from "../utils";
import userStoreInjectable from "./user-store.injectable";
const terminalConfigInjectable = getInjectable({
id: "terminal-config",
instantiate: (di) => {
const store = di.inject(userStoreInjectable);
return computed(() => toJS(store.terminalConfig));
},
});
export default terminalConfigInjectable;
@@ -0,0 +1,18 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
const terminalCopyOnSelectInjectable = getInjectable({
id: "terminal-copy-on-select",
instantiate: (di) => {
const store = di.inject(userStoreInjectable);
return computed(() => store.terminalCopyOnSelect);
},
});
export default terminalCopyOnSelectInjectable;
@@ -0,0 +1,37 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
export type TerminalThemePreference = {
matchLensTheme: true;
} | {
matchLensTheme: false;
themeId: string;
};
const terminalThemePreferenceInjectable = getInjectable({
id: "terminal-theme-preference",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
return computed((): TerminalThemePreference => {
// NOTE: remove use of magic strings
if (!userStore.terminalTheme) {
return {
matchLensTheme: true,
};
}
return {
matchLensTheme: false,
themeId: userStore.terminalTheme,
};
});
},
});
export default terminalThemePreferenceInjectable;
@@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../test-utils/get-global-override";
import userInfoInjectable from "./user-info.injectable";
export default getGlobalOverride(userInfoInjectable, () => ({
gid: 1,
homedir: "/some-home-dir",
shell: "bash",
uid: 2,
username: "some-user-name",
}));
@@ -0,0 +1,14 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { userInfo } from "os";
const userInfoInjectable = getInjectable({
id: "user-info",
instantiate: () => userInfo(),
causesSideEffects: true,
});
export default userInfoInjectable;
@@ -0,0 +1,42 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { UserStore } from "./user-store";
import selectedUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../logger.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import storeMigrationsInjectable from "../base-store/migrations.injectable";
import { userStoreMigrationInjectionToken } from "./migrations-token";
import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel-prefix";
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token";
import userStorePreferenceDescriptorsInjectable from "./preference-descriptors.injectable";
const userStoreInjectable = getInjectable({
id: "user-store",
instantiate: (di) => new UserStore({
selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
migrations: di.inject(storeMigrationsInjectable, userStoreMigrationInjectionToken),
getBasenameOfPath: di.inject(getBasenameOfPathInjectable),
ipcChannelPrefixes: di.inject(baseStoreIpcChannelPrefixesInjectionToken),
persistStateToConfig: di.inject(persistStateToConfigInjectionToken),
enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken),
shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken),
preferenceDescriptors: di.inject(userStorePreferenceDescriptorsInjectable),
}),
});
export default userStoreInjectable;
@@ -0,0 +1,155 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, observable, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx";
import type { BaseStoreDependencies } from "../base-store/base-store";
import { BaseStore } from "../base-store/base-store";
import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
// TODO: Remove coupling with Feature
import type { SelectedUpdateChannel } from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import type { ReleaseChannel } from "../../features/application-update/common/update-channels";
import type { PreferenceDescriptors } from "./preference-descriptors.injectable";
export interface UserStoreModel {
preferences: UserPreferencesModel;
}
interface Dependencies extends BaseStoreDependencies {
readonly selectedUpdateChannel: SelectedUpdateChannel;
readonly preferenceDescriptors: PreferenceDescriptors;
emitAppEvent: EmitAppEvent;
}
export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
constructor(protected readonly dependencies: Dependencies) {
super(dependencies, {
configName: "lens-user-store",
});
makeObservable(this);
}
/**
* @deprecated No longer used
*/
@observable seenContexts = observable.set<string>();
/**
* @deprecated No longer used
*/
@observable newContexts = observable.set<string>();
@observable allowErrorReporting!: StoreType<PreferenceDescriptors["allowErrorReporting"]>;
@observable allowUntrustedCAs!: StoreType<PreferenceDescriptors["allowUntrustedCAs"]>;
@observable colorTheme!: StoreType<PreferenceDescriptors["colorTheme"]>;
@observable terminalTheme!: StoreType<PreferenceDescriptors["terminalTheme"]>;
@observable localeTimezone!: StoreType<PreferenceDescriptors["localeTimezone"]>;
@observable downloadMirror!: StoreType<PreferenceDescriptors["downloadMirror"]>;
@observable httpsProxy!: StoreType<PreferenceDescriptors["httpsProxy"]>;
@observable shell!: StoreType<PreferenceDescriptors["shell"]>;
@observable downloadBinariesPath!: StoreType<PreferenceDescriptors["downloadBinariesPath"]>;
@observable kubectlBinariesPath!: StoreType<PreferenceDescriptors["kubectlBinariesPath"]>;
@observable terminalCopyOnSelect!: StoreType<PreferenceDescriptors["terminalCopyOnSelect"]>;
@observable terminalConfig!: StoreType<PreferenceDescriptors["terminalConfig"]>;
@observable extensionRegistryUrl!: StoreType<PreferenceDescriptors["extensionRegistryUrl"]>;
/**
* Download kubectl binaries matching cluster version
*/
@observable downloadKubectlBinaries!: StoreType<PreferenceDescriptors["downloadKubectlBinaries"]>;
/**
* Whether the application should open itself at login.
*/
@observable openAtLogin!: StoreType<PreferenceDescriptors["openAtLogin"]>;
/**
* The column IDs under each configurable table ID that have been configured
* to not be shown
*/
@observable hiddenTableColumns!: StoreType<PreferenceDescriptors["hiddenTableColumns"]>;
/**
* Monaco editor configs
*/
@observable editorConfiguration!: StoreType<PreferenceDescriptors["editorConfiguration"]>;
/**
* The set of file/folder paths to be synced
*/
@observable syncKubeconfigEntries!: StoreType<PreferenceDescriptors["syncKubeconfigEntries"]>;
/**
* Checks if a column (by ID) for a table (by ID) is configured to be hidden
* @param tableId The ID of the table to be checked against
* @param columnIds The list of IDs the check if one is hidden
* @returns true if at least one column under the table is set to hidden
*/
isTableColumnHidden(tableId: string, ...columnIds: (string | undefined)[]): boolean {
if (columnIds.length === 0) {
return false;
}
const config = this.hiddenTableColumns.get(tableId);
if (!config) {
return false;
}
return columnIds.some(columnId => columnId && config.has(columnId));
}
/**
* Toggles the hidden configuration of a table's column
*/
toggleTableColumnVisibility(tableId: string, columnId: string) {
toggle(getOrInsertSet(this.hiddenTableColumns, tableId), columnId);
}
@action
resetTheme() {
this.colorTheme = this.dependencies.preferenceDescriptors.colorTheme.fromStore(undefined);
}
@action
protected fromStore({ preferences }: Partial<UserStoreModel> = {}) {
this.dependencies.logger.debug("UserStore.fromStore()", { preferences });
for (const [key, { fromStore }] of object.entries(this.dependencies.preferenceDescriptors)) {
const curVal = this[key];
const newVal = fromStore((preferences)?.[key] as never) as never;
if (isObservableArray(curVal)) {
curVal.replace(newVal);
} else if (isObservableSet(curVal) || isObservableMap(curVal)) {
curVal.replace(newVal);
} else {
this[key] = newVal;
}
}
// TODO: Switch to action-based saving instead saving stores by reaction
if (preferences?.updateChannel) {
this.dependencies.selectedUpdateChannel.setValue(preferences?.updateChannel as ReleaseChannel);
}
}
toJSON(): UserStoreModel {
const preferences = object.fromEntries(
object.entries(this.dependencies.preferenceDescriptors)
.map(([key, { toStore }]) => [key, toStore(this[key] as never)]),
) as UserPreferencesModel;
return toJS({
preferences: {
...preferences,
updateChannel: this.dependencies.selectedUpdateChannel.value.get().id,
},
});
}
}