1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/renderer/utils/create-storage/create-storage.ts
Janne Savolainen 3c13fef3d4
Provide a way to unit test usages of storages
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
2022-07-18 15:51:55 +03:00

101 lines
3.1 KiB
TypeScript
Executable File

/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
// Keeps window.localStorage state in external JSON-files.
// Because app creates random port between restarts => storage session wiped out each time.
import { comparer, reaction, toJS, when } from "mobx";
import type { StorageLayer } from "../storageHelper";
import { StorageHelper } from "../storageHelper";
import { isTestEnv } from "../../../common/vars";
import type { JsonObject, JsonValue } from "type-fest";
import type { Logger } from "../../../common/logger";
import type { GetAbsolutePath } from "../../../common/path/get-absolute-path.injectable";
interface Dependencies {
storage: { initialized: boolean; loaded: boolean; data: Record<string, any> };
logger: Logger;
directoryForLensLocalStorage: string;
readJsonFile: (filePath: string) => Promise<JsonValue>;
writeJsonFile: (filePath: string, contentObject: JsonObject) => Promise<void>;
getAbsolutePath: GetAbsolutePath;
hostedClusterId: string | undefined;
saveDelay: number;
}
export type CreateStorage = <T>(key: string, defaultValue: T) => StorageLayer<T>;
/**
* Creates a helper for saving data under the "key" intended for window.localStorage
*/
export const createStorage = ({
storage,
getAbsolutePath,
logger,
directoryForLensLocalStorage,
readJsonFile,
writeJsonFile,
hostedClusterId,
saveDelay,
}: Dependencies): CreateStorage => (key, defaultValue) => {
const { logPrefix } = StorageHelper;
if (!storage.initialized) {
storage.initialized = true;
(async () => {
const filePath = getAbsolutePath(directoryForLensLocalStorage, `${hostedClusterId || "app"}.json`);
try {
storage.data = (await readJsonFile(filePath)) as JsonObject;
} catch {
// do nothing
} finally {
if (!isTestEnv) {
logger.info(`${logPrefix} loading finished for ${filePath}`);
}
storage.loaded = true;
}
// bind auto-saving data changes to %storage-file.json
reaction(() => toJS(storage.data), saveFile, {
delay: saveDelay, // lazy, avoid excessive writes to fs
equals: comparer.structural, // save only when something really changed
});
async function saveFile(state: Record<string, any> = {}) {
logger.info(`${logPrefix} saving ${filePath}`);
try {
await writeJsonFile(filePath, state);
} catch (error) {
logger.error(`${logPrefix} saving failed: ${error}`, {
json: state, jsonFilePath: filePath,
});
}
}
})()
.catch(error => logger.error(`${logPrefix} Failed to initialize storage: ${error}`));
}
return new StorageHelper(key, {
autoInit: true,
defaultValue,
storage: {
async getItem(key: string) {
await when(() => storage.loaded);
return storage.data[key];
},
setItem(key: string, value: any) {
storage.data[key] = value;
},
removeItem(key: string) {
delete storage.data[key];
},
},
});
};