mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
WIP
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
4b63bc238e
commit
5f05c9cb6b
24
package-lock.json
generated
24
package-lock.json
generated
@ -3825,6 +3825,10 @@
|
|||||||
"resolved": "packages/utility-features/run-many",
|
"resolved": "packages/utility-features/run-many",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@k8slens/runtime-features": {
|
||||||
|
"resolved": "packages/business-features/runtime-features",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@k8slens/semver": {
|
"node_modules/@k8slens/semver": {
|
||||||
"resolved": "packages/semver",
|
"resolved": "packages/semver",
|
||||||
"link": true
|
"link": true
|
||||||
@ -34177,6 +34181,26 @@
|
|||||||
"react": "^17 || ^18"
|
"react": "^17 || ^18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"packages/business-features/runtime-features": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@async-fn/jest": "^1.6.4",
|
||||||
|
"@k8slens/eslint-config": "^6.5.0-alpha.3",
|
||||||
|
"@k8slens/react-testing-library-discovery": "^1.0.0-alpha.4",
|
||||||
|
"@k8slens/webpack": "^6.5.0-alpha.9"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
||||||
|
"@k8slens/react-application": "^1.0.0-alpha.0",
|
||||||
|
"@ogre-tools/fp": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable-extension-for-auto-registration": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable-react": "^16.1.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"react": "^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"packages/cluster-settings": {
|
"packages/cluster-settings": {
|
||||||
"name": "@k8slens/cluster-settings",
|
"name": "@k8slens/cluster-settings",
|
||||||
"version": "6.5.0-alpha.8",
|
"version": "6.5.0-alpha.8",
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "@k8slens/eslint-config/eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/business-features/runtime-features/.prettierrc
Normal file
1
packages/business-features/runtime-features/.prettierrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
"@k8slens/eslint-config/prettier"
|
||||||
19
packages/business-features/runtime-features/README.md
Normal file
19
packages/business-features/runtime-features/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# @k8slens/runtime-features
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install @k8slens/runtime-features
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { runtimeFeaturesFeature } from "@k8slens/runtime-features";
|
||||||
|
import { registerFeature } from "@k8slens/feature-core";
|
||||||
|
import { createContainer } from "@ogre-tools/injectable";
|
||||||
|
|
||||||
|
const di = createContainer("some-container");
|
||||||
|
|
||||||
|
registerFeature(di, runtimeFeaturesFeature);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extendability
|
||||||
8
packages/business-features/runtime-features/index.ts
Normal file
8
packages/business-features/runtime-features/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||||
|
export { runtimeFeaturesFeature } from "./src/feature";
|
||||||
|
|
||||||
|
export { mikkoFeature } from "./src/mikko-feature";
|
||||||
|
|
||||||
|
export const requireInjectionToken = getInjectionToken<any>({
|
||||||
|
id: "require-injection-token",
|
||||||
|
});
|
||||||
@ -0,0 +1 @@
|
|||||||
|
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact;
|
||||||
52
packages/business-features/runtime-features/package.json
Normal file
52
packages/business-features/runtime-features/package.json
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "@k8slens/runtime-features",
|
||||||
|
"private": false,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "TBD",
|
||||||
|
"type": "commonjs",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public",
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/lensapp/lens.git"
|
||||||
|
},
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"author": {
|
||||||
|
"name": "OpenLens Authors",
|
||||||
|
"email": "info@k8slens.dev"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/lensapp/lens",
|
||||||
|
"scripts": {
|
||||||
|
"build": "lens-webpack-build",
|
||||||
|
"clean": "rimraf dist/",
|
||||||
|
"test:unit": "jest --coverage --runInBand",
|
||||||
|
"lint": "lens-lint",
|
||||||
|
"lint:fix": "lens-lint --fix"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
||||||
|
"@k8slens/react-application": "^1.0.0-alpha.0",
|
||||||
|
"@ogre-tools/fp": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable-extension-for-auto-registration": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable-extension-for-mobx": "^16.1.0",
|
||||||
|
"@ogre-tools/injectable-react": "^16.1.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"react": "^17 || ^18",
|
||||||
|
"mobx": "^6.9.0",
|
||||||
|
"mobx-react": "^7.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@async-fn/jest": "^1.6.4",
|
||||||
|
"@k8slens/eslint-config": "^6.5.0-alpha.3",
|
||||||
|
"@k8slens/react-testing-library-discovery": "^1.0.0-alpha.4",
|
||||||
|
"@k8slens/webpack": "^6.5.0-alpha.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`keyboard-shortcuts when application is started renders 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
data-keyboard-shortcut-scope="some-scope"
|
||||||
|
data-keyboard-shortcut-scope-test="some-scope"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
17
packages/business-features/runtime-features/src/feature.ts
Normal file
17
packages/business-features/runtime-features/src/feature.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { getFeature } from "@k8slens/feature-core";
|
||||||
|
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||||
|
import { reactApplicationFeature } from "@k8slens/react-application";
|
||||||
|
|
||||||
|
export const runtimeFeaturesFeature = getFeature({
|
||||||
|
id: "runtime-features",
|
||||||
|
|
||||||
|
register: (di) => {
|
||||||
|
autoRegister({
|
||||||
|
di,
|
||||||
|
targetModule: module,
|
||||||
|
getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
dependencies: [reactApplicationFeature],
|
||||||
|
});
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { pipeline } from "@ogre-tools/fp";
|
||||||
|
import { DiContainer, getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { requireInjectionToken } from "../index";
|
||||||
|
import { map } from "lodash/fp";
|
||||||
|
import { Feature, registerFeature } from "@k8slens/feature-core";
|
||||||
|
import type React from "react";
|
||||||
|
import { runInAction } from "mobx";
|
||||||
|
|
||||||
|
export const installFeaturesInjectable = getInjectable({
|
||||||
|
id: "install-features",
|
||||||
|
instantiate: (di) => {
|
||||||
|
const requireAsd = di.inject(requireInjectionToken);
|
||||||
|
|
||||||
|
const getDynamicFeature = (featureJsString: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
||||||
|
const sandbox = new Function("module", "require", featureJsString);
|
||||||
|
const moduleFake = {};
|
||||||
|
|
||||||
|
sandbox(moduleFake, requireAsd);
|
||||||
|
|
||||||
|
console.log("mikko", { moduleFake });
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return moduleFake.exports.default;
|
||||||
|
};
|
||||||
|
|
||||||
|
return async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
await pipeline(
|
||||||
|
event.target.files,
|
||||||
|
map((file) => file.text()),
|
||||||
|
(x) => Promise.all(x),
|
||||||
|
map(getDynamicFeature),
|
||||||
|
(y) => {
|
||||||
|
runInAction(() => {
|
||||||
|
y.forEach((x) => registerFeature(di as unknown as DiContainer, x as Feature));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
import { getFeature } from "@k8slens/feature-core";
|
||||||
|
import { reactApplicationFeature } from "@k8slens/react-application";
|
||||||
|
|
||||||
|
import { computed } from "mobx";
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { reactApplicationChildrenInjectionToken } from "@k8slens/react-application";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export const mikkoInjectable = getInjectable({
|
||||||
|
id: "mikko",
|
||||||
|
|
||||||
|
instantiate: () => ({
|
||||||
|
id: "mikkomikko",
|
||||||
|
Component: () => (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "500px",
|
||||||
|
width: "500px",
|
||||||
|
backgroundColor: "green",
|
||||||
|
color: "white",
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
padding: "80px",
|
||||||
|
zIndex: 9999,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Mikko
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
enabled: computed(() => true),
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: reactApplicationChildrenInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const mikkoFeature = getFeature({
|
||||||
|
id: "mikko",
|
||||||
|
|
||||||
|
register: (di) => {
|
||||||
|
di.register(mikkoInjectable);
|
||||||
|
},
|
||||||
|
|
||||||
|
dependencies: [reactApplicationFeature],
|
||||||
|
});
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { reactApplicationChildrenInjectionToken } from "@k8slens/react-application";
|
||||||
|
import { computed, IComputedValue } from "mobx";
|
||||||
|
import React from "react";
|
||||||
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
|
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||||
|
import { featureInjectionToken } from "@k8slens/feature-core";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import type { FeatureAsd } from "@k8slens/feature-core";
|
||||||
|
import { installFeaturesInjectable } from "./install-features.injectable";
|
||||||
|
|
||||||
|
interface Dependencies {
|
||||||
|
features: IComputedValue<FeatureAsd[]>;
|
||||||
|
installFeatures: (event: any) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NonInjectedRuntimeFeaturesPreferences = observer(({ features, installFeatures }: Dependencies) => (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "500px",
|
||||||
|
width: "500px",
|
||||||
|
backgroundColor: "red",
|
||||||
|
color: "white",
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
padding: "80px",
|
||||||
|
zIndex: 9999,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h2>Features</h2>
|
||||||
|
<ul>
|
||||||
|
{features.get().map((x) => (
|
||||||
|
<li key={x.id}>
|
||||||
|
{x.id} <input type="checkbox" checked={x.enabled.get()} onChange={x.toggle} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Register new feature
|
||||||
|
<input type="file" onChange={installFeatures} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
|
||||||
|
export const RuntimeFeaturesPreferences = withInjectables<Dependencies>(
|
||||||
|
NonInjectedRuntimeFeaturesPreferences,
|
||||||
|
|
||||||
|
{
|
||||||
|
getProps: (di) => {
|
||||||
|
const computedInjectMany = di.inject(computedInjectManyInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
features: computedInjectMany(featureInjectionToken),
|
||||||
|
installFeatures: di.inject(installFeaturesInjectable),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const runtimeFeaturesPreferencesInjectable = getInjectable({
|
||||||
|
id: "runtime-features-preferences",
|
||||||
|
|
||||||
|
instantiate: () => ({
|
||||||
|
id: "runtime-feature-preferences",
|
||||||
|
Component: RuntimeFeaturesPreferences,
|
||||||
|
enabled: computed(() => true),
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: reactApplicationChildrenInjectionToken,
|
||||||
|
});
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "@k8slens/typescript/config/base.json",
|
||||||
|
"include": ["**/*.ts", "**/*.tsx"],
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
module.exports = require("@k8slens/webpack").configForReact;
|
||||||
@ -1,3 +1,4 @@
|
|||||||
export { getFeature } from "./src/feature";
|
export { getFeature } from "./src/feature";
|
||||||
export { registerFeature } from "./src/register-feature";
|
export { registerFeature, featureInjectionToken } from "./src/register-feature";
|
||||||
|
export type { FeatureAsd } from "./src/register-feature";
|
||||||
export type { Feature, GetFeatureArgs } from "./src/feature";
|
export type { Feature, GetFeatureArgs } from "./src/feature";
|
||||||
|
|||||||
@ -31,7 +31,8 @@
|
|||||||
"lint:fix": "lens-lint --fix"
|
"lint:fix": "lens-lint --fix"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ogre-tools/injectable": "^16.1.0"
|
"@ogre-tools/injectable": "^16.1.0",
|
||||||
|
"mobx": "^6.9.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@k8slens/eslint-config": "^6.5.0-alpha.3",
|
"@k8slens/eslint-config": "^6.5.0-alpha.3",
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
import type { DiContainer } from "@ogre-tools/injectable";
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||||
import type { Feature } from "./feature";
|
import type { Feature } from "./feature";
|
||||||
import { featureContextMapInjectable, featureContextMapInjectionToken } from "./feature-context-map-injectable";
|
import { featureContextMapInjectable, featureContextMapInjectionToken } from "./feature-context-map-injectable";
|
||||||
|
import { action, IComputedValue } from "mobx";
|
||||||
|
import { computed, observable } from "mobx";
|
||||||
|
|
||||||
|
export type FeatureAsd = {
|
||||||
|
id: string;
|
||||||
|
enabled: IComputedValue<boolean>;
|
||||||
|
toggle: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const featureInjectionToken = getInjectionToken<FeatureAsd>({
|
||||||
|
id: "feature-injection-token",
|
||||||
|
});
|
||||||
|
|
||||||
const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
||||||
const featureContextInjectable = getInjectable({
|
const featureContextInjectable = getInjectable({
|
||||||
@ -26,6 +38,40 @@ const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
|||||||
|
|
||||||
di.register(featureContextInjectable);
|
di.register(featureContextInjectable);
|
||||||
|
|
||||||
|
const featureAsdInjectable = getInjectable({
|
||||||
|
id: `${feature.id}-feature`,
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const enabled = observable.box(true);
|
||||||
|
|
||||||
|
const featureContext = di.inject(featureContextInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: feature.id,
|
||||||
|
|
||||||
|
enabled: computed(() => {
|
||||||
|
return enabled.get();
|
||||||
|
}),
|
||||||
|
|
||||||
|
toggle: action(() => {
|
||||||
|
console.log("mikko", enabled.get());
|
||||||
|
|
||||||
|
if (enabled.get()) {
|
||||||
|
enabled.set(false);
|
||||||
|
featureContext.deregister();
|
||||||
|
} else {
|
||||||
|
enabled.set(true);
|
||||||
|
featureContext.register();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: featureInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
di.register(featureAsdInjectable);
|
||||||
|
|
||||||
const featureContextMap = di.inject(featureContextMapInjectable);
|
const featureContextMap = di.inject(featureContextMapInjectable);
|
||||||
const featureContext = di.inject(featureContextInjectable);
|
const featureContext = di.inject(featureContextInjectable);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user