mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Introduce eslint and prettier for features and start using it (#7306)
* Introduce package for sharing eslint and prettier configurations Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Start using eslint and prettier in packages Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> --------- Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
2789bcebcb
commit
699fc0309e
2945
package-lock.json
generated
2945
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
packages/infrastructure/eslint-config/README.md
Normal file
32
packages/infrastructure/eslint-config/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Lens Code Style
|
||||||
|
|
||||||
|
**Note:** This package contains Eslint and Prettier configurations, name of package is `@k8slens/eslint-config` just because Eslint has arbitrary requirement (https://eslint.org/docs/latest/extend/shareable-configs).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Install `@k8slens/eslint-config`
|
||||||
|
2. Create `.prettierrc` that contains `"@k8slens/eslint-config/prettier"`
|
||||||
|
3. Add a `.eslintrc.js` that extends `@k8slens/eslint-config/eslint`, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
module.exports = {
|
||||||
|
extends: "@k8slens/eslint-config/eslint",
|
||||||
|
parserOptions: {
|
||||||
|
project: "./tsconfig.json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Add linting and formatting scripts to `package.json`
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"lint": "lens-lint",
|
||||||
|
"lint:fix": "lens-lint --fix"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Run `npm run lint` to lint
|
||||||
|
7. Run `npm run format` to fix all formatting
|
||||||
20
packages/infrastructure/eslint-config/bin/lint
Executable file
20
packages/infrastructure/eslint-config/bin/lint
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const execSync = require("child_process").execSync;
|
||||||
|
|
||||||
|
const argv = process.argv
|
||||||
|
|
||||||
|
const shouldDoTheFix = argv.includes('--fix');
|
||||||
|
|
||||||
|
try {
|
||||||
|
execSync(`eslint ${shouldDoTheFix ? "--fix " : " "}--ext ts,tsx --max-warnings=0 .`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.stdout.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = execSync(`prettier ${shouldDoTheFix ? "--write" : "--check"} "**/*.{js,ts,tsx}"`);
|
||||||
|
|
||||||
|
console.log(result.toString());
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.stdout.toString());
|
||||||
|
}
|
||||||
173
packages/infrastructure/eslint-config/eslint-config.js
Normal file
173
packages/infrastructure/eslint-config/eslint-config.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"react-app",
|
||||||
|
"react-app/jest",
|
||||||
|
"airbnb-typescript",
|
||||||
|
"prettier",
|
||||||
|
"plugin:security/recommended",
|
||||||
|
"plugin:xss/recommended",
|
||||||
|
"plugin:no-unsanitized/DOM"
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
"unused-imports",
|
||||||
|
"prettier",
|
||||||
|
"xss",
|
||||||
|
"no-unsanitized"
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"react/react-in-jsx-scope": 0,
|
||||||
|
"security/detect-object-injection": "off",
|
||||||
|
"security/detect-non-literal-fs-filename": "off"
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
"**/*.ts?(x)",
|
||||||
|
"**/*.js?(x)",
|
||||||
|
"**/*.@(m|c)js"
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"prettier/prettier": 2,
|
||||||
|
indent: "off", // Let prettier do it
|
||||||
|
curly: "error",
|
||||||
|
"import/prefer-default-export": "off",
|
||||||
|
"class-methods-use-this": "off",
|
||||||
|
"comma-dangle": "off",
|
||||||
|
"max-classes-per-file": "off",
|
||||||
|
"no-shadow": "off",
|
||||||
|
"no-param-reassign": ["error", { props: false }],
|
||||||
|
quotes: [
|
||||||
|
"error",
|
||||||
|
"double",
|
||||||
|
{
|
||||||
|
"avoidEscape": true,
|
||||||
|
"allowTemplateLiterals": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"padding-line-between-statements": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
blankLine: "always",
|
||||||
|
prev: "*",
|
||||||
|
next: "return",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: "always",
|
||||||
|
prev: "*",
|
||||||
|
next: "block-like",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: "always",
|
||||||
|
prev: "*",
|
||||||
|
next: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: "always",
|
||||||
|
prev: "*",
|
||||||
|
next: "class",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: "always",
|
||||||
|
prev: ["const", "let", "var"],
|
||||||
|
next: "*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: "any",
|
||||||
|
prev: ["const", "let", "var"],
|
||||||
|
next: ["const", "let", "var"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"import/no-extraneous-dependencies": "off",
|
||||||
|
"jsx-a11y/no-redundant-roles": ["off"],
|
||||||
|
"no-restricted-syntax": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
selector: "ForInStatement",
|
||||||
|
message:
|
||||||
|
"for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: "WithStatement",
|
||||||
|
message:
|
||||||
|
"`with` is disallowed in strict mode because it makes code impossible to predict and optimize.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"max-len": [
|
||||||
|
"error",
|
||||||
|
120,
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
ignoreUrls: true,
|
||||||
|
ignoreComments: false,
|
||||||
|
ignoreRegExpLiterals: true,
|
||||||
|
ignoreStrings: true,
|
||||||
|
ignoreTemplateLiterals: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"unused-imports/no-unused-imports-ts": "error",
|
||||||
|
"import/extensions": "off",
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"eol-last": ["error", "always"],
|
||||||
|
"object-shorthand": "error",
|
||||||
|
"prefer-template": "error",
|
||||||
|
"template-curly-spacing": "error",
|
||||||
|
"keyword-spacing": "off",
|
||||||
|
|
||||||
|
// testing-library
|
||||||
|
"testing-library/no-node-access": "off",
|
||||||
|
"testing-library/no-container": "off",
|
||||||
|
"testing-library/prefer-screen-queries": "off",
|
||||||
|
"testing-library/no-render-in-setup": "off",
|
||||||
|
"testing-library/render-result-naming-convention": "off",
|
||||||
|
|
||||||
|
// Typescript specific rules
|
||||||
|
"@typescript-eslint/ban-types": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"@typescript-eslint/no-empty-interface": "off",
|
||||||
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-useless-constructor": "off",
|
||||||
|
"@typescript-eslint/comma-dangle": "off",
|
||||||
|
"@typescript-eslint/no-shadow": "off",
|
||||||
|
"@typescript-eslint/quotes": [
|
||||||
|
"error",
|
||||||
|
"double",
|
||||||
|
{
|
||||||
|
avoidEscape: true,
|
||||||
|
allowTemplateLiterals: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-expressions": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
allowShortCircuit: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/keyword-spacing": ["error"],
|
||||||
|
"@typescript-eslint/naming-convention": "off",
|
||||||
|
|
||||||
|
// React specific rules
|
||||||
|
"react-hooks/rules-of-hooks": "error",
|
||||||
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
|
"react/require-default-props": "off",
|
||||||
|
"react/function-component-definition": "off",
|
||||||
|
"react/prop-types": "off",
|
||||||
|
"react/jsx-filename-extension": [1, { extensions: [".tsx"] }],
|
||||||
|
|
||||||
|
// jsx-a11y custom components
|
||||||
|
"jsx-a11y/label-has-associated-control": [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
controlComponents: ["Select", "StyledInput", "StyledSlider"],
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
48
packages/infrastructure/eslint-config/package.json
Normal file
48
packages/infrastructure/eslint-config/package.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "@k8slens/eslint-config",
|
||||||
|
"version": "^6.5.0-alpha.0",
|
||||||
|
"description": "Lens eslint and prettier configurations",
|
||||||
|
"author": {
|
||||||
|
"name": "OpenLens Authors",
|
||||||
|
"email": "info@k8slens.dev"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"lens-lint": "bin/lint"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
"./eslint": "./eslint-config.js",
|
||||||
|
"./prettier": "./prettier-config.json"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./eslint-config.js",
|
||||||
|
"./prettier-config.json"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/lensapp/lens"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public",
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": ">= 5",
|
||||||
|
"@typescript-eslint/parser": ">= 5",
|
||||||
|
"eslint": ">= 7",
|
||||||
|
"eslint-config-airbnb-typescript": ">= 17",
|
||||||
|
"eslint-config-prettier": ">= 8",
|
||||||
|
"eslint-config-react-app": "^7.0.1",
|
||||||
|
"eslint-plugin-import": ">= 2",
|
||||||
|
"eslint-plugin-jest": ">= 27",
|
||||||
|
"eslint-plugin-jsx-a11y": ">= 6",
|
||||||
|
"eslint-plugin-no-unsanitized": ">= 4.0.2",
|
||||||
|
"eslint-plugin-prettier": ">= 4",
|
||||||
|
"eslint-plugin-react-hooks": ">= 4",
|
||||||
|
"eslint-plugin-security": ">= 1.6.0",
|
||||||
|
"eslint-plugin-simple-import-sort": ">= 7",
|
||||||
|
"eslint-plugin-unused-imports": ">= 2",
|
||||||
|
"eslint-plugin-xss": ">= 0.1.12",
|
||||||
|
"prettier": ">= 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
12
packages/infrastructure/eslint-config/prettier-config.json
Normal file
12
packages/infrastructure/eslint-config/prettier-config.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"quoteProps": "as-needed",
|
||||||
|
"jsxSingleQuote": false,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "always"
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: "@k8slens/eslint-config/eslint",
|
||||||
|
parserOptions: {
|
||||||
|
project: "./tsconfig.json",
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
"@k8slens/eslint-config/prettier"
|
||||||
@ -1,2 +1 @@
|
|||||||
module.exports =
|
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode;
|
||||||
require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode;
|
|
||||||
|
|||||||
@ -26,7 +26,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"dev": "webpack --mode=development --watch",
|
"dev": "webpack --mode=development --watch",
|
||||||
"test": "jest --coverage --runInBand"
|
"test": "jest --coverage --runInBand",
|
||||||
|
"lint": "lens-lint",
|
||||||
|
"lint:fix": "lens-lint --fix"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
||||||
@ -37,6 +39,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@async-fn/jest": "^1.6.4"
|
"@async-fn/jest": "^1.6.4",
|
||||||
|
"@k8slens/eslint-config": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,15 +10,15 @@ export type ApplicationInformation = {
|
|||||||
productName: string;
|
productName: string;
|
||||||
copyright: string;
|
copyright: string;
|
||||||
description: string;
|
description: string;
|
||||||
k8sProxyVersion: string,
|
k8sProxyVersion: string;
|
||||||
bundledKubectlVersion: string,
|
bundledKubectlVersion: string;
|
||||||
bundledHelmVersion: string,
|
bundledHelmVersion: string;
|
||||||
sentryDsn: string,
|
sentryDsn: string;
|
||||||
contentSecurityPolicy: string,
|
contentSecurityPolicy: string;
|
||||||
welcomeRoute: string,
|
welcomeRoute: string;
|
||||||
updatingIsEnabled: boolean;
|
updatingIsEnabled: boolean;
|
||||||
dependencies: Partial<Record<string, string>>;
|
dependencies: Partial<Record<string, string>>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
|
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
|
||||||
id: "application-information-token",
|
id: "application-information-token",
|
||||||
|
|||||||
@ -9,9 +9,7 @@ export const applicationFeature = getFeature({
|
|||||||
di,
|
di,
|
||||||
targetModule: module,
|
targetModule: module,
|
||||||
|
|
||||||
getRequireContexts: () => [
|
getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)],
|
||||||
require.context("./", true, /\.injectable\.(ts|tsx)$/),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { createContainer, DiContainer, getInjectable } from "@ogre-tools/injectable";
|
||||||
createContainer,
|
|
||||||
DiContainer,
|
|
||||||
getInjectable,
|
|
||||||
} from "@ogre-tools/injectable";
|
|
||||||
import { registerFeature } from "@k8slens/feature-core";
|
import { registerFeature } from "@k8slens/feature-core";
|
||||||
import { applicationFeature } from "../feature";
|
import { applicationFeature } from "../feature";
|
||||||
import { startApplicationInjectionToken } from "./start-application.injectable";
|
import { startApplicationInjectionToken } from "./start-application.injectable";
|
||||||
@ -46,7 +42,7 @@ describe("starting-of-application", () => {
|
|||||||
di.register(
|
di.register(
|
||||||
beforeApplicationIsLoadingInjectable,
|
beforeApplicationIsLoadingInjectable,
|
||||||
onLoadOfApplicationInjectable,
|
onLoadOfApplicationInjectable,
|
||||||
afterApplicationIsLoadedInjectable
|
afterApplicationIsLoadedInjectable,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,7 +50,7 @@ describe("starting-of-application", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const startApplication = di.inject(startApplicationInjectionToken);
|
const startApplication = di.inject(startApplicationInjectionToken);
|
||||||
|
|
||||||
startApplication();
|
void startApplication();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("calls runnables registered in before application is loading", () => {
|
it("calls runnables registered in before application is loading", () => {
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "@k8slens/typescript/config/base.json"
|
"extends": "@k8slens/typescript/config/base.json",
|
||||||
|
"include": ["**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: "@k8slens/eslint-config/eslint",
|
||||||
|
parserOptions: {
|
||||||
|
project: "./tsconfig.json",
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
"@k8slens/eslint-config/prettier"
|
||||||
@ -4,4 +4,4 @@ export * from "./src/start-application/time-slots";
|
|||||||
|
|
||||||
export { applicationFeatureForElectronMain } from "./src/feature";
|
export { applicationFeatureForElectronMain } from "./src/feature";
|
||||||
|
|
||||||
export const testUtils = { overrideSideEffectsWithFakes }
|
export const testUtils = { overrideSideEffectsWithFakes };
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
module.exports =
|
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode;
|
||||||
require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode;
|
|
||||||
|
|||||||
@ -26,7 +26,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"dev": "webpack --mode=development --watch",
|
"dev": "webpack --mode=development --watch",
|
||||||
"test": "jest --coverage --runInBand"
|
"test": "jest --coverage --runInBand",
|
||||||
|
"lint": "lens-lint",
|
||||||
|
"lint:fix": "lens-lint --fix"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
"@k8slens/feature-core": "^6.5.0-alpha.0",
|
||||||
@ -38,6 +40,7 @@
|
|||||||
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@async-fn/jest": "^1.6.4",
|
"@async-fn/jest": "^1.6.4",
|
||||||
"@ogre-tools/test-utils": "^15.1.2"
|
"@ogre-tools/test-utils": "^15.1.2",
|
||||||
|
"@k8slens/eslint-config": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import electronAppInjectable from "./electron-app.injectable";
|
import electronAppInjectable from "./electron-app.injectable";
|
||||||
import { app } from 'electron';
|
import { app } from "electron";
|
||||||
import { createContainer } from "@ogre-tools/injectable";
|
import { createContainer } from "@ogre-tools/injectable";
|
||||||
import { applicationFeatureForElectronMain } from "../feature";
|
import { applicationFeatureForElectronMain } from "../feature";
|
||||||
import { registerFeature } from "@k8slens/feature-core";
|
import { registerFeature } from "@k8slens/feature-core";
|
||||||
|
|
||||||
describe('electron-app', () => {
|
describe("electron-app", () => {
|
||||||
it('is electron app', () => {
|
it("is electron app", () => {
|
||||||
const di = createContainer('irrelevant');
|
const di = createContainer("irrelevant");
|
||||||
|
|
||||||
registerFeature(di, applicationFeatureForElectronMain)
|
registerFeature(di, applicationFeatureForElectronMain);
|
||||||
|
|
||||||
const actual = di.inject(electronAppInjectable);
|
const actual = di.inject(electronAppInjectable);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { getFeature } from "@k8slens/feature-core";
|
import { getFeature } from "@k8slens/feature-core";
|
||||||
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||||
import { applicationFeature } from '@k8slens/application';
|
import { applicationFeature } from "@k8slens/application";
|
||||||
|
|
||||||
export const applicationFeatureForElectronMain = getFeature({
|
export const applicationFeatureForElectronMain = getFeature({
|
||||||
id: "application-for-electron-main",
|
id: "application-for-electron-main",
|
||||||
@ -10,13 +10,9 @@ export const applicationFeatureForElectronMain = getFeature({
|
|||||||
di,
|
di,
|
||||||
targetModule: module,
|
targetModule: module,
|
||||||
|
|
||||||
getRequireContexts: () => [
|
getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)],
|
||||||
require.context("./", true, /\.injectable\.(ts|tsx)$/),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dependencies: [
|
dependencies: [applicationFeature],
|
||||||
applicationFeature
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,5 +2,5 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
|||||||
import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable";
|
import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable";
|
||||||
|
|
||||||
export const overrideSideEffectsWithFakes = (di: DiContainer) => {
|
export const overrideSideEffectsWithFakes = (di: DiContainer) => {
|
||||||
di.override(whenAppIsReadyInjectable, () => () => Promise.resolve())
|
di.override(whenAppIsReadyInjectable, () => () => Promise.resolve());
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,10 +18,7 @@ describe("when-app-is-ready", () => {
|
|||||||
|
|
||||||
whenReadyMock = asyncFn();
|
whenReadyMock = asyncFn();
|
||||||
|
|
||||||
di.override(
|
di.override(electronAppInjectable, () => ({ whenReady: whenReadyMock } as unknown));
|
||||||
electronAppInjectable,
|
|
||||||
() => ({ whenReady: whenReadyMock } as unknown)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when called", () => {
|
describe("when called", () => {
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { createContainer, DiContainer, getInjectable } from "@ogre-tools/injectable";
|
||||||
createContainer,
|
|
||||||
DiContainer,
|
|
||||||
getInjectable,
|
|
||||||
} from "@ogre-tools/injectable";
|
|
||||||
import { registerFeature } from "@k8slens/feature-core";
|
import { registerFeature } from "@k8slens/feature-core";
|
||||||
import { applicationFeatureForElectronMain } from "./feature";
|
import { applicationFeatureForElectronMain } from "./feature";
|
||||||
import {
|
import {
|
||||||
@ -52,7 +48,7 @@ describe("starting-of-electron-main-application", () => {
|
|||||||
di.register(
|
di.register(
|
||||||
beforeAnythingIsLoadingInjectable,
|
beforeAnythingIsLoadingInjectable,
|
||||||
beforeElectronIsReadyIsLoadingInjectable,
|
beforeElectronIsReadyIsLoadingInjectable,
|
||||||
beforeApplicationIsLoadingInjectable
|
beforeApplicationIsLoadingInjectable,
|
||||||
);
|
);
|
||||||
|
|
||||||
di.override(whenAppIsReadyInjectable, () => whenAppIsReadyMock);
|
di.override(whenAppIsReadyInjectable, () => whenAppIsReadyMock);
|
||||||
@ -62,7 +58,7 @@ describe("starting-of-electron-main-application", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const startApplication = di.inject(startApplicationInjectionToken);
|
const startApplication = di.inject(startApplicationInjectionToken);
|
||||||
|
|
||||||
startApplication();
|
void startApplication();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("calls for synchronous runnables for before anything", () => {
|
it("calls for synchronous runnables for before anything", () => {
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "@k8slens/typescript/config/base.json"
|
"extends": "@k8slens/typescript/config/base.json",
|
||||||
|
"include": ["**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
6
packages/technical-features/feature-core/.eslintrc.js
Normal file
6
packages/technical-features/feature-core/.eslintrc.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: "@k8slens/eslint-config/eslint",
|
||||||
|
parserOptions: {
|
||||||
|
project: "./tsconfig.json",
|
||||||
|
},
|
||||||
|
};
|
||||||
1
packages/technical-features/feature-core/.prettierrc
Normal file
1
packages/technical-features/feature-core/.prettierrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
"@k8slens/eslint-config/prettier"
|
||||||
@ -1,2 +1 @@
|
|||||||
module.exports =
|
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact;
|
||||||
require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact;
|
|
||||||
|
|||||||
@ -28,9 +28,15 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"dev": "webpack --mode=development --watch",
|
"dev": "webpack --mode=development --watch",
|
||||||
"test": "jest --coverage --runInBand"
|
"test": "jest --coverage --runInBand",
|
||||||
|
"lint": "lens-lint",
|
||||||
|
"lint:fix": "lens-lint --fix"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ogre-tools/injectable": "^15.1.2"
|
"@ogre-tools/injectable": "^15.1.2"
|
||||||
|
},
|
||||||
|
|
||||||
|
"devDependencies": {
|
||||||
|
"@k8slens/eslint-config": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,25 +2,31 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
|||||||
import type { Feature } from "./feature";
|
import type { Feature } from "./feature";
|
||||||
import { featureContextMapInjectable } from "./feature-context-map-injectable";
|
import { featureContextMapInjectable } from "./feature-context-map-injectable";
|
||||||
|
|
||||||
export const deregisterFeature = (di: DiContainer, ...features: Feature[]) => {
|
const getDependingFeaturesFor = (
|
||||||
features.forEach((feature) => {
|
featureContextMap: Map<Feature, { dependedBy: Map<Feature, number> }>,
|
||||||
deregisterFeatureRecursed(di, feature);
|
) => {
|
||||||
});
|
const getDependingFeaturesForRecursion = (feature: Feature, atRoot = true): string[] => {
|
||||||
|
const context = featureContextMap.get(feature);
|
||||||
|
|
||||||
|
if (context?.dependedBy.size) {
|
||||||
|
return [...context?.dependedBy.entries()].flatMap(([dependant]) =>
|
||||||
|
getDependingFeaturesForRecursion(dependant, false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return atRoot ? [] : [feature.id];
|
||||||
|
};
|
||||||
|
|
||||||
|
return getDependingFeaturesForRecursion;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deregisterFeatureRecursed = (
|
const deregisterFeatureRecursed = (di: DiContainer, feature: Feature, dependedBy?: Feature) => {
|
||||||
di: DiContainer,
|
|
||||||
feature: Feature,
|
|
||||||
dependedBy?: Feature
|
|
||||||
) => {
|
|
||||||
const featureContextMap = di.inject(featureContextMapInjectable);
|
const featureContextMap = di.inject(featureContextMapInjectable);
|
||||||
|
|
||||||
const featureContext = featureContextMap.get(feature);
|
const featureContext = featureContextMap.get(feature);
|
||||||
|
|
||||||
if (!featureContext) {
|
if (!featureContext) {
|
||||||
throw new Error(
|
throw new Error(`Tried to deregister feature "${feature.id}", but it was not registered.`);
|
||||||
`Tried to deregister feature "${feature.id}", but it was not registered.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
featureContext.numberOfRegistrations--;
|
featureContext.numberOfRegistrations--;
|
||||||
@ -33,15 +39,15 @@ const deregisterFeatureRecursed = (
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
`Tried to deregister Feature "${
|
`Tried to deregister Feature "${
|
||||||
feature.id
|
feature.id
|
||||||
}", but it is the dependency of Features "${dependingFeatures.join(
|
}", but it is the dependency of Features "${dependingFeatures.join(", ")}"`,
|
||||||
", "
|
|
||||||
)}"`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dependedBy) {
|
if (dependedBy) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const oldNumberOfDependents = featureContext.dependedBy.get(dependedBy)!;
|
const oldNumberOfDependents = featureContext.dependedBy.get(dependedBy)!;
|
||||||
const newNumberOfDependants = oldNumberOfDependents - 1;
|
const newNumberOfDependants = oldNumberOfDependents - 1;
|
||||||
|
|
||||||
featureContext.dependedBy.set(dependedBy, newNumberOfDependants);
|
featureContext.dependedBy.set(dependedBy, newNumberOfDependants);
|
||||||
|
|
||||||
if (newNumberOfDependants === 0) {
|
if (newNumberOfDependants === 0) {
|
||||||
@ -60,23 +66,8 @@ const deregisterFeatureRecursed = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDependingFeaturesFor = (
|
export const deregisterFeature = (di: DiContainer, ...features: Feature[]) => {
|
||||||
featureContextMap: Map<Feature, { dependedBy: Map<Feature, number> }>
|
features.forEach((feature) => {
|
||||||
) => {
|
deregisterFeatureRecursed(di, feature);
|
||||||
const getDependingFeaturesForRecursion = (
|
});
|
||||||
feature: Feature,
|
|
||||||
atRoot = true
|
|
||||||
): string[] => {
|
|
||||||
const context = featureContextMap.get(feature);
|
|
||||||
|
|
||||||
if (context?.dependedBy.size) {
|
|
||||||
return [...context!.dependedBy.entries()].flatMap(([dependant]) =>
|
|
||||||
getDependingFeaturesForRecursion(dependant, false)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return atRoot ? [] : [feature.id];
|
|
||||||
};
|
|
||||||
|
|
||||||
return getDependingFeaturesForRecursion;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,10 +11,9 @@ export type FeatureContextMap = Map<
|
|||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const featureContextMapInjectionToken =
|
export const featureContextMapInjectionToken = getInjectionToken<FeatureContextMap>({
|
||||||
getInjectionToken<FeatureContextMap>({
|
id: "feature-context-map-injection-token",
|
||||||
id: "feature-context-map-injection-token",
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const featureContextMapInjectable = getInjectable({
|
const featureContextMapInjectable = getInjectable({
|
||||||
id: "feature-store",
|
id: "feature-store",
|
||||||
|
|||||||
@ -1,14 +1,9 @@
|
|||||||
import {
|
import { createContainer, DiContainer, getInjectable, Injectable } from "@ogre-tools/injectable";
|
||||||
createContainer,
|
|
||||||
DiContainer,
|
|
||||||
getInjectable,
|
|
||||||
Injectable,
|
|
||||||
} from "@ogre-tools/injectable";
|
|
||||||
|
|
||||||
import type { Feature } from "./feature";
|
import type { Feature } from "./feature";
|
||||||
import { registerFeature } from "./register-feature";
|
import { registerFeature } from "./register-feature";
|
||||||
import { deregisterFeature } from "./deregister-feature";
|
import { deregisterFeature } from "./deregister-feature";
|
||||||
import { getFeature } from "./feature" ;
|
import { getFeature } from "./feature";
|
||||||
|
|
||||||
describe("feature-dependencies", () => {
|
describe("feature-dependencies", () => {
|
||||||
describe("given a parent Feature with another Features as dependency", () => {
|
describe("given a parent Feature with another Features as dependency", () => {
|
||||||
@ -55,7 +50,7 @@ describe("feature-dependencies", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someDependencyFeature);
|
deregisterFeature(di, someDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature"'
|
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,7 +60,7 @@ describe("feature-dependencies", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someDependencyFeature);
|
deregisterFeature(di, someDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to deregister feature "some-dependency-feature", but it was not registered.'
|
'Tried to deregister feature "some-dependency-feature", but it was not registered.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,9 +69,7 @@ describe("feature-dependencies", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
di.inject(someInjectableInDependencyFeature);
|
di.inject(someInjectableInDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow('Tried to inject non-registered injectable "irrelevant" -> "some-injectable".');
|
||||||
'Tried to inject non-registered injectable "irrelevant" -> "some-injectable".'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,7 +105,7 @@ describe("feature-dependencies", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someFeature1);
|
deregisterFeature(di, someFeature1);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to deregister Feature "some-feature-1", but it is the dependency of Features "some-feature-2"'
|
'Tried to deregister Feature "some-feature-1", but it is the dependency of Features "some-feature-2"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -170,7 +163,7 @@ describe("feature-dependencies", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someSharedDependencyFeature);
|
deregisterFeature(di, someSharedDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"'
|
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -188,7 +181,7 @@ describe("feature-dependencies", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
di.inject(someInjectableInDependencyFeature);
|
di.inject(someInjectableInDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".'
|
'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -231,19 +224,14 @@ describe("feature-dependencies", () => {
|
|||||||
dependencies: [someFeatureForAdditionalHierarchy],
|
dependencies: [someFeatureForAdditionalHierarchy],
|
||||||
});
|
});
|
||||||
|
|
||||||
registerFeature(
|
registerFeature(di, someFeature1, someFeature2, someSharedDependencyFeature);
|
||||||
di,
|
|
||||||
someFeature1,
|
|
||||||
someFeature2,
|
|
||||||
someSharedDependencyFeature
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("when the shared Feature is deregistered, throws", () => {
|
it("when the shared Feature is deregistered, throws", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someSharedDependencyFeature);
|
deregisterFeature(di, someSharedDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"'
|
'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -264,17 +252,12 @@ describe("feature-dependencies", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("given all of the Features get deregistered, when injecting an injectable from the shared Feature, throws", () => {
|
it("given all of the Features get deregistered, when injecting an injectable from the shared Feature, throws", () => {
|
||||||
deregisterFeature(
|
deregisterFeature(di, someFeature1, someFeature2, someSharedDependencyFeature);
|
||||||
di,
|
|
||||||
someFeature1,
|
|
||||||
someFeature2,
|
|
||||||
someSharedDependencyFeature
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
di.inject(someInjectableInDependencyFeature);
|
di.inject(someInjectableInDependencyFeature);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".'
|
'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,5 +8,4 @@ export interface Feature {
|
|||||||
|
|
||||||
export interface GetFeatureArgs extends Feature {}
|
export interface GetFeatureArgs extends Feature {}
|
||||||
|
|
||||||
export const getFeature = (getFeatureArgs: GetFeatureArgs): Feature =>
|
export const getFeature = (getFeatureArgs: GetFeatureArgs): Feature => getFeatureArgs;
|
||||||
getFeatureArgs;
|
|
||||||
|
|||||||
@ -6,58 +6,6 @@ import {
|
|||||||
featureContextMapInjectionToken,
|
featureContextMapInjectionToken,
|
||||||
} from "./feature-context-map-injectable";
|
} from "./feature-context-map-injectable";
|
||||||
|
|
||||||
export const registerFeature = (di: DiContainer, ...features: Feature[]) => {
|
|
||||||
features.forEach((feature) => {
|
|
||||||
registerFeatureRecursed(di, feature);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const registerFeatureRecursed = (
|
|
||||||
di: DiContainer,
|
|
||||||
feature: Feature,
|
|
||||||
dependedBy?: Feature
|
|
||||||
) => {
|
|
||||||
const featureContextMaps = di.injectMany(featureContextMapInjectionToken);
|
|
||||||
|
|
||||||
if (featureContextMaps.length === 0) {
|
|
||||||
di.register(featureContextMapInjectable);
|
|
||||||
}
|
|
||||||
|
|
||||||
const featureContextMap = di.inject(featureContextMapInjectable);
|
|
||||||
|
|
||||||
const existingFeatureContext = featureContextMap.get(feature);
|
|
||||||
if (
|
|
||||||
!dependedBy &&
|
|
||||||
existingFeatureContext &&
|
|
||||||
existingFeatureContext.dependedBy.size === 0
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
`Tried to register feature "${feature.id}", but it was already registered.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const featureContext =
|
|
||||||
existingFeatureContext || createFeatureContext(feature, di);
|
|
||||||
|
|
||||||
featureContext.numberOfRegistrations++;
|
|
||||||
|
|
||||||
if (dependedBy) {
|
|
||||||
const oldNumberOfDependents =
|
|
||||||
featureContext.dependedBy.get(dependedBy) || 0;
|
|
||||||
|
|
||||||
const newNumberOfDependants = oldNumberOfDependents + 1;
|
|
||||||
featureContext.dependedBy.set(dependedBy, newNumberOfDependants);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!existingFeatureContext) {
|
|
||||||
featureContext.register();
|
|
||||||
}
|
|
||||||
|
|
||||||
feature.dependencies?.forEach((dependency) => {
|
|
||||||
registerFeatureRecursed(di, dependency, feature);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
||||||
const featureContextInjectable = getInjectable({
|
const featureContextInjectable = getInjectable({
|
||||||
id: feature.id,
|
id: feature.id,
|
||||||
@ -88,3 +36,45 @@ const createFeatureContext = (feature: Feature, di: DiContainer) => {
|
|||||||
|
|
||||||
return featureContext;
|
return featureContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const registerFeatureRecursed = (di: DiContainer, feature: Feature, dependedBy?: Feature) => {
|
||||||
|
const featureContextMaps = di.injectMany(featureContextMapInjectionToken);
|
||||||
|
|
||||||
|
if (featureContextMaps.length === 0) {
|
||||||
|
di.register(featureContextMapInjectable);
|
||||||
|
}
|
||||||
|
|
||||||
|
const featureContextMap = di.inject(featureContextMapInjectable);
|
||||||
|
|
||||||
|
const existingFeatureContext = featureContextMap.get(feature);
|
||||||
|
|
||||||
|
if (!dependedBy && existingFeatureContext && existingFeatureContext.dependedBy.size === 0) {
|
||||||
|
throw new Error(`Tried to register feature "${feature.id}", but it was already registered.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const featureContext = existingFeatureContext || createFeatureContext(feature, di);
|
||||||
|
|
||||||
|
featureContext.numberOfRegistrations++;
|
||||||
|
|
||||||
|
if (dependedBy) {
|
||||||
|
const oldNumberOfDependents = featureContext.dependedBy.get(dependedBy) || 0;
|
||||||
|
|
||||||
|
const newNumberOfDependants = oldNumberOfDependents + 1;
|
||||||
|
|
||||||
|
featureContext.dependedBy.set(dependedBy, newNumberOfDependants);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingFeatureContext) {
|
||||||
|
featureContext.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
feature.dependencies?.forEach((dependency) => {
|
||||||
|
registerFeatureRecursed(di, dependency, feature);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const registerFeature = (di: DiContainer, ...features: Feature[]) => {
|
||||||
|
features.forEach((feature) => {
|
||||||
|
registerFeatureRecursed(di, feature);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import { registerFeature } from "./register-feature";
|
import { registerFeature } from "./register-feature";
|
||||||
import {
|
import { createContainer, DiContainer, getInjectable, Injectable } from "@ogre-tools/injectable";
|
||||||
createContainer,
|
|
||||||
DiContainer,
|
|
||||||
getInjectable,
|
|
||||||
Injectable,
|
|
||||||
} from "@ogre-tools/injectable";
|
|
||||||
import type { Feature } from "./feature";
|
import type { Feature } from "./feature";
|
||||||
import { getFeature } from "./feature";
|
import { getFeature } from "./feature";
|
||||||
import { deregisterFeature } from "./deregister-feature";
|
import { deregisterFeature } from "./deregister-feature";
|
||||||
@ -90,9 +85,7 @@ describe("register-feature", () => {
|
|||||||
it("when a Feature is registered again, throws", () => {
|
it("when a Feature is registered again, throws", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
registerFeature(di, someFeature);
|
registerFeature(di, someFeature);
|
||||||
}).toThrow(
|
}).toThrow('Tried to register feature "some-feature-1", but it was already registered.');
|
||||||
'Tried to register feature "some-feature-1", but it was already registered.'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("given a Feature deregistered, when deregistered again, throws", () => {
|
it("given a Feature deregistered, when deregistered again, throws", () => {
|
||||||
@ -100,15 +93,14 @@ describe("register-feature", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
deregisterFeature(di, someFeature);
|
deregisterFeature(di, someFeature);
|
||||||
}).toThrow(
|
}).toThrow('Tried to deregister feature "some-feature-1", but it was not registered.');
|
||||||
'Tried to deregister feature "some-feature-1", but it was not registered.'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("given di-container and registered Features with injectables forming a cycle, when an injectable is injected, throws with namespaced error about cycle", () => {
|
it("given di-container and registered Features with injectables forming a cycle, when an injectable is injected, throws with namespaced error about cycle", () => {
|
||||||
const someInjectable: Injectable<any> = getInjectable({
|
const someInjectable: Injectable<any> = getInjectable({
|
||||||
id: "some-injectable-1",
|
id: "some-injectable-1",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||||
instantiate: (di) => di.inject(someInjectable2),
|
instantiate: (di) => di.inject(someInjectable2),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,8 +132,9 @@ describe("register-feature", () => {
|
|||||||
expect(() => {
|
expect(() => {
|
||||||
di.inject(someInjectable);
|
di.inject(someInjectable);
|
||||||
}).toThrow(
|
}).toThrow(
|
||||||
// 'Cycle of injectables encountered: "some-container" -> "some-feature-1:some-injectable-1" -> "some-feature-2:some-injectable-2" -> "some-feature-1:some-injectable-1"'
|
// 'Cycle of injectables encountered: "some-container" -> "some-feature-1:some-injectable-1"
|
||||||
'Maximum call stack size exceeded'
|
// -> "some-feature-2:some-injectable-2" -> "some-feature-1:some-injectable-1"'
|
||||||
|
"Maximum call stack size exceeded",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "@k8slens/typescript/config/base.json"
|
"extends": "@k8slens/typescript/config/base.json",
|
||||||
|
"include": ["**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user