mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
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:
1 parent
0066ca4ea2
commit
2657df2293
3321 files changed
+28699
-11447
No files matched your search
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type Config from "conf";
|
||||
import type { Migrations, Options as ConfOptions } from "conf/dist/source/types";
|
||||
import type { IEqualsComparer } from "mobx";
|
||||
import { makeObservable, reaction } from "mobx";
|
||||
import { disposer, isPromiseLike, toJS } from "../utils";
|
||||
import { broadcastMessage } from "../ipc";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { kebabCase } from "lodash";
|
||||
import type { GetConfigurationFileModel } from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import type { Logger } from "../logger";
|
||||
import type { PersistStateToConfig } from "./save-to-file";
|
||||
import type { GetBasenameOfPath } from "../path/get-basename.injectable";
|
||||
import type { EnlistMessageChannelListener } from "../utils/channel/enlist-message-channel-listener-injection-token";
|
||||
|
||||
export interface BaseStoreParams<T> extends Omit<ConfOptions<T>, "migrations"> {
|
||||
syncOptions?: {
|
||||
fireImmediately?: boolean;
|
||||
equals?: IEqualsComparer<T>;
|
||||
};
|
||||
configName: string;
|
||||
}
|
||||
|
||||
export interface IpcChannelPrefixes {
|
||||
local: string;
|
||||
remote: string;
|
||||
}
|
||||
|
||||
export interface BaseStoreDependencies {
|
||||
readonly logger: Logger;
|
||||
readonly storeMigrationVersion: string;
|
||||
readonly directoryForUserData: string;
|
||||
readonly migrations: Migrations<Record<string, unknown>>;
|
||||
readonly ipcChannelPrefixes: IpcChannelPrefixes;
|
||||
readonly shouldDisableSyncInListener: boolean;
|
||||
getConfigurationFileModel: GetConfigurationFileModel;
|
||||
persistStateToConfig: PersistStateToConfig;
|
||||
getBasenameOfPath: GetBasenameOfPath;
|
||||
enlistMessageChannelListener: EnlistMessageChannelListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: T should only contain base JSON serializable types.
|
||||
*/
|
||||
export abstract class BaseStore<T extends object> {
|
||||
private readonly syncDisposers = disposer();
|
||||
|
||||
readonly displayName = kebabCase(this.params.configName).toUpperCase();
|
||||
|
||||
protected constructor(
|
||||
protected readonly dependencies: BaseStoreDependencies,
|
||||
protected readonly params: BaseStoreParams<T>,
|
||||
) {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called after the last child's constructor is finished (or just before it finishes)
|
||||
*/
|
||||
load() {
|
||||
this.dependencies.logger.info(`[${this.displayName}]: LOADING ...`);
|
||||
|
||||
const config = this.dependencies.getConfigurationFileModel({
|
||||
projectName: "lens",
|
||||
projectVersion: this.dependencies.storeMigrationVersion,
|
||||
cwd: this.cwd(),
|
||||
...this.params,
|
||||
migrations: this.dependencies.migrations as Migrations<T>,
|
||||
});
|
||||
|
||||
const res = this.fromStore(config.store);
|
||||
|
||||
if (isPromiseLike(res)) {
|
||||
this.dependencies.logger.error(`${this.displayName} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
|
||||
}
|
||||
|
||||
this.startSyncing(config);
|
||||
this.dependencies.logger.info(`[${this.displayName}]: LOADED from ${config.path}`);
|
||||
}
|
||||
|
||||
protected cwd() {
|
||||
return this.dependencies.directoryForUserData;
|
||||
}
|
||||
|
||||
private startSyncing(config: Config<T>) {
|
||||
const name = this.dependencies.getBasenameOfPath(config.path);
|
||||
|
||||
const disableSync = () => this.syncDisposers();
|
||||
const enableSync = () => {
|
||||
this.syncDisposers.push(
|
||||
reaction(
|
||||
() => toJS(this.toJSON()), // unwrap possible observables and react to everything
|
||||
model => {
|
||||
this.dependencies.persistStateToConfig(config, model);
|
||||
broadcastMessage(`${this.dependencies.ipcChannelPrefixes.remote}:${config.path}`, model);
|
||||
},
|
||||
this.params.syncOptions,
|
||||
),
|
||||
this.dependencies.enlistMessageChannelListener({
|
||||
channel: {
|
||||
id: `${this.dependencies.ipcChannelPrefixes.local}:${config.path}`,
|
||||
},
|
||||
handler: (model) => {
|
||||
this.dependencies.logger.silly(`[${this.displayName}]: syncing ${name}`, { model });
|
||||
|
||||
if (this.dependencies.shouldDisableSyncInListener) {
|
||||
disableSync();
|
||||
}
|
||||
|
||||
// todo: use "resourceVersion" if merge required (to avoid equality checks => better performance)
|
||||
if (!isEqual(this.toJSON(), model)) {
|
||||
this.fromStore(model as T);
|
||||
}
|
||||
|
||||
if (this.dependencies.shouldDisableSyncInListener) {
|
||||
enableSync();
|
||||
}
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
enableSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* fromStore is called internally when a child class syncs with the file
|
||||
* system.
|
||||
*
|
||||
* Note: This function **must** be synchronous.
|
||||
*
|
||||
* @param data the parsed information read from the stored JSON file
|
||||
*/
|
||||
protected abstract fromStore(data: T): void;
|
||||
|
||||
/**
|
||||
* toJSON is called when syncing the store to the filesystem. It should
|
||||
* produce a JSON serializable object representation of the current state.
|
||||
*
|
||||
* It is recommended that a round trip is valid. Namely, calling
|
||||
* `this.fromStore(this.toJSON())` shouldn't change the state.
|
||||
*/
|
||||
abstract toJSON(): T;
|
||||
}
|
||||
@@ -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 { IpcChannelPrefixes } from "./base-store";
|
||||
|
||||
export const baseStoreIpcChannelPrefixesInjectionToken = getInjectionToken<IpcChannelPrefixes>({
|
||||
id: "base-store-ipc-channel-prefix-token",
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
export const shouldBaseStoreDisableSyncInIpcListenerInjectionToken = getInjectionToken<boolean>({
|
||||
id: "should-base-store-disable-sync-in-ipc-listener-token",
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { InjectionToken } from "@ogre-tools/injectable";
|
||||
import { lifecycleEnum, getInjectable } from "@ogre-tools/injectable";
|
||||
import type Conf from "conf/dist/source";
|
||||
import type { Migrations } from "conf/dist/source/types";
|
||||
import loggerInjectable from "../logger.injectable";
|
||||
import { getOrInsert, iter } from "../utils";
|
||||
|
||||
export interface MigrationDeclaration {
|
||||
version: string;
|
||||
run(store: Conf<Partial<Record<string, unknown>>>): void;
|
||||
}
|
||||
|
||||
const storeMigrationsInjectable = getInjectable({
|
||||
id: "store-migrations",
|
||||
instantiate: (di, token): Migrations<Record<string, unknown>> => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const declarations = di.injectMany(token);
|
||||
const migrations = new Map<string, MigrationDeclaration["run"][]>();
|
||||
|
||||
for (const decl of declarations) {
|
||||
getOrInsert(migrations, decl.version, []).push(decl.run);
|
||||
}
|
||||
|
||||
return Object.fromEntries(
|
||||
iter.map(
|
||||
migrations,
|
||||
([v, fns]) => [v, (store) => {
|
||||
logger.info(`Running ${v} migration for ${store.path}`);
|
||||
|
||||
for (const fn of fns) {
|
||||
fn(store);
|
||||
}
|
||||
}],
|
||||
),
|
||||
);
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, token: InjectionToken<MigrationDeclaration, void>) => token.id,
|
||||
}),
|
||||
});
|
||||
|
||||
export default storeMigrationsInjectable;
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 Config from "conf";
|
||||
|
||||
export type PersistStateToConfig = <T extends object>(config: Config<T>, state: T) => void;
|
||||
|
||||
export const persistStateToConfigInjectionToken = getInjectionToken<PersistStateToConfig>({
|
||||
id: "persist-state-to-config-token",
|
||||
});
|
||||
Reference in new issue
Block a user