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",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@k8slens/runtime-features": {
|
||||
"resolved": "packages/business-features/runtime-features",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@k8slens/semver": {
|
||||
"resolved": "packages/semver",
|
||||
"link": true
|
||||
@ -34177,6 +34181,26 @@
|
||||
"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": {
|
||||
"name": "@k8slens/cluster-settings",
|
||||
"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 { 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";
|
||||
|
||||
@ -31,7 +31,8 @@
|
||||
"lint:fix": "lens-lint --fix"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ogre-tools/injectable": "^16.1.0"
|
||||
"@ogre-tools/injectable": "^16.1.0",
|
||||
"mobx": "^6.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@k8slens/eslint-config": "^6.5.0-alpha.3",
|
||||
|
||||
@ -1,7 +1,19 @@
|
||||
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 { 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 featureContextInjectable = getInjectable({
|
||||
@ -26,6 +38,40 @@ const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
||||
|
||||
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 featureContext = di.inject(featureContextInjectable);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user