From 0f1f030a06cb3625eb62194696547d4c4fb0d703 Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Tue, 21 Mar 2023 11:38:43 +0200 Subject: [PATCH] Switch to using messaging and startable stoppable from NPM package (#7368) * Add custom jest resolver to fix requiring "uuid" module Signed-off-by: Janne Savolainen * Update dependencies Signed-off-by: Janne Savolainen * Introduce test utils for rendering and running with thrown mobx reactions Signed-off-by: Janne Savolainen * Extract startable-stoppable to NPM package Signed-off-by: Janne Savolainen * Extract messaging to NPM package Co-authored-by: Mikko Aspiala Signed-off-by: Janne Savolainen * Switch to using startable-stoppable from NPM package Signed-off-by: Janne Savolainen * Switch to using messaging from the Feature Signed-off-by: Janne Savolainen * Remove old implementation of messaging Signed-off-by: Janne Savolainen * Make setupping app paths happen earlier in renderer Signed-off-by: Janne Savolainen * Fix typo Signed-off-by: Janne Savolainen * Add kludge to make testing-library work properly from test-utils package Signed-off-by: Janne Savolainen * Fix code style Signed-off-by: Janne Savolainen * Add lint:fix -root script Signed-off-by: Janne Savolainen * Fix unrelated failing unit tests Signed-off-by: Janne Savolainen * Turn of no-floating-promises from typescript linting for being broken Signed-off-by: Janne Savolainen * Make linting not happen for dist -directories Signed-off-by: Janne Savolainen * Make linting failures appear as failure Signed-off-by: Janne Savolainen * Stop running prettier twice It already gets ran as eslint-plugin. Signed-off-by: Janne Savolainen * Make CI run unit tests for all packages by consolidating name of NPM script Co-authored-by: Mikko Aspiala Signed-off-by: Janne Savolainen * Add missing unit tests for coverage Co-authored-by: Mikko Aspiala Signed-off-by: Janne Savolainen * Skip coverage for test utils Co-authored-by: Mikko Aspiala Signed-off-by: Janne Savolainen * Remove check for coverage in packages which are not ready for it Signed-off-by: Janne Savolainen * Stop collecting coverage from index.ts files them being indirections to the implementation Co-authored-by: Mikko Aspiala Signed-off-by: Janne Savolainen * Implement sending message to channel in main Signed-off-by: Janne Savolainen * Add missing feature dependencies Signed-off-by: Janne Savolainen * Add dummy implementations for requesting in main from renderer Signed-off-by: Janne Savolainen * Re-enable communicating from main to cluster frames Signed-off-by: Janne Savolainen * Ignore trivial files from coverage Signed-off-by: Janne Savolainen * Update package-lock Signed-off-by: Janne Savolainen * Extract message-bridge to separate NPM package to prevent dev dependencies being in the production bundle Signed-off-by: Janne Savolainen * Extract computed channel to own NPM package for clear dependencies Signed-off-by: Janne Savolainen * Consolidate electron related stuff to a directory Signed-off-by: Janne Savolainen * Add missing publish configurations Signed-off-by: Janne Savolainen * Ignore test implementation from coverage being not interesting Signed-off-by: Janne Savolainen --------- Signed-off-by: Janne Savolainen --- package-lock.json | 1200 +++++++++++------ package.json | 1 + packages/core/package.json | 5 + .../src/common/app-paths/app-paths-channel.ts | 8 +- .../core/src/common/base-store/base-store.ts | 3 +- .../lens-proxy-certificate-channel.ts | 2 +- .../cluster-store/cluster-store.injectable.ts | 2 +- .../common/cluster/current-cluster-channel.ts | 2 +- .../src/common/cluster/visibility-channel.ts | 2 +- .../app-navigation-channel.ts | 2 +- .../cluster-frame-navigation-channel.ts | 2 +- .../helm/add-helm-repository-channel.ts | 13 +- .../get-active-helm-repositories-channel.ts | 11 +- .../helm/remove-helm-repository-channel.ts | 11 +- .../src/common/hotbars/store.injectable.ts | 2 +- .../core/src/common/kube-helpers/channels.ts | 24 +- .../root-frame/root-frame-rendered-channel.ts | 2 +- .../user-store/user-store.injectable.ts | 2 +- .../src/common/utils/channel/channel.test.ts | 245 ---- ...essage-channel-listener-injection-token.ts | 13 - .../utils/channel/get-request-channel.ts | 9 - ...istening-on-message-channels.injectable.ts | 25 - ...essage-channel-listener-injection-token.ts | 51 - ...equest-channel-listener-injection-token.ts | 10 - .../resolve-system-proxy-channel.ts | 10 +- .../sync-box/channel-listener.injectable.ts | 4 +- .../src/common/utils/sync-box/channels.ts | 18 +- .../sync-box/create-sync-box.injectable.ts | 2 +- .../utils/sync-box/handler.injectable.ts | 19 - .../vars/build-semantic-version.injectable.ts | 2 +- .../weblink-store.injectable.ts | 2 +- ...ile-system-provisioner-store.injectable.ts | 2 +- .../core/src/extensions/extension-store.ts | 2 +- .../extensions-store.injectable.ts | 2 +- .../application-menu-reactivity.injectable.ts | 2 +- ...periodical-check-for-updates.injectable.ts | 2 +- .../restart-and-install-update-channel.ts | 2 +- ...-and-install-update-listener.injectable.ts | 4 +- ...update-should-happen-on-quit.injectable.ts | 2 +- .../restart-and-install-update.injectable.ts | 4 +- .../certificate-authorities/common/channel.ts | 3 +- ...-handler.global-override-for-injectable.ts | 1 + .../main/channel-handler.injectable.ts | 5 +- .../renderer/request-system-cas.injectable.ts | 2 +- .../cluster/activation/common/channels.ts | 2 +- .../activation/common/request-token.ts | 2 +- .../main/activate-listener.injectable.ts | 5 +- .../main/deactivate-listener.injectable.ts | 5 +- .../renderer/request-activation.injectable.ts | 4 +- .../request-deactivation.injectable.ts | 4 +- .../common/clear-as-deleting-channel.ts | 10 +- .../delete-dialog/common/delete-channel.ts | 9 +- .../common/set-as-deleting-channel.ts | 10 +- ...as-deleting-channel-listener.injectable.ts | 5 +- .../delete-channel-listener.injectable.ts | 5 +- ...s-deleteing-channel-listener.injectable.ts | 5 +- .../request-clear-as-deleting.injectable.ts | 4 +- .../renderer/request-delete.injectable.ts | 4 +- .../request-set-as-deleting.injectable.ts | 4 +- .../cluster/state-sync/common/channels.ts | 3 +- .../state-sync/main/emit-update.injectable.ts | 10 +- .../main/handle-initial.injectable.ts | 5 +- .../renderer/listener.injectable.ts | 4 +- .../renderer/request-initial.injectable.ts | 6 +- .../extensions/navigate/common/channel.ts | 2 +- .../navigate/renderer/listener.injectable.ts | 6 +- .../active-helm-repositories.injectable.ts | 2 +- .../add-helm-repository.injectable.ts | 2 +- .../remove-helm-repository.injectable.ts | 2 +- .../navigation/reload-page/common/channel.ts | 2 +- ...listener.global-override-for-injectable.ts | 1 + .../renderer/register-listener.injectable.ts | 4 +- .../path-picking-dialog/common/channel.ts | 2 +- .../main/handle-pick-paths.injectable.ts | 5 +- .../renderer/pick-paths.injectable.ts | 4 +- .../shell-sync/common/failure-channel.ts | 2 +- .../main/emit-failure.injectable.ts | 7 +- .../renderer/failure-listener.injectable.ts | 4 +- .../theme/system-type/common/channels.ts | 3 +- .../main/emit-update.injectable.ts | 10 +- .../main/handle-initial.injectable.ts | 5 +- .../renderer/request-initial.injectable.ts | 6 +- .../renderer/update-listener.injectable.ts | 4 +- packages/core/src/jest-after-env.setup.ts | 5 + ...ths-request-channel-listener.injectable.ts | 5 +- .../build-version/setup-channel.injectable.ts | 5 +- .../catalog-sync-to-renderer.injectable.ts | 2 +- .../cluster/visibility-handler.injectable.ts | 4 +- ...-theme-from-operating-system.injectable.ts | 2 +- packages/core/src/main/getDiForUnitTesting.ts | 7 + ...-repository-channel-listener.injectable.ts | 12 +- .../add-helm-repository.injectable.ts | 11 +- ...epositories-channel-listener.injectable.ts | 5 +- ...-repository-channel-listener.injectable.ts | 5 +- .../ipc/ask-user-for-file-paths.injectable.ts | 2 +- .../kubectl/apply-all-handler.injectable.ts | 5 +- .../kubectl/delete-all-handler.injectable.ts | 5 +- ...-certificate-request-handler.injectable.ts | 5 +- .../listener.injectable.ts | 10 +- .../channel-listener.injectable.ts | 4 +- .../tray/menu-icon/reactive.injectable.ts | 2 +- .../reactive-tray-menu-items.injectable.ts | 2 +- ...ist-message-channel-listener.injectable.ts | 32 - ...istening-on-request-channels.injectable.ts | 34 - .../start-listening-on-channels.injectable.ts | 26 - .../channel/message-to-channel.injectable.ts | 32 - .../utils/channel/message-to-channel.test.ts | 115 -- ...stem-proxy-channel-responder.injectable.ts | 5 +- ...itial-value-channel-listener.injectable.ts | 5 +- .../app-paths/setup-app-paths.injectable.ts | 6 +- ...up-current-cluster-broadcast.injectable.ts | 2 +- ...quest-lens-proxy-certificate.injectable.ts | 4 +- .../attempt-install-by-info.injectable.tsx | 1 + .../cluster-manager/cluster-frame-handler.ts | 3 +- .../emit-cluster-visibility.injectable.ts | 10 +- .../test-utils/get-application-builder.tsx | 18 +- ...-that-root-frame-is-rendered.injectable.ts | 2 +- .../core/src/renderer/getDiForUnitTesting.tsx | 9 +- .../renderer/kubectl/apply-all.injectable.ts | 4 +- .../renderer/kubectl/delete-all.injectable.ts | 4 +- .../navigation-channel-listener.injectable.ts | 11 +- .../start-listening-of-channels.injectable.ts | 23 - .../channel/message-to-channel.injectable.ts | 24 - .../request-from-channel.injectable.ts | 22 - .../utils/channel/send-to-main.injectable.ts | 20 - .../initialize-state.injectable.ts | 4 +- .../resolve-system-proxy.injectable.ts | 4 +- ...nitial-values-for-sync-boxes.injectable.ts | 2 +- .../build-version/build-version.injectable.ts | 2 +- .../channel-fakes/override-channels.ts | 29 - .../override-messaging-from-main-to-window.ts | 79 -- .../override-messaging-from-window-to-main.ts | 53 - ...override-requesting-from-window-to-main.ts | 60 - .../infrastructure/eslint-config/bin/lint | 10 +- .../eslint-config/eslint-config.js | 3 +- .../infrastructure/jest/jest-28-resolver.js | 34 + .../jest/monorepo-package-config.js | 6 + .../legacy-extension-example/jest.config.js | 3 +- .../legacy-extension-example/package.json | 1 - packages/open-lens/package.json | 4 + packages/open-lens/src/main/index.ts | 3 +- packages/open-lens/src/renderer/index.ts | 3 +- .../application/agnostic/index.ts | 4 +- .../application/agnostic/package.json | 2 +- ...lication-information-token.no-coverage.ts} | 0 .../start-application.injectable.ts | 13 +- .../starting-of-application.test.ts | 29 +- .../application/electron-main/index.ts | 2 +- .../application/electron-main/package.json | 2 +- .../override-side-effects-with-fakes.ts | 2 +- .../legacy-extensions/jest.config.js | 3 +- .../legacy-extensions/package.json | 1 - .../feature-core/package.json | 2 +- .../messaging/agnostic/.eslintrc.json | 6 + .../messaging/agnostic/.prettierrc | 1 + .../messaging/agnostic/index.ts | 2 + .../messaging/agnostic/jest.config.js | 1 + .../messaging/agnostic/package.json | 49 + .../features/actual/channel.no-coverage.ts} | 7 - .../agnostic/src/features/actual/feature.ts | 18 + .../agnostic/src/features/actual/index.ts | 53 + .../listening-of-channels.injectable.ts | 106 ++ .../start-listening-of-channels.injectable.ts | 21 + ...essage-channel-listener-injection-token.ts | 15 + .../actual/message/get-message-channel.ts | 5 + ...essage-channel-listener-injection-token.ts | 51 + .../message-to-channel-injection-token.ts | 10 - ...equest-channel-listener-injection-token.ts | 15 + .../actual/request/get-request-channel.ts | 7 + ...quest-channel-listener-injection-token.ts} | 42 +- .../request-from-channel-injection-token.ts | 16 +- .../src/features/unit-testing/feature.ts | 18 + .../src/features/unit-testing/index.ts | 1 + .../unit-testing/test-doubles.injectable.ts | 31 + .../src/listening-of-messages.test.ts | 169 +++ .../src/listening-of-requests.test.ts | 204 +++ .../messaging/agnostic/tsconfig.json | 4 + .../messaging/agnostic/webpack.config.js | 1 + .../messaging/computed-channel/.eslintrc.json | 6 + .../messaging/computed-channel/.prettierrc | 1 + .../messaging/computed-channel/index.ts | 12 + .../messaging/computed-channel/jest.config.js | 1 + .../messaging/computed-channel/package.json | 51 + ...annel-administration-channel.injectable.ts | 64 + .../computed-channel.injectable.ts | 110 ++ .../computed-channel.test.tsx | 571 ++++++++ ...icate-channel-observer-guard.injectable.ts | 42 + .../messaging/computed-channel/src/feature.ts | 18 + .../messaging/computed-channel/tsconfig.json | 4 + .../computed-channel/webpack.config.js | 1 + .../messaging/electron/main/.eslintrc.json | 6 + .../messaging/electron/main/.prettierrc | 1 + .../messaging/electron/main/index.ts | 1 + .../messaging/electron/main/jest.config.js | 1 + .../messaging/electron/main/package.json | 47 + ...ist-message-channel-listener.injectable.ts | 28 + .../enlist-message-channel-listener.test.ts | 44 +- ...ist-request-channel-listener.injectable.ts | 19 +- .../enlist-request-channel-listener.test.ts | 28 +- .../messaging/electron/main/src/feature.ts | 18 + .../main/src/ipc-main/ipc-main.injectable.ts | 10 + .../main/src/ipc-main/ipc-main.test.ts | 21 + .../request-from-channel.injectable.ts | 23 + ...allow-communication-listener.injectable.ts | 21 + .../frameIds.injectable.ts | 8 + .../get-web-contents.injectable.ts | 12 + ...send-message-to-channel.injectable.test.ts | 121 ++ .../send-message-to-channel.injectable.ts | 48 + .../messaging/electron/main/tsconfig.json | 4 + .../messaging/electron/main/webpack.config.js | 1 + .../electron/renderer/.eslintrc.json | 6 + .../messaging/electron/renderer/.prettierrc | 1 + .../messaging/electron/renderer/index.ts | 1 + .../electron/renderer/jest.config.js | 1 + .../messaging/electron/renderer/package.json | 48 + ...llow-communication-to-iframe.injectable.ts | 25 + .../src/allow-communication-to-iframe.test.ts | 35 + .../electron/renderer/src/feature.ts | 18 + .../src/ipc/ipc-renderer.injectable.ts | 10 + .../renderer/src/ipc/ipc-renderer.test.ts | 27 + ...ist-message-channel-listener.injectable.ts | 8 +- .../enlist-message-channel-listener.test.ts | 30 +- ...ist-request-channel-listener.injectable.ts | 18 + .../invoke-ipc.injectable.ts | 10 + .../requesting-of-requests/invoke-ipc.test.ts | 21 + .../request-from-channel.injectable.ts | 18 + .../request-from-channel.test.ts | 46 + .../message-to-channel.injectable.ts | 19 + .../message-to-channel.test.ts | 38 + .../send-to-ipc.injectable.ts | 10 + .../sending-of-messages/send-to-ipc.test.ts | 21 + .../messaging/electron/renderer/tsconfig.json | 4 + .../electron/renderer/webpack.config.js | 1 + .../message-bridge-fake/.eslintrc.json | 6 + .../messaging/message-bridge-fake/.prettierrc | 1 + .../messaging/message-bridge-fake/index.ts | 3 + .../message-bridge-fake/jest.config.js | 1 + .../message-bridge-fake/package.json | 49 + .../get-message-bridge-fake.test.ts | 397 ++++++ .../get-message-bridge-fake.ts | 196 +++ .../message-bridge-fake/tsconfig.json | 4 + .../message-bridge-fake/webpack.config.js | 1 + .../utility-features/run-many/jest.config.js | 5 +- .../utility-features/run-many/package.json | 4 +- .../startable-stoppable/.eslintrc.json | 6 + .../startable-stoppable/.prettierrc | 1 + .../startable-stoppable/index.ts | 3 + .../startable-stoppable/jest.config.js | 1 + .../startable-stoppable/package.json | 38 + .../src}/get-startable-stoppable.test.ts | 10 +- .../src}/get-startable-stoppable.ts | 5 - .../startable-stoppable/tsconfig.json | 4 + .../startable-stoppable/webpack.config.js | 1 + packages/utility-features/test-utils/index.ts | 2 + .../utility-features/test-utils/package.json | 8 +- .../test-utils/src/render-for.tsx | 24 + .../src/run-with-thrown-mobx-reactions.ts | 38 + .../utility-features/utilities/jest.config.js | 5 +- .../utility-features/utilities/package.json | 5 +- .../utilities/src/splitArray.test.ts | 24 +- .../utilities/src/union-env-path.test.ts | 2 +- 261 files changed, 4447 insertions(+), 1795 deletions(-) delete mode 100644 packages/core/src/common/utils/channel/channel.test.ts delete mode 100644 packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts delete mode 100644 packages/core/src/common/utils/channel/get-request-channel.ts delete mode 100644 packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts delete mode 100644 packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts delete mode 100644 packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts delete mode 100644 packages/core/src/common/utils/sync-box/handler.injectable.ts delete mode 100644 packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts delete mode 100644 packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts delete mode 100644 packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts delete mode 100644 packages/core/src/main/utils/channel/message-to-channel.injectable.ts delete mode 100644 packages/core/src/main/utils/channel/message-to-channel.test.ts delete mode 100644 packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts delete mode 100644 packages/core/src/renderer/utils/channel/message-to-channel.injectable.ts delete mode 100644 packages/core/src/renderer/utils/channel/request-from-channel.injectable.ts delete mode 100644 packages/core/src/renderer/utils/channel/send-to-main.injectable.ts delete mode 100644 packages/core/src/test-utils/channel-fakes/override-channels.ts delete mode 100644 packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts delete mode 100644 packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts delete mode 100644 packages/core/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts create mode 100644 packages/infrastructure/jest/jest-28-resolver.js rename packages/technical-features/application/agnostic/src/{application-information-token.ts => application-information-token.no-coverage.ts} (100%) rename packages/technical-features/application/electron-main/src/{ => test-utils}/override-side-effects-with-fakes.ts (69%) create mode 100644 packages/technical-features/messaging/agnostic/.eslintrc.json create mode 100644 packages/technical-features/messaging/agnostic/.prettierrc create mode 100644 packages/technical-features/messaging/agnostic/index.ts create mode 100644 packages/technical-features/messaging/agnostic/jest.config.js create mode 100644 packages/technical-features/messaging/agnostic/package.json rename packages/{core/src/common/utils/channel/channel-injection-token.ts => technical-features/messaging/agnostic/src/features/actual/channel.no-coverage.ts} (52%) create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/feature.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/index.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/listening-of-channels.injectable.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/start-listening-of-channels.injectable.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/message/enlist-message-channel-listener-injection-token.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/message/get-message-channel.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/message/message-channel-listener-injection-token.ts rename packages/{core/src/common/utils/channel => technical-features/messaging/agnostic/src/features/actual/message}/message-to-channel-injection-token.ts (55%) create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/request/enlist-request-channel-listener-injection-token.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/actual/request/get-request-channel.ts rename packages/{core/src/main/utils/channel/channel-listeners/listener-tokens.ts => technical-features/messaging/agnostic/src/features/actual/request/request-channel-listener-injection-token.ts} (56%) rename packages/{core/src/common/utils/channel => technical-features/messaging/agnostic/src/features/actual/request}/request-from-channel-injection-token.ts (53%) create mode 100644 packages/technical-features/messaging/agnostic/src/features/unit-testing/feature.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/unit-testing/index.ts create mode 100644 packages/technical-features/messaging/agnostic/src/features/unit-testing/test-doubles.injectable.ts create mode 100644 packages/technical-features/messaging/agnostic/src/listening-of-messages.test.ts create mode 100644 packages/technical-features/messaging/agnostic/src/listening-of-requests.test.ts create mode 100644 packages/technical-features/messaging/agnostic/tsconfig.json create mode 100644 packages/technical-features/messaging/agnostic/webpack.config.js create mode 100644 packages/technical-features/messaging/computed-channel/.eslintrc.json create mode 100644 packages/technical-features/messaging/computed-channel/.prettierrc create mode 100644 packages/technical-features/messaging/computed-channel/index.ts create mode 100644 packages/technical-features/messaging/computed-channel/jest.config.js create mode 100644 packages/technical-features/messaging/computed-channel/package.json create mode 100644 packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts create mode 100644 packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts create mode 100644 packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx create mode 100644 packages/technical-features/messaging/computed-channel/src/computed-channel/duplicate-channel-observer-guard.injectable.ts create mode 100644 packages/technical-features/messaging/computed-channel/src/feature.ts create mode 100644 packages/technical-features/messaging/computed-channel/tsconfig.json create mode 100644 packages/technical-features/messaging/computed-channel/webpack.config.js create mode 100644 packages/technical-features/messaging/electron/main/.eslintrc.json create mode 100644 packages/technical-features/messaging/electron/main/.prettierrc create mode 100644 packages/technical-features/messaging/electron/main/index.ts create mode 100644 packages/technical-features/messaging/electron/main/jest.config.js create mode 100644 packages/technical-features/messaging/electron/main/package.json create mode 100644 packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.injectable.ts rename packages/{core/src/main/utils/channel => technical-features/messaging/electron/main/src}/channel-listeners/enlist-message-channel-listener.test.ts (59%) rename packages/{core/src/main/utils/channel => technical-features/messaging/electron/main/src}/channel-listeners/enlist-request-channel-listener.injectable.ts (53%) rename packages/{core/src/main/utils/channel => technical-features/messaging/electron/main/src}/channel-listeners/enlist-request-channel-listener.test.ts (86%) create mode 100644 packages/technical-features/messaging/electron/main/src/feature.ts create mode 100644 packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.test.ts create mode 100644 packages/technical-features/messaging/electron/main/src/request-from-channel/request-from-channel.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/src/send-message-to-channel/allow-communication-listener.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/src/send-message-to-channel/frameIds.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/src/send-message-to-channel/get-web-contents.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts create mode 100644 packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.ts create mode 100644 packages/technical-features/messaging/electron/main/tsconfig.json create mode 100644 packages/technical-features/messaging/electron/main/webpack.config.js create mode 100644 packages/technical-features/messaging/electron/renderer/.eslintrc.json create mode 100644 packages/technical-features/messaging/electron/renderer/.prettierrc create mode 100644 packages/technical-features/messaging/electron/renderer/index.ts create mode 100644 packages/technical-features/messaging/electron/renderer/jest.config.js create mode 100644 packages/technical-features/messaging/electron/renderer/package.json create mode 100644 packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.test.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/feature.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.test.ts rename packages/{core/src/renderer/utils/channel/channel-listeners => technical-features/messaging/electron/renderer/src/listening-of-messages}/enlist-message-channel-listener.injectable.ts (67%) rename packages/{core/src/renderer/utils/channel/channel-listeners => technical-features/messaging/electron/renderer/src/listening-of-messages}/enlist-message-channel-listener.test.ts (73%) create mode 100644 packages/technical-features/messaging/electron/renderer/src/listening-of-requests/enlist-request-channel-listener.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.test.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.test.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.test.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.injectable.ts create mode 100644 packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.test.ts create mode 100644 packages/technical-features/messaging/electron/renderer/tsconfig.json create mode 100644 packages/technical-features/messaging/electron/renderer/webpack.config.js create mode 100644 packages/technical-features/messaging/message-bridge-fake/.eslintrc.json create mode 100644 packages/technical-features/messaging/message-bridge-fake/.prettierrc create mode 100644 packages/technical-features/messaging/message-bridge-fake/index.ts create mode 100644 packages/technical-features/messaging/message-bridge-fake/jest.config.js create mode 100644 packages/technical-features/messaging/message-bridge-fake/package.json create mode 100644 packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.test.ts create mode 100644 packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.ts create mode 100644 packages/technical-features/messaging/message-bridge-fake/tsconfig.json create mode 100644 packages/technical-features/messaging/message-bridge-fake/webpack.config.js create mode 100644 packages/utility-features/startable-stoppable/.eslintrc.json create mode 100644 packages/utility-features/startable-stoppable/.prettierrc create mode 100644 packages/utility-features/startable-stoppable/index.ts create mode 100644 packages/utility-features/startable-stoppable/jest.config.js create mode 100644 packages/utility-features/startable-stoppable/package.json rename packages/{core/src/common/utils => utility-features/startable-stoppable/src}/get-startable-stoppable.test.ts (84%) rename packages/{core/src/common/utils => utility-features/startable-stoppable/src}/get-startable-stoppable.ts (86%) create mode 100644 packages/utility-features/startable-stoppable/tsconfig.json create mode 100644 packages/utility-features/startable-stoppable/webpack.config.js create mode 100644 packages/utility-features/test-utils/src/render-for.tsx create mode 100644 packages/utility-features/test-utils/src/run-with-thrown-mobx-reactions.ts diff --git a/package-lock.json b/package-lock.json index b59d132b39..fc13b55540 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,20 +73,20 @@ } }, "node_modules/@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", + "@babel/generator": "^7.21.0", "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", + "@babel/helper-module-transforms": "^7.21.0", "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", + "@babel/parser": "^7.21.0", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -115,9 +115,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz", - "integrity": "sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -151,11 +151,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", "dependencies": { - "@babel/types": "^7.21.3", + "@babel/types": "^7.21.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -595,9 +595,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1269,9 +1269,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", + "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" @@ -1523,9 +1523,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" @@ -1754,12 +1754,11 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", - "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz", + "integrity": "sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg==", "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-typescript": "^7.20.0" @@ -1997,18 +1996,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", + "@babel/generator": "^7.21.1", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2017,9 +2016,9 @@ } }, "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -2685,9 +2684,9 @@ "dev": true }, "node_modules/@esbuild/android-arm": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.12.tgz", - "integrity": "sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.11.tgz", + "integrity": "sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw==", "cpu": [ "arm" ], @@ -2701,9 +2700,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.12.tgz", - "integrity": "sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz", + "integrity": "sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg==", "cpu": [ "arm64" ], @@ -2717,9 +2716,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.12.tgz", - "integrity": "sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.11.tgz", + "integrity": "sha512-3PL3HKtsDIXGQcSCKtWD/dy+mgc4p2Tvo2qKgKHj9Yf+eniwFnuoQ0OUhlSfAEpKAFzF9N21Nwgnap6zy3L3MQ==", "cpu": [ "x64" ], @@ -2733,9 +2732,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.12.tgz", - "integrity": "sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz", + "integrity": "sha512-pJ950bNKgzhkGNO3Z9TeHzIFtEyC2GDQL3wxkMApDEghYx5Qers84UTNc1bAxWbRkuJOgmOha5V0WUeh8G+YGw==", "cpu": [ "arm64" ], @@ -2749,9 +2748,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.12.tgz", - "integrity": "sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz", + "integrity": "sha512-iB0dQkIHXyczK3BZtzw1tqegf0F0Ab5texX2TvMQjiJIWXAfM4FQl7D909YfXWnB92OQz4ivBYQ2RlxBJrMJOw==", "cpu": [ "x64" ], @@ -2765,9 +2764,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.12.tgz", - "integrity": "sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz", + "integrity": "sha512-7EFzUADmI1jCHeDRGKgbnF5sDIceZsQGapoO6dmw7r/ZBEKX7CCDnIz8m9yEclzr7mFsd+DyasHzpjfJnmBB1Q==", "cpu": [ "arm64" ], @@ -2781,9 +2780,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.12.tgz", - "integrity": "sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz", + "integrity": "sha512-iPgenptC8i8pdvkHQvXJFzc1eVMR7W2lBPrTE6GbhR54sLcF42mk3zBOjKPOodezzuAz/KSu8CPyFSjcBMkE9g==", "cpu": [ "x64" ], @@ -2797,9 +2796,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.12.tgz", - "integrity": "sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz", + "integrity": "sha512-M9iK/d4lgZH0U5M1R2p2gqhPV/7JPJcRz+8O8GBKVgqndTzydQ7B2XGDbxtbvFkvIs53uXTobOhv+RyaqhUiMg==", "cpu": [ "arm" ], @@ -2813,9 +2812,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.12.tgz", - "integrity": "sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz", + "integrity": "sha512-Qxth3gsWWGKz2/qG2d5DsW/57SeA2AmpSMhdg9TSB5Svn2KDob3qxfQSkdnWjSd42kqoxIPy3EJFs+6w1+6Qjg==", "cpu": [ "arm64" ], @@ -2829,9 +2828,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.12.tgz", - "integrity": "sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz", + "integrity": "sha512-dB1nGaVWtUlb/rRDHmuDQhfqazWE0LMro/AIbT2lWM3CDMHJNpLckH+gCddQyhhcLac2OYw69ikUMO34JLt3wA==", "cpu": [ "ia32" ], @@ -2845,9 +2844,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.12.tgz", - "integrity": "sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz", + "integrity": "sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g==", "cpu": [ "loong64" ], @@ -2861,9 +2860,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.12.tgz", - "integrity": "sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz", + "integrity": "sha512-cGeGNdQxqY8qJwlYH1BP6rjIIiEcrM05H7k3tR7WxOLmD1ZxRMd6/QIOWMb8mD2s2YJFNRuNQ+wjMhgEL2oCEw==", "cpu": [ "mips64el" ], @@ -2877,9 +2876,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.12.tgz", - "integrity": "sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz", + "integrity": "sha512-BdlziJQPW/bNe0E8eYsHB40mYOluS+jULPCjlWiHzDgr+ZBRXPtgMV1nkLEGdpjrwgmtkZHEGEPaKdS/8faLDA==", "cpu": [ "ppc64" ], @@ -2893,9 +2892,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.12.tgz", - "integrity": "sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz", + "integrity": "sha512-MDLwQbtF+83oJCI1Cixn68Et/ME6gelmhssPebC40RdJaect+IM+l7o/CuG0ZlDs6tZTEIoxUe53H3GmMn8oMA==", "cpu": [ "riscv64" ], @@ -2909,9 +2908,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.12.tgz", - "integrity": "sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz", + "integrity": "sha512-4N5EMESvws0Ozr2J94VoUD8HIRi7X0uvUv4c0wpTHZyZY9qpaaN7THjosdiW56irQ4qnJ6Lsc+i+5zGWnyqWqQ==", "cpu": [ "s390x" ], @@ -2925,9 +2924,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.12.tgz", - "integrity": "sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz", + "integrity": "sha512-rM/v8UlluxpytFSmVdbCe1yyKQd/e+FmIJE2oPJvbBo+D0XVWi1y/NQ4iTNx+436WmDHQBjVLrbnAQLQ6U7wlw==", "cpu": [ "x64" ], @@ -2941,9 +2940,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.12.tgz", - "integrity": "sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz", + "integrity": "sha512-4WaAhuz5f91h3/g43VBGdto1Q+X7VEZfpcWGtOFXnggEuLvjV+cP6DyLRU15IjiU9fKLLk41OoJfBFN5DhPvag==", "cpu": [ "x64" ], @@ -2957,9 +2956,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.12.tgz", - "integrity": "sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz", + "integrity": "sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w==", "cpu": [ "x64" ], @@ -2973,9 +2972,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.12.tgz", - "integrity": "sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz", + "integrity": "sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg==", "cpu": [ "x64" ], @@ -2989,9 +2988,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.12.tgz", - "integrity": "sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz", + "integrity": "sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ==", "cpu": [ "arm64" ], @@ -3005,9 +3004,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.12.tgz", - "integrity": "sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz", + "integrity": "sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw==", "cpu": [ "ia32" ], @@ -3021,9 +3020,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.12.tgz", - "integrity": "sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz", + "integrity": "sha512-N9vXqLP3eRL8BqSy8yn4Y98cZI2pZ8fyuHx6lKjiG2WABpT2l01TXdzq5Ma2ZUBzfB7tx5dXVhge8X9u0S70ZQ==", "cpu": [ "x64" ], @@ -3037,9 +3036,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", + "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -3114,24 +3113,25 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.4.tgz", - "integrity": "sha512-SQOeVbMwb1di+mVWWJLpsUTToKfqVNioXys011beCAhyOIFtS+GQoW4EQSneuxzmQKddExDwQ+X0hLl4lJJaSQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.3.tgz", + "integrity": "sha512-upVRtrNZuYNsw+EoxkiBFRPROnU8UTy/u/dZ9U0W14BlemPYODwhhxYXSR2Y9xOnvr1XtptJRWx7gL8Te1qaog==", "dev": true }, "node_modules/@floating-ui/dom": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.5.tgz", - "integrity": "sha512-+sAUfpQ3Frz+VCbPCqj+cZzvEESy3fjSeT/pDWkYCWOBXYNNKZfuVsHuv8/JO2zze8+Eb/Q7a6hZVgzS81fLbQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.4.tgz", + "integrity": "sha512-4+k+BLhtWj+peCU60gp0+rHeR8+Ohqx6kjJf/lHMnJ8JD5Qj6jytcq1+SZzRwD7rvHKRhR7TDiWWddrNrfwQLg==", "dev": true, "dependencies": { - "@floating-ui/core": "^1.2.4" + "@floating-ui/core": "^1.2.3" } }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true }, "node_modules/@hapi/b64": { "version": "5.0.0", @@ -3359,7 +3359,8 @@ "node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", - "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==" + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -4684,6 +4685,10 @@ "resolved": "packages/bump-version-for-cron", "link": true }, + "node_modules/@k8slens/computed-channel": { + "resolved": "packages/technical-features/messaging/computed-channel", + "link": true + }, "node_modules/@k8slens/core": { "resolved": "packages/core", "link": true @@ -4720,6 +4725,22 @@ "resolved": "packages/technical-features/application/legacy-extensions", "link": true }, + "node_modules/@k8slens/messaging": { + "resolved": "packages/technical-features/messaging/agnostic", + "link": true + }, + "node_modules/@k8slens/messaging-fake-bridge": { + "resolved": "packages/technical-features/messaging/message-bridge-fake", + "link": true + }, + "node_modules/@k8slens/messaging-for-main": { + "resolved": "packages/technical-features/messaging/electron/main", + "link": true + }, + "node_modules/@k8slens/messaging-for-renderer": { + "resolved": "packages/technical-features/messaging/electron/renderer", + "link": true + }, "node_modules/@k8slens/node-fetch": { "resolved": "packages/node-fetch", "link": true @@ -4736,6 +4757,10 @@ "resolved": "packages/semver", "link": true }, + "node_modules/@k8slens/startable-stoppable": { + "resolved": "packages/utility-features/startable-stoppable", + "link": true + }, "node_modules/@k8slens/test-utils": { "resolved": "packages/utility-features/test-utils", "link": true @@ -4778,6 +4803,11 @@ "openid-client": "^5.3.0" } }, + "node_modules/@kubernetes/client-node/node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -5180,6 +5210,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz", "integrity": "sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==", + "dev": true, "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -5227,6 +5258,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -5238,6 +5270,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -5246,6 +5279,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -5260,6 +5294,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -5274,6 +5309,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" @@ -5286,6 +5322,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", + "dev": true, "dependencies": { "@npmcli/promise-spawn": "^3.0.0", "lru-cache": "^7.4.4", @@ -5305,6 +5342,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -5313,6 +5351,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, "dependencies": { "npm-bundled": "^1.1.1", "npm-normalize-package-bin": "^1.0.1" @@ -5328,6 +5367,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz", "integrity": "sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg==", + "dev": true, "dependencies": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^8.0.1", @@ -5342,6 +5382,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -5350,6 +5391,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5368,6 +5410,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5379,6 +5422,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz", "integrity": "sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA==", + "dev": true, "dependencies": { "cacache": "^16.0.0", "json-parse-even-better-errors": "^2.3.1", @@ -5394,6 +5438,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -5406,6 +5451,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -5419,12 +5465,14 @@ "node_modules/@npmcli/name-from-folder": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", - "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==" + "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==", + "dev": true }, "node_modules/@npmcli/node-gyp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -5433,6 +5481,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz", "integrity": "sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.1" }, @@ -5444,6 +5493,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", + "dev": true, "dependencies": { "infer-owner": "^1.0.4" }, @@ -5455,6 +5505,7 @@ "version": "4.1.7", "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", + "dev": true, "dependencies": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", @@ -5470,6 +5521,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -5478,6 +5530,7 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -5504,6 +5557,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -5515,6 +5569,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -5531,6 +5586,7 @@ "version": "9.3.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -5554,6 +5610,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, "dependencies": { "abbrev": "^1.0.0" }, @@ -5568,6 +5625,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -5582,6 +5640,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -5594,21 +5653,22 @@ "node_modules/@npmcli/run-script/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/@nrwl/cli": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-15.8.7.tgz", - "integrity": "sha512-G1NEy4jGuZJ/7KjhLQNOe11XmoTgwJS82FW8Tbo4iceq2ItSEbe7bkA8xTSK/AzUixZIMimztb9Oyxw/n1ajGQ==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-15.8.6.tgz", + "integrity": "sha512-KrWoYcZgE6woCubPO1QSnwbZAjs2rdV4dotHxR+iRkeHRPAq0D6w83CVo5oP/krfUri2pxwzhnbkgAK1LSPBYg==", "dev": true, "dependencies": { - "nx": "15.8.7" + "nx": "15.8.6" } }, "node_modules/@nrwl/devkit": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.8.7.tgz", - "integrity": "sha512-A99nZrA5KN9wRn2uYX2vKByA+t2XEGoZBR5TU/bpXbPYrh92qAHkIJ8ke3ImGQOlzk4iIaZ5Me0k7k1p9Zx4wA==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.8.6.tgz", + "integrity": "sha512-yA5hBpeqoIlyEN5lUkejUrmB/5vfg+k6xoT4KhXnmj6bLPDGOYTuixg8k+iYrIAFIRMx0F8zYbYOYzXG3lmvHg==", "dev": true, "dependencies": { "@phenomnomnominal/tsquery": "4.1.1", @@ -5683,9 +5743,9 @@ "dev": true }, "node_modules/@nrwl/nx-darwin-arm64": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.8.7.tgz", - "integrity": "sha512-+cu8J337gRxUHjz2TGwS/2Oh3yw8d3/T6SoBfvee1DY72VQaeYd8UTz0doOhDtmc/zowvRu7ZVsW0ytNB0jIXQ==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.8.6.tgz", + "integrity": "sha512-8diQitlyjHxpkWcXNecd6T2ch8fHR7LOMaZg9+qgrt5AypWkEGf+UHMxTSNRObAiBGnoxySa+AL/UKVtpQ203Q==", "cpu": [ "arm64" ], @@ -5699,9 +5759,9 @@ } }, "node_modules/@nrwl/nx-darwin-x64": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.8.7.tgz", - "integrity": "sha512-VqHJEP0wgFu1MU0Bo1vKZ5/s7ThRfYkX8SyGUxjVTzR02CrsjC4rNxFoKD8Cc4YkUn44U/F78toGf+i2gRcjSQ==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.8.6.tgz", + "integrity": "sha512-h9/JULzPZTpt6oNpKMZLc1NGDu+CLyx91c8DJUh/hH0Zh/7dS9LFxe9jWeFIdh18iAu7ZAoktK2KJ5YhOrUYhA==", "cpu": [ "x64" ], @@ -5715,9 +5775,9 @@ } }, "node_modules/@nrwl/nx-linux-arm-gnueabihf": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.8.7.tgz", - "integrity": "sha512-4F/8awwqPTt7zKQolvjBNrcR1wYicPjGchLOdaqnfMxn/iRRUdh0hD11mEP5zHNv9gZs/nOIvhdBUErNjFkplQ==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.8.6.tgz", + "integrity": "sha512-Yp/YjzcIHW+OW4revPRZIt0Px9cKRsOL69FPLlYSxWuR/PD9SPeXWcbo3pKkjnIWIjOL2YT8z5cHiQ3bV1NVfw==", "cpu": [ "arm" ], @@ -5731,9 +5791,9 @@ } }, "node_modules/@nrwl/nx-linux-arm64-gnu": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.8.7.tgz", - "integrity": "sha512-3ZTSZx02Vv5emQOpaDROIcLtQucoXAe73zGKYDTXB95mxbOPSjjQJ8Rtx+BeqWq9JQoZZyRcD0qnBkTTy1aLRg==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.8.6.tgz", + "integrity": "sha512-b+OenpPhhxqgaG6EFHRLfVGtAU4+UbKqOhv7DLLh5P7tX3RAQAtyrT6tVkfDRFYl6kgEme/I5ZrevcbaGyDO+w==", "cpu": [ "arm64" ], @@ -5747,9 +5807,9 @@ } }, "node_modules/@nrwl/nx-linux-arm64-musl": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.8.7.tgz", - "integrity": "sha512-SZxTomiHxAh8El+swbmGSGcaA0vGbHb/rmhFAixo19INu1wBJfD6hjkVJt17h6PyEO7BIYPOpRia6Poxnyv8hA==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.8.6.tgz", + "integrity": "sha512-F9D8moy+lfJQhVrZoY54vDwpigBgxQy4HB9PRmc6Ln9mIk3ouOvKNC99OjUYEO+ensHr9eMpsbghsRCjod//uw==", "cpu": [ "arm64" ], @@ -5763,9 +5823,9 @@ } }, "node_modules/@nrwl/nx-linux-x64-gnu": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.8.7.tgz", - "integrity": "sha512-BlNC6Zz1/x6CFbBFTVrgRGMOPqb7zWh5cOjBVNpoBXYTEth1UXb2r1U+gpuQ4xdUqG+uXoWhy6BHJjqBIjzLJA==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.8.6.tgz", + "integrity": "sha512-an0zD6lKpblexazKssFvcfOx7BuGutwlrzmwScxISPXj5+ly99u+sYclDg2P56YRHYXIuYGBK0c0VWaJ91QIcw==", "cpu": [ "x64" ], @@ -5779,9 +5839,9 @@ } }, "node_modules/@nrwl/nx-linux-x64-musl": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.8.7.tgz", - "integrity": "sha512-FNYX/IKy8SUbw6bJpvwZrup2YQBYmSJwP6Rw76Vf7c32XHk7uA6AjiPWMIrZCSndXcry8fnwXvR+J2Dnyo82nQ==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.8.6.tgz", + "integrity": "sha512-LOurlSuLf9LWdjvpHHIsHC0auxgMVrkeOFFCUJ3oVv/dN4uZ0vuNG98XM2E7fPDXDacBZIyKdx34KQlmFfBHsA==", "cpu": [ "x64" ], @@ -5795,9 +5855,9 @@ } }, "node_modules/@nrwl/nx-win32-arm64-msvc": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.8.7.tgz", - "integrity": "sha512-sZALEzazjPAeLlw6IbFWsMidCZ4ZM3GKWZZ6rsAqG2y7I9t4nlUPH/y/Isl9MuLBvrBCBXbVnD20wh6EhtuwTw==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.8.6.tgz", + "integrity": "sha512-MvH84nLv1tdM96z92abeQd+tguY/zKC22AFHek9PSR1StUQzwwPu6rR7XDn3mggwnkLm11jTUXlk7wdbE5sldQ==", "cpu": [ "arm64" ], @@ -5811,9 +5871,9 @@ } }, "node_modules/@nrwl/nx-win32-x64-msvc": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.8.7.tgz", - "integrity": "sha512-VMdDptI2rqkLQRCvertF29QeA/V/MnFtHbsmVzMCEv5EUfrkHbA5LLxV66LLfngmkDT1FHktffztlsMpbxvhRw==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.8.6.tgz", + "integrity": "sha512-P0Sb4HJCeoeTvPFdUMKljRUIjzso0go36cn1Zpl+Z5CG/nbOvLlbnzh6rg15SRNu9OLWTHNPtyQIvKxjqEDoxg==", "cpu": [ "x64" ], @@ -5827,12 +5887,12 @@ } }, "node_modules/@nrwl/tao": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-15.8.7.tgz", - "integrity": "sha512-wA7QIEh0VwWcyo32Y/xSCTwnQTGcZupe933nResXv8mAb36W8MoR5SXRx+Wdd8fJ1eWlm2tuotIrslhN+lYx/Q==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-15.8.6.tgz", + "integrity": "sha512-dY205cotLiKTV+5BrUlneZEOucDmXiJU4asj1G4vQCf8Nt7awwuLYOmgbsACS27gkopSVV+DPl1zmtkSJX8Cjg==", "dev": true, "dependencies": { - "nx": "15.8.7" + "nx": "15.8.6" }, "bin": { "tao": "index.js" @@ -6581,9 +6641,9 @@ } }, "node_modules/@swc/core": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.41.tgz", - "integrity": "sha512-v6P2dfqJDpZ/7RXPvWge9oI6YgolDM0jtNhQZ2qdXrLBzaWQdDoBGBTJ8KN/nTgGhX3IkNvSB1fafXQ+nVnqAQ==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.40.tgz", + "integrity": "sha512-ZQJ+NID24PQkPIHnbO2B68YNQ6aMEyDz6dcsZucpRK4r7+aPqQ2yVLaqFcQU9VcGMyo4JJydmokzyTr1roWPIQ==", "hasInstallScript": true, "engines": { "node": ">=10" @@ -6593,22 +6653,22 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.41", - "@swc/core-darwin-x64": "1.3.41", - "@swc/core-linux-arm-gnueabihf": "1.3.41", - "@swc/core-linux-arm64-gnu": "1.3.41", - "@swc/core-linux-arm64-musl": "1.3.41", - "@swc/core-linux-x64-gnu": "1.3.41", - "@swc/core-linux-x64-musl": "1.3.41", - "@swc/core-win32-arm64-msvc": "1.3.41", - "@swc/core-win32-ia32-msvc": "1.3.41", - "@swc/core-win32-x64-msvc": "1.3.41" + "@swc/core-darwin-arm64": "1.3.40", + "@swc/core-darwin-x64": "1.3.40", + "@swc/core-linux-arm-gnueabihf": "1.3.40", + "@swc/core-linux-arm64-gnu": "1.3.40", + "@swc/core-linux-arm64-musl": "1.3.40", + "@swc/core-linux-x64-gnu": "1.3.40", + "@swc/core-linux-x64-musl": "1.3.40", + "@swc/core-win32-arm64-msvc": "1.3.40", + "@swc/core-win32-ia32-msvc": "1.3.40", + "@swc/core-win32-x64-msvc": "1.3.40" } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.41.tgz", - "integrity": "sha512-D4fybODToO/BvuP35bionDUrSuTVVr8eW+mApr1unOqb3mfiqOrVv0VP2fpWNRYiA+xMq+oBCB6KcGpL60HKWQ==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.40.tgz", + "integrity": "sha512-x4JHshTVB2o5xOedLL54/jsKkfUlsMw25tNM5fWkehiKWXlQuxEasl5/roceAFETWm8mEESuL8pWgZaiyTDl4Q==", "cpu": [ "arm64" ], @@ -6621,9 +6681,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.41.tgz", - "integrity": "sha512-0RoVyiPCnylf3TG77C3S86PRSmaq+SaYB4VDLJFz3qcEHz1pfP0LhyskhgX4wjQV1mveDzFEn1BVAuo0eOMwZA==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.40.tgz", + "integrity": "sha512-2QaW9HtlvatiQscQACVIyKtj+vAEFEC6Tn+8rqxm8ikYHUD33M/FVXGWEvMLTI7T3P25zjhs+toAlLsjHgfzQQ==", "cpu": [ "x64" ], @@ -6636,9 +6696,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.41.tgz", - "integrity": "sha512-mZW7GeY7Uw1nkKoWpx898ou20oCSt8MR+jAVuAhMjX+G4Zr0WWXYSigWNiRymhR6Q9KhyvoFpMckguSvYWmXsw==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.40.tgz", + "integrity": "sha512-cJPgSg8222gezj5Db2S8PNvcALJLokvXqvFjyzRR253SMFFkq9JKWk0uwO3wg8i8jhe78xMB6EO6AteQqFWvCg==", "cpu": [ "arm" ], @@ -6651,9 +6711,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.41.tgz", - "integrity": "sha512-e91LGn+6KuLFw3sWk5swwGc/dP4tXs0mg3HrhjImRoofU02Bb9aHcj5zgrSO8ZByvDtm/Knn16h1ojxIMOFaxg==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.40.tgz", + "integrity": "sha512-s76n4/vpQzV7dpS703m1WnCxyG7OfGk+EeJf+KEl/m6KP7c5MHHOLOf8hpagI/QI1H8jb9j1ADqNu2C7tEUR8Q==", "cpu": [ "arm64" ], @@ -6666,9 +6726,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.41.tgz", - "integrity": "sha512-Q7hmrniLWsQ7zjtImGcjx1tl5/Qxpel+fC+OXTnGvAyyoGssSftIBlXMnqVLteL78zhxIPAzi+gizWAe5RGqrA==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.40.tgz", + "integrity": "sha512-aTkeImCq1WrkljAQNnqlbk/1ermotONkBl11GH7Ia+8yhsmgt8ZiNBIi0tJ5UjdfXDtnl58Iek43Vo8LWaPUKA==", "cpu": [ "arm64" ], @@ -6681,9 +6741,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.41.tgz", - "integrity": "sha512-h4sv1sCfZQgRIwmykz8WPqVpbvHb13Qm3SsrbOudhAp2MuzpWzsgMP5hAEpdCP/nWreiCz3aoM6L8JeakRDq0g==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.40.tgz", + "integrity": "sha512-ZsfVlzXSXvNZBuK1fCrenoLSLVv0Zk7OdmkAG9cWN3bKkc/ynxO+6njXLEKWfv9bRfDBXhxifyHGOVOQlIFIAA==", "cpu": [ "x64" ], @@ -6696,9 +6756,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.41.tgz", - "integrity": "sha512-Z7c26i38378d0NT/dcz8qPSAXm41lqhNzykdhKhI+95mA9m4pskP18T/0I45rmyx1ywifypu+Ip+SXmKeVSPgQ==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.40.tgz", + "integrity": "sha512-5GgMuadbd6fhHg/+7W25i+9OQTW4nTMGECias0BNPlcW8nnohzSphpj5jLI/Ub5bWzMwE2hua6e2uiZ17rTySg==", "cpu": [ "x64" ], @@ -6711,9 +6771,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.41.tgz", - "integrity": "sha512-I0CYnPc+ZGc912YeN0TykIOf/Q7yJQHRwDuhewwD6RkbiSEaVfSux5pAmmdoKw2aGMSq+cwLmgPe9HYLRNz+4w==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.40.tgz", + "integrity": "sha512-TqiK28eaK3YOKSp8iESlrrbSzDGRQqM0zR4hvCgfHwL4L1BPh/M0aIMC/vyYh2gqpz2quyNqgi/DxoZ2+WxlUg==", "cpu": [ "arm64" ], @@ -6726,9 +6786,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.41.tgz", - "integrity": "sha512-EygN4CVDWF29/U2T5fXGfWyLvRbMd2hiUgkciAl7zHuyJ6nKl+kpodqV2A0Wd4sFtSNedU0gQEBEXEe7cqvmsA==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.40.tgz", + "integrity": "sha512-PqtCXFs5+ZbrfFe1VZAcCl8k9h47wE65mKDhDvZ9/SQhXxZX2+f5mUGXuH4G5rA0CyijsVpHnpA/5rqE7f2Sxw==", "cpu": [ "ia32" ], @@ -6741,9 +6801,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.41", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.41.tgz", - "integrity": "sha512-Mfp8qD1hNwWWRy0ISdwQJu1g0UYoVTtuQlO0z3aGbXqL51ew9e56+8j3M1U9i95lXFyWkARgjDCcKkQi+WezyA==", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.40.tgz", + "integrity": "sha512-73DGsjsJYSzmoRbfomPj5jcQawtK2H0bCDi/1wgfl8NKVOuzrq+PpaTry3lzx+gvTHxUX6mUHV22i7C9ITL74Q==", "cpu": [ "x64" ], @@ -6845,7 +6905,6 @@ "version": "12.1.5", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^8.0.0", @@ -6863,7 +6922,6 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -6881,14 +6939,12 @@ "node_modules/@testing-library/react/node_modules/@types/aria-query": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true + "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" }, "node_modules/@testing-library/react/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6900,7 +6956,6 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, "dependencies": { "deep-equal": "^2.0.5" } @@ -6909,7 +6964,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -7168,9 +7222,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", - "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", + "version": "8.21.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", + "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -7616,7 +7670,6 @@ "version": "17.0.19", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", - "dev": true, "dependencies": { "@types/react": "^17" } @@ -8383,7 +8436,8 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -8536,6 +8590,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dev": true, "dependencies": { "debug": "^4.1.0", "depd": "^2.0.0", @@ -8806,7 +8861,8 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true }, "node_modules/arch": { "version": "2.2.0", @@ -8832,6 +8888,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -8988,7 +9045,8 @@ "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true }, "node_modules/asar": { "version": "3.2.0", @@ -9216,9 +9274,9 @@ } }, "node_modules/b4a": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.3.tgz", - "integrity": "sha512-aX6/FqpWQve8VN9kyTExy7GlmwNShvxcCWWD5QVR3ZbRlyBGtCrG5Autu95xxSPH4CRs+5PSV4d7PRnWpmqFlA==" + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.2.tgz", + "integrity": "sha512-YFqjbZ8iqX/wWJVmF1SSOB5TYDwsPd/sZzhSdu2PskElf55PjEe+0MhsEPgoa5eTK1VS/WqJMz9qwIFwZta+3g==" }, "node_modules/babel-jest": { "version": "28.1.3", @@ -9578,6 +9636,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz", "integrity": "sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA==", + "dev": true, "dependencies": { "cmd-shim": "^5.0.0", "mkdirp-infer-owner": "^2.0.0", @@ -9594,6 +9653,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -9602,6 +9662,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -10039,6 +10100,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, "dependencies": { "semver": "^7.0.0" } @@ -10073,6 +10135,7 @@ "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", @@ -10101,6 +10164,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -10109,6 +10173,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10127,6 +10192,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -10135,6 +10201,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10146,6 +10213,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -10157,6 +10225,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -10171,6 +10240,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10180,6 +10250,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10199,6 +10270,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10209,7 +10281,8 @@ "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/cacheable-lookup": { "version": "5.0.4", @@ -10333,9 +10406,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001468", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz", - "integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==", + "version": "1.0.30001466", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz", + "integrity": "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==", "funding": [ { "type": "opencollective", @@ -10734,6 +10807,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz", "integrity": "sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==", + "dev": true, "dependencies": { "mkdirp-infer-owner": "^2.0.0" }, @@ -10807,6 +10881,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, "bin": { "color-support": "bin.js" } @@ -10851,6 +10926,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", + "dev": true, "dependencies": { "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" @@ -10896,7 +10972,8 @@ "node_modules/common-ancestor-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "dev": true }, "node_modules/common-path-prefix": { "version": "3.0.0", @@ -11125,7 +11202,8 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -11851,6 +11929,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", + "dev": true, "engines": { "node": "*" } @@ -11983,9 +12062,9 @@ } }, "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", "engines": { "node": ">=0.10.0" } @@ -12159,12 +12238,14 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -12237,6 +12318,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -12858,9 +12940,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.333", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.333.tgz", - "integrity": "sha512-YyE8+GKyGtPEP1/kpvqsdhD6rA/TP1DUFDN4uiU/YI52NzDxmwHkEb3qjId8hLBa5siJvG0sfC3O66501jMruQ==" + "version": "1.4.328", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz", + "integrity": "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==" }, "node_modules/electron-updater": { "version": "4.6.5", @@ -12981,6 +13063,7 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -13057,7 +13140,8 @@ "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true }, "node_modules/errno": { "version": "0.1.8", @@ -13204,9 +13288,9 @@ "peer": true }, "node_modules/esbuild": { - "version": "0.17.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.12.tgz", - "integrity": "sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==", + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.11.tgz", + "integrity": "sha512-pAMImyokbWDtnA/ufPxjQg0fYo2DDuzAlqwnDvbXqHLphe+m80eF++perYKVm8LeTuj2zUuFXC+xgSVxyoHUdg==", "dev": true, "hasInstallScript": true, "bin": { @@ -13216,28 +13300,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.12", - "@esbuild/android-arm64": "0.17.12", - "@esbuild/android-x64": "0.17.12", - "@esbuild/darwin-arm64": "0.17.12", - "@esbuild/darwin-x64": "0.17.12", - "@esbuild/freebsd-arm64": "0.17.12", - "@esbuild/freebsd-x64": "0.17.12", - "@esbuild/linux-arm": "0.17.12", - "@esbuild/linux-arm64": "0.17.12", - "@esbuild/linux-ia32": "0.17.12", - "@esbuild/linux-loong64": "0.17.12", - "@esbuild/linux-mips64el": "0.17.12", - "@esbuild/linux-ppc64": "0.17.12", - "@esbuild/linux-riscv64": "0.17.12", - "@esbuild/linux-s390x": "0.17.12", - "@esbuild/linux-x64": "0.17.12", - "@esbuild/netbsd-x64": "0.17.12", - "@esbuild/openbsd-x64": "0.17.12", - "@esbuild/sunos-x64": "0.17.12", - "@esbuild/win32-arm64": "0.17.12", - "@esbuild/win32-ia32": "0.17.12", - "@esbuild/win32-x64": "0.17.12" + "@esbuild/android-arm": "0.17.11", + "@esbuild/android-arm64": "0.17.11", + "@esbuild/android-x64": "0.17.11", + "@esbuild/darwin-arm64": "0.17.11", + "@esbuild/darwin-x64": "0.17.11", + "@esbuild/freebsd-arm64": "0.17.11", + "@esbuild/freebsd-x64": "0.17.11", + "@esbuild/linux-arm": "0.17.11", + "@esbuild/linux-arm64": "0.17.11", + "@esbuild/linux-ia32": "0.17.11", + "@esbuild/linux-loong64": "0.17.11", + "@esbuild/linux-mips64el": "0.17.11", + "@esbuild/linux-ppc64": "0.17.11", + "@esbuild/linux-riscv64": "0.17.11", + "@esbuild/linux-s390x": "0.17.11", + "@esbuild/linux-x64": "0.17.11", + "@esbuild/netbsd-x64": "0.17.11", + "@esbuild/openbsd-x64": "0.17.11", + "@esbuild/sunos-x64": "0.17.11", + "@esbuild/win32-arm64": "0.17.11", + "@esbuild/win32-ia32": "0.17.11", + "@esbuild/win32-x64": "0.17.11" } }, "node_modules/esbuild-loader": { @@ -15686,6 +15770,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -16126,9 +16211,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/graceful-readlink": { "version": "1.0.1", @@ -16393,7 +16478,8 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true }, "node_modules/he": { "version": "1.2.0", @@ -16434,6 +16520,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -16445,6 +16532,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -16455,7 +16543,8 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/hpack.js": { "version": "2.1.6", @@ -16755,6 +16844,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, "dependencies": { "ms": "^2.0.0" } @@ -16857,6 +16947,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", + "dev": true, "dependencies": { "minimatch": "^5.0.1" }, @@ -16868,6 +16959,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -16876,6 +16968,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -16980,7 +17073,8 @@ "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true }, "node_modules/inflight": { "version": "1.0.6", @@ -17005,6 +17099,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz", "integrity": "sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==", + "dev": true, "dependencies": { "npm-package-arg": "^9.0.1", "promzard": "^0.3.0", @@ -17022,6 +17117,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -17033,6 +17129,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -17041,6 +17138,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -17117,7 +17215,8 @@ "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true }, "node_modules/ip-regex": { "version": "4.3.0", @@ -17354,7 +17453,8 @@ "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true }, "node_modules/is-map": { "version": "2.0.2", @@ -20317,9 +20417,9 @@ } }, "node_modules/jest-watch-typeahead/node_modules/ansi-escapes": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.1.0.tgz", - "integrity": "sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", + "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", "dependencies": { "type-fest": "^3.0.0" }, @@ -20708,9 +20808,9 @@ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" }, "node_modules/joi": { - "version": "17.9.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.0.tgz", - "integrity": "sha512-PWirKfKoZL3kWHfkGKzdCLGv23c00rI31PKVDMg33b/ANe+bMC/ZPdEnHAoHzn5Hy6BTg3J0A2yRVKzT64e6Xw==", + "version": "17.8.4", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.4.tgz", + "integrity": "sha512-jjdRHb5WtL+KgSHvOULQEPPv4kcl+ixd1ybOFQq3rWLgEEqc03QMmilodL0GVJE14U/SQDXkUhQUSZANGDH/AA==", "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", @@ -20880,6 +20980,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -20920,6 +21021,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, "engines": [ "node >= 0.2.0" ] @@ -21128,12 +21230,14 @@ "node_modules/just-diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-5.2.0.tgz", - "integrity": "sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw==" + "integrity": "sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw==", + "dev": true }, "node_modules/just-diff-apply": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", - "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==" + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "dev": true }, "node_modules/keyv": { "version": "4.5.2", @@ -21187,16 +21291,6 @@ "language-subtag-registry": "~0.3.2" } }, - "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" - } - }, "node_modules/lazy-cache": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", @@ -21392,12 +21486,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lerna/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, "node_modules/lerna/node_modules/inquirer": { "version": "8.2.5", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", @@ -21748,6 +21836,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.3.tgz", "integrity": "sha512-4tkfUZprwvih2VUZYMozL7EMKgQ5q9VW2NtRyxWtQWlkLTAWHRklcAvBN49CVqEkhUw7vTX2fNgB5LzgUucgYg==", + "dev": true, "dependencies": { "aproba": "^2.0.0", "minipass": "^3.1.1", @@ -21762,6 +21851,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -21773,6 +21863,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -21781,6 +21872,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21792,6 +21884,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -21805,12 +21898,14 @@ "node_modules/libnpmaccess/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/libnpmpublish": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-6.0.4.tgz", "integrity": "sha512-lvAEYW8mB8QblL6Q/PI/wMzKNvIrF7Kpujf/4fGS/32a2i3jzUXi04TNyIBcK6dQJ34IgywfaKGh+Jq4HYPFmg==", + "dev": true, "dependencies": { "normalize-package-data": "^4.0.0", "npm-package-arg": "^9.0.1", @@ -21826,6 +21921,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -21837,6 +21933,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -21845,6 +21942,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -21859,6 +21957,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -22189,6 +22288,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -22215,6 +22315,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -22225,6 +22326,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -22237,6 +22339,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, "engines": { "node": ">= 6" } @@ -22245,6 +22348,7 @@ "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -22273,6 +22377,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -22286,6 +22391,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -22297,6 +22403,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -22308,6 +22415,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -22322,6 +22430,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, "dependencies": { "minipass": "^3.1.1" }, @@ -22333,6 +22442,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, "dependencies": { "unique-slug": "^2.0.0" } @@ -22341,6 +22451,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4" } @@ -22348,7 +22459,8 @@ "node_modules/make-fetch-happen/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/make-plural": { "version": "6.2.2", @@ -22844,9 +22956,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz", - "integrity": "sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.3.tgz", + "integrity": "sha512-CD9cXeKeXLcnMw8FZdtfrRrLaM7gwCl4nKuKn2YkY2Bw5wdlB8zU2cCzw+w2zS9RFvbrufTBkMCJACNPwqQA0w==", "dependencies": { "schema-utils": "^4.0.0" }, @@ -22961,6 +23073,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -22972,6 +23085,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -22982,12 +23096,14 @@ "node_modules/minipass-collect/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-fetch": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -23004,6 +23120,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23014,12 +23131,14 @@ "node_modules/minipass-fetch/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23031,6 +23150,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23041,12 +23161,14 @@ "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-json-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, "dependencies": { "jsonparse": "^1.3.1", "minipass": "^3.0.0" @@ -23056,6 +23178,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23066,12 +23189,14 @@ "node_modules/minipass-json-stream/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23083,6 +23208,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23093,12 +23219,14 @@ "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23110,6 +23238,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23120,7 +23249,8 @@ "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minizlib": { "version": "2.1.2", @@ -23207,6 +23337,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", + "dev": true, "dependencies": { "chownr": "^2.0.0", "infer-owner": "^1.0.4", @@ -23474,6 +23605,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -23572,6 +23704,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -23606,6 +23739,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -23725,6 +23859,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, "dependencies": { "abbrev": "1" }, @@ -23944,6 +24079,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } @@ -23976,6 +24112,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", + "dev": true, "dependencies": { "semver": "^7.1.1" }, @@ -23986,12 +24123,14 @@ "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true }, "node_modules/npm-package-arg": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==", + "dev": true, "dependencies": { "hosted-git-info": "^3.0.6", "semver": "^7.0.0", @@ -24004,12 +24143,14 @@ "node_modules/npm-package-arg/node_modules/builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==" + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", + "dev": true }, "node_modules/npm-package-arg/node_modules/hosted-git-info": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -24021,6 +24162,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -24032,6 +24174,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "dev": true, "dependencies": { "builtins": "^1.0.3" } @@ -24039,12 +24182,14 @@ "node_modules/npm-package-arg/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/npm-packlist": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.1.tgz", "integrity": "sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw==", + "dev": true, "dependencies": { "glob": "^8.0.1", "ignore-walk": "^5.0.1", @@ -24062,6 +24207,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -24070,6 +24216,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -24088,6 +24235,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -24099,6 +24247,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz", "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", + "dev": true, "dependencies": { "npm-install-checks": "^5.0.0", "npm-normalize-package-bin": "^2.0.0", @@ -24113,6 +24262,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -24124,6 +24274,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -24132,6 +24283,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -24140,6 +24292,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -24154,6 +24307,7 @@ "version": "13.3.0", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.0.tgz", "integrity": "sha512-10LJQ/1+VhKrZjIuY9I/+gQTvumqqlgnsCufoXETHAPFTS3+M+Z5CFhZRDHGavmJ6rOye3UvNga88vl8n1r6gg==", + "dev": true, "dependencies": { "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", @@ -24171,6 +24325,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -24182,6 +24337,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -24190,6 +24346,7 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -24216,6 +24373,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -24227,6 +24385,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -24243,6 +24402,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -24257,6 +24417,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -24269,7 +24430,8 @@ "node_modules/npm-registry-fetch/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/npm-run-path": { "version": "2.0.2", @@ -26489,6 +26651,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -26517,14 +26680,14 @@ "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" }, "node_modules/nx": { - "version": "15.8.7", - "resolved": "https://registry.npmjs.org/nx/-/nx-15.8.7.tgz", - "integrity": "sha512-u6p/1gU20WU61orxK7hcXBsVspPHy3X66XVAAakkYcaOBlsJhJrR7Og191qIyjEkqEWmcekiDQVw3D6XfagL4Q==", + "version": "15.8.6", + "resolved": "https://registry.npmjs.org/nx/-/nx-15.8.6.tgz", + "integrity": "sha512-3OsT6HMyyUyRuP07vLr7iuWzqziQvkh/vSfOWQb3PXakm6N1IvaLxF+NuUCtSaBDUACfqoVO4MC7WE2270OrKQ==", "dev": true, "hasInstallScript": true, "dependencies": { - "@nrwl/cli": "15.8.7", - "@nrwl/tao": "15.8.7", + "@nrwl/cli": "15.8.6", + "@nrwl/tao": "15.8.6", "@parcel/watcher": "2.0.4", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0-rc.18", @@ -26563,15 +26726,15 @@ "nx": "bin/nx.js" }, "optionalDependencies": { - "@nrwl/nx-darwin-arm64": "15.8.7", - "@nrwl/nx-darwin-x64": "15.8.7", - "@nrwl/nx-linux-arm-gnueabihf": "15.8.7", - "@nrwl/nx-linux-arm64-gnu": "15.8.7", - "@nrwl/nx-linux-arm64-musl": "15.8.7", - "@nrwl/nx-linux-x64-gnu": "15.8.7", - "@nrwl/nx-linux-x64-musl": "15.8.7", - "@nrwl/nx-win32-arm64-msvc": "15.8.7", - "@nrwl/nx-win32-x64-msvc": "15.8.7" + "@nrwl/nx-darwin-arm64": "15.8.6", + "@nrwl/nx-darwin-x64": "15.8.6", + "@nrwl/nx-linux-arm-gnueabihf": "15.8.6", + "@nrwl/nx-linux-arm64-gnu": "15.8.6", + "@nrwl/nx-linux-arm64-musl": "15.8.6", + "@nrwl/nx-linux-x64-gnu": "15.8.6", + "@nrwl/nx-linux-x64-musl": "15.8.6", + "@nrwl/nx-win32-arm64-msvc": "15.8.6", + "@nrwl/nx-win32-x64-msvc": "15.8.6" }, "peerDependencies": { "@swc-node/register": "^1.4.2", @@ -26603,9 +26766,9 @@ } }, "node_modules/nx/node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -27291,6 +27454,7 @@ "version": "13.6.1", "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.1.tgz", "integrity": "sha512-L+2BI1ougAPsFjXRyBhcKmfT016NscRFLv6Pz5EiNf1CCFJFU0pSKKQwsZTyAQB+sTuUL4TyFyp6J1Ork3dOqw==", + "dev": true, "dependencies": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -27325,6 +27489,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -27336,6 +27501,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -27344,6 +27510,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -27355,6 +27522,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -27369,6 +27537,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -27382,7 +27551,8 @@ "node_modules/pacote/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/pako": { "version": "0.2.9", @@ -27414,6 +27584,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz", "integrity": "sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.1", "just-diff": "^5.0.1", @@ -27534,6 +27705,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.1.tgz", "integrity": "sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==", + "dev": true, "dependencies": { "lru-cache": "^7.14.1", "minipass": "^4.0.2" @@ -27549,6 +27721,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -28361,9 +28534,9 @@ } }, "node_modules/prettier": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.5.tgz", - "integrity": "sha512-3gzuxrHbKUePRBB4ZeU08VNkUcqEHaUaouNt0m7LGP4Hti/NuB07C7PPTM/LkWqXoJYJn2McEo5+kxPNrtQkLQ==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", "peer": true, "bin": { "prettier": "bin-prettier.js" @@ -28441,6 +28614,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -28470,6 +28644,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -28478,6 +28653,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -28485,12 +28661,14 @@ "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -28515,6 +28693,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", "integrity": "sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw==", + "dev": true, "dependencies": { "read": "1" } @@ -28899,6 +29078,16 @@ "react-dom": "^16.13.1 || ^17.0.1" } }, + "node_modules/react-material-ui-carousel/node_modules/@types/react": { + "version": "16.14.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.35.tgz", + "integrity": "sha512-NUEiwmSS1XXtmBcsm1NyRRPYjoZF2YTE89/5QiLt5mlGffYK9FQqOKuOLuXNrjPQV04oQgaZG+Yq02ZfHoFyyg==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "node_modules/react-material-ui-carousel/node_modules/auto-bind": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-2.1.1.tgz", @@ -28910,6 +29099,11 @@ "node": ">=6" } }, + "node_modules/react-material-ui-carousel/node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, "node_modules/react-redux": { "version": "7.2.9", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", @@ -29010,9 +29204,9 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-select": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.1.tgz", - "integrity": "sha512-u/brzm3B6vgI+PtxNyE4/18kXgaf6bn5sOAjKhaQ54EItBfW41SRLH1AJC5fefPnGM4JmMcM51t/HAVCi5GrpQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.0.tgz", + "integrity": "sha512-lJGiMxCa3cqnUr2Jjtg9YHsaytiZqeNOKeibv6WF5zbK/fPegZ1hg3y/9P1RZVLhqBTs0PfqQLKuAACednYGhQ==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.0", @@ -29114,6 +29308,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, "dependencies": { "mute-stream": "~0.0.4" }, @@ -29134,6 +29329,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.0.tgz", "integrity": "sha512-KQDVjGqhZk92PPNRj9ZEXEuqg8bUobSKRw+q0YQ3TKI5xkce7bUJobL4Z/OtiEbAAv70yEpYIXp4iQ9L8oPVog==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -29167,6 +29363,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.1.tgz", "integrity": "sha512-MALHuNgYWdGW3gKzuNMuYtcSSZbGQm94fAp16xt8VsYTLBjUSc55bLMKe6gzpWue0Tfi6CBgwCSdDAqutGDhMg==", + "dev": true, "dependencies": { "glob": "^8.0.1", "json-parse-even-better-errors": "^2.3.1", @@ -29181,6 +29378,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.0", "npm-normalize-package-bin": "^1.0.1" @@ -29193,6 +29391,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -29201,6 +29400,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -29219,6 +29419,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -29230,6 +29431,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -29238,6 +29440,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -29249,6 +29452,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -29472,6 +29676,7 @@ "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "debuglog": "^1.0.1", "dezalgo": "^1.0.0", @@ -29902,6 +30107,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "dev": true, "dependencies": { "glob": "^9.2.0" }, @@ -29919,14 +30125,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/rimraf/node_modules/glob": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", - "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.2.1.tgz", + "integrity": "sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^7.4.1", @@ -29944,6 +30152,7 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -30053,9 +30262,9 @@ } }, "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", + "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==", "engines": { "node": ">=10" } @@ -30075,9 +30284,9 @@ } }, "node_modules/sass": { - "version": "1.59.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.59.3.tgz", - "integrity": "sha512-QCq98N3hX1jfTCoUAsF3eyGuXLsY7BCnCEg9qAact94Yc21npG2/mVOqoDvE0fCbWDqiM4WlcJQla0gWG2YlxQ==", + "version": "1.59.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.59.2.tgz", + "integrity": "sha512-jJyO6SmbzkJexF8MUorHx5tAilcgabioYxT/BHbY4+OvoqmbHxsYlrjZ8Adhqcgl6Zqwie0TgMXLCAmPFxXOuw==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -30447,7 +30656,8 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/set-getter": { "version": "0.1.1", @@ -30692,6 +30902,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -30712,6 +30923,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -30725,6 +30937,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -30826,6 +31039,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -30834,12 +31048,14 @@ "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -30848,7 +31064,8 @@ "node_modules/spdx-license-ids": { "version": "3.0.13", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true }, "node_modules/spdy": { "version": "4.0.2", @@ -30944,6 +31161,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, "dependencies": { "minipass": "^3.1.1" }, @@ -30955,6 +31173,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -30965,7 +31184,8 @@ "node_modules/ssri/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/stack-trace": { "version": "0.0.10", @@ -31123,53 +31343,6 @@ "node": ">= 0.8" } }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", - "dependencies": { - "bl": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stdin-discarder/node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/stdin-discarder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -31824,9 +31997,9 @@ } }, "node_modules/tar-stream/node_modules/bl": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.1.tgz", - "integrity": "sha512-zk1P1eAEBHhhB+4NfGxqmuV6NgwECnIoRgsOq2ObdEsmoFVIYzJ/Jjcgaj7JOY/8ekH27bIHSV4Si2T+evqu+Q==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.0.tgz", + "integrity": "sha512-Ik9BVIMdcWzSOCpzDv2XpQ4rJ4oZBuk3ck6MgiOv0EopdgtohN2uSCrrLlkH1Jf0KnpZZMBA3D0bUMbCdj/jgA==", "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", @@ -32396,6 +32569,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz", "integrity": "sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -32807,9 +32981,9 @@ "dev": true }, "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -32855,6 +33029,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, "dependencies": { "unique-slug": "^3.0.0" }, @@ -32866,6 +33041,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4" }, @@ -33096,6 +33272,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -33105,6 +33282,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "dev": true, "dependencies": { "builtins": "^5.0.0" }, @@ -33207,7 +33385,8 @@ "node_modules/walk-up-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", - "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==" + "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==", + "dev": true }, "node_modules/walker": { "version": "1.0.8", @@ -33263,9 +33442,9 @@ } }, "node_modules/webpack": { - "version": "5.76.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz", - "integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -33439,9 +33618,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.13.1.tgz", - "integrity": "sha512-5tWg00bnWbYgkN+pd5yISQKDejRBYGEw15RaEEslH+zdbNDxxaZvEAO2WulaSaFKb5n3YG8JXsGaDsut1D0xdA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", + "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", "dev": true, "dependencies": { "@types/bonjour": "^3.5.9", @@ -33463,7 +33642,6 @@ "html-entities": "^2.3.2", "http-proxy-middleware": "^2.0.3", "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", "open": "^8.0.9", "p-retry": "^4.5.0", "rimraf": "^3.0.2", @@ -33473,7 +33651,7 @@ "sockjs": "^0.3.24", "spdy": "^4.0.2", "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" + "ws": "^8.4.2" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" @@ -33489,9 +33667,6 @@ "webpack": "^4.37.0 || ^5.0.0" }, "peerDependenciesMeta": { - "webpack": { - "optional": true - }, "webpack-cli": { "optional": true } @@ -33737,6 +33912,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -34267,6 +34443,7 @@ }, "devDependencies": { "@async-fn/jest": "1.6.4", + "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", @@ -34403,7 +34580,11 @@ "@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", "@k8slens/legacy-extensions": "^1.0.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/messaging-for-main": "^1.0.0-alpha.1", + "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", "@types/byline": "^4.2.33", @@ -35073,9 +35254,9 @@ "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" }, "packages/infrastructure/jest/node_modules/@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", + "version": "29.4.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.1.tgz", + "integrity": "sha512-zDQSWXG+ZkEvs2zFFMszePhx4euKz+Yt3Gg1P+RHjfJBinTTr6L2DEyovO4V/WrKXuF0Dgn56GWGZPDa6TW9eQ==", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -35971,6 +36152,18 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "packages/infrastructure/jest/node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "packages/infrastructure/jest/node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -36132,11 +36325,11 @@ } }, "packages/infrastructure/webpack/node_modules/sass-loader": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.1.tgz", - "integrity": "sha512-VQUrgUa5/waIzMrzyuko3sj5WD9NMsYph91cNICx+OaODbRtLl6To2fswLx8MH2qNxXFqRtpvdPQIa7mE93YOA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", + "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", "dependencies": { - "klona": "^2.0.6", + "klona": "^2.0.4", "neo-async": "^2.6.2" }, "engines": { @@ -36457,7 +36650,11 @@ "@k8slens/generate-tray-icons": "^6.5.0-alpha.1", "@k8slens/legacy-extension-example": "^1.0.0-alpha.1", "@k8slens/legacy-extensions": "^1.0.0-alpha.1", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/messaging-for-main": "^1.0.0-alpha.1", + "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", "@ogre-tools/fp": "^15.1.2", @@ -36654,9 +36851,9 @@ "dev": true }, "packages/release-tool/node_modules/ansi-escapes": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.1.0.tgz", - "integrity": "sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", + "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", "dependencies": { "type-fest": "^3.0.0" }, @@ -36689,6 +36886,39 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "packages/release-tool/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "packages/release-tool/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "packages/release-tool/node_modules/chalk": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", @@ -36754,28 +36984,28 @@ } }, "packages/release-tool/node_modules/inquirer": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.5.tgz", - "integrity": "sha512-3ygAIh8gcZavV9bj6MTdYddG2zPSYswP808fKS46NOwlF0zZljVpnLCHODDqItWJDbDpLb3aouAxGaJbkxoppA==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", + "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", "dependencies": { "ansi-escapes": "^6.0.0", - "chalk": "^5.2.0", + "chalk": "^5.1.2", "cli-cursor": "^4.0.0", "cli-width": "^4.0.0", "external-editor": "^3.0.3", "figures": "^5.0.0", "lodash": "^4.17.21", - "mute-stream": "1.0.0", + "mute-stream": "0.0.8", "ora": "^6.1.2", "run-async": "^2.4.0", - "rxjs": "^7.8.0", + "rxjs": "^7.5.7", "string-width": "^5.1.2", "strip-ansi": "^7.0.1", "through": "^2.3.6", - "wrap-ansi": "^8.1.0" + "wrap-ansi": "^8.0.1" }, "engines": { - "node": ">=14.18.0" + "node": ">=12.0.0" } }, "packages/release-tool/node_modules/is-interactive": { @@ -36815,26 +37045,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/release-tool/node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "packages/release-tool/node_modules/ora": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.2.0.tgz", - "integrity": "sha512-c1qb/1rdE+EFDYiLXh10VY459uMh7DN9zlgd8mZJLoeiPpYllN8eAOiih2Rkah5ywxRm5tHN5C9zPheDq8d1MA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", + "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", "dependencies": { + "bl": "^5.0.0", "chalk": "^5.0.0", "cli-cursor": "^4.0.0", "cli-spinners": "^2.6.1", "is-interactive": "^2.0.0", "is-unicode-supported": "^1.1.0", "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" }, @@ -36995,6 +37217,98 @@ "@ogre-tools/injectable": "^15.1.2" } }, + "packages/technical-features/messaging/agnostic": { + "name": "@k8slens/messaging", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "lodash": "^4.17.21", + "mobx": "^6.7.0" + } + }, + "packages/technical-features/messaging/computed-channel": { + "name": "@k8slens/computed-channel", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1", + "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1", + "type-fest": "^2.14.0" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "lodash": "^4.17.21", + "mobx": "^6.8.0" + } + }, + "packages/technical-features/messaging/electron/main": { + "name": "@k8slens/messaging-for-main", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "electron": "^19.1.8", + "lodash": "^4.17.21" + } + }, + "packages/technical-features/messaging/electron/renderer": { + "name": "@k8slens/messaging-for-renderer", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "electron": "^19.1.8", + "lodash": "^4.17.21" + } + }, + "packages/technical-features/messaging/message-bridge-fake": { + "name": "@k8slens/messaging-fake-bridge", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "^6.5.0-alpha.1", + "@k8slens/feature-core": "6.5.0-alpha.1", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "mobx": "^6.7.0" + }, + "peerDependencies": { + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "lodash": "^4.17.21" + } + }, "packages/utility-features/run-many": { "name": "@k8slens/run-many", "version": "1.0.0-alpha.1", @@ -37005,7 +37319,7 @@ "peerDependencies": { "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", - "@ogre-tools/fp": "^15.1.1", + "@ogre-tools/fp": "^15.1.2", "@ogre-tools/injectable": "^15.1.2", "type-fest": "^2.19.0", "typed-emitter": "^1.4.0", @@ -37018,6 +37332,14 @@ "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", "dev": true }, + "packages/utility-features/startable-stoppable": { + "name": "@k8slens/startable-stoppable", + "version": "1.0.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + } + }, "packages/utility-features/test-utils": { "name": "@k8slens/test-utils", "version": "1.0.0-alpha.1", @@ -37027,7 +37349,10 @@ }, "peerDependencies": { "@ogre-tools/injectable": "^15.1.2", - "lodash": "^4.17.21" + "@ogre-tools/injectable-react": "^15.1.2", + "@testing-library/react": "^12.1.5", + "lodash": "^4.17.21", + "react": "^17.0.2" } }, "packages/utility-features/utilities": { @@ -37041,7 +37366,8 @@ "@types/react-router": "^5.1.20", "@types/readable-stream": "^2.3.15", "@types/semver": "^7.3.13", - "@types/tar": "^6.1.4" + "@types/tar": "^6.1.4", + "type-fest": "^2.14.0" }, "peerDependencies": { "@astronautlabs/jsonpath": "^1.1.0", diff --git a/package.json b/package.json index bc6c89ab37..0a9f693adb 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "clean:node_modules": "lerna clean -y && rimraf node_modules", "dev": "lerna run dev --stream --skip-nx-cache", "lint": "lerna run lint --stream", + "lint:fix": "lerna run lint:fix --stream", "mkdocs:serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest", "mkdocs:verify": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -v ${PWD}:/docs mkdocs-serve-local:latest build --strict", "test:unit": "lerna run --stream test:unit", diff --git a/packages/core/package.json b/packages/core/package.json index 6b4aecf2cc..15c79d774d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -189,6 +189,7 @@ }, "devDependencies": { "@async-fn/jest": "1.6.4", + "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", @@ -322,7 +323,11 @@ "@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", "@k8slens/legacy-extensions": "^1.0.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/messaging-for-main": "^1.0.0-alpha.1", + "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", "@types/byline": "^4.2.33", diff --git a/packages/core/src/common/app-paths/app-paths-channel.ts b/packages/core/src/common/app-paths/app-paths-channel.ts index 4502569d3b..e738b4896a 100644 --- a/packages/core/src/common/app-paths/app-paths-channel.ts +++ b/packages/core/src/common/app-paths/app-paths-channel.ts @@ -3,11 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { AppPaths } from "./app-path-injection-token"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; -export type AppPathsChannel = RequestChannel; - -export const appPathsChannel: AppPathsChannel = { - id: "app-paths", -}; +export const appPathsChannel = getRequestChannel("app-paths"); diff --git a/packages/core/src/common/base-store/base-store.ts b/packages/core/src/common/base-store/base-store.ts index be7abf1293..a1dd26f0f7 100644 --- a/packages/core/src/common/base-store/base-store.ts +++ b/packages/core/src/common/base-store/base-store.ts @@ -15,7 +15,7 @@ import type { GetConfigurationFileModel } from "../get-configuration-file-model/ 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"; +import type { EnlistMessageChannelListener } from "@k8slens/messaging"; import { toJS } from "../utils"; export interface BaseStoreParams extends Omit, "migrations"> { @@ -108,6 +108,7 @@ export abstract class BaseStore { this.params.syncOptions, ), this.dependencies.enlistMessageChannelListener({ + id: this.displayName, channel: { id: `${this.dependencies.ipcChannelPrefixes.local}:${config.path}`, }, diff --git a/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts b/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts index 7d9652ce5c..9dd339ee65 100644 --- a/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts +++ b/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts @@ -4,6 +4,6 @@ */ import type { SelfSignedCert } from "selfsigned"; -import { getRequestChannel } from "../utils/channel/get-request-channel"; +import { getRequestChannel } from "@k8slens/messaging"; export const lensProxyCertificateChannel = getRequestChannel("request-lens-proxy-certificate"); diff --git a/packages/core/src/common/cluster-store/cluster-store.injectable.ts b/packages/core/src/common/cluster-store/cluster-store.injectable.ts index ddd811c760..79eb02e36c 100644 --- a/packages/core/src/common/cluster-store/cluster-store.injectable.ts +++ b/packages/core/src/common/cluster-store/cluster-store.injectable.ts @@ -16,7 +16,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; import getBasenameOfPathInjectable from "../path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; const clusterStoreInjectable = getInjectable({ id: "cluster-store", diff --git a/packages/core/src/common/cluster/current-cluster-channel.ts b/packages/core/src/common/cluster/current-cluster-channel.ts index 957baa6f9c..c16af7832b 100644 --- a/packages/core/src/common/cluster/current-cluster-channel.ts +++ b/packages/core/src/common/cluster/current-cluster-channel.ts @@ -4,7 +4,7 @@ */ import type { ClusterId } from "../cluster-types"; -import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export const currentClusterMessageChannel: MessageChannel = { id: "current-visible-cluster", diff --git a/packages/core/src/common/cluster/visibility-channel.ts b/packages/core/src/common/cluster/visibility-channel.ts index 8a1a297ff2..554217a409 100644 --- a/packages/core/src/common/cluster/visibility-channel.ts +++ b/packages/core/src/common/cluster/visibility-channel.ts @@ -4,7 +4,7 @@ */ import type { ClusterId } from "../cluster-types"; -import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export const clusterVisibilityChannel: MessageChannel = { id: "cluster-visibility", diff --git a/packages/core/src/common/front-end-routing/app-navigation-channel.ts b/packages/core/src/common/front-end-routing/app-navigation-channel.ts index b3d8f02c66..8670fc4953 100644 --- a/packages/core/src/common/front-end-routing/app-navigation-channel.ts +++ b/packages/core/src/common/front-end-routing/app-navigation-channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { IpcRendererNavigationEvents } from "../ipc/navigation-events"; -import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export type AppNavigationChannel = MessageChannel; diff --git a/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts b/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts index 2439f523e2..5f96526da4 100644 --- a/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts +++ b/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { IpcRendererNavigationEvents } from "../ipc/navigation-events"; -import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export type ClusterFrameNavigationChannel = MessageChannel; diff --git a/packages/core/src/common/helm/add-helm-repository-channel.ts b/packages/core/src/common/helm/add-helm-repository-channel.ts index 258367c7ec..1744192059 100644 --- a/packages/core/src/common/helm/add-helm-repository-channel.ts +++ b/packages/core/src/common/helm/add-helm-repository-channel.ts @@ -3,11 +3,10 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { HelmRepo } from "./helm-repo"; -import type { AsyncResult } from "@k8slens/utilities"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import type { Result } from "@k8slens/utilities"; +import { getRequestChannel } from "@k8slens/messaging"; -export type AddHelmRepositoryChannel = RequestChannel>; - -export const addHelmRepositoryChannel: AddHelmRepositoryChannel = { - id: "add-helm-repository-channel", -}; +export const addHelmRepositoryChannel = getRequestChannel< + HelmRepo, + Result +>("add-helm-repository-channel"); diff --git a/packages/core/src/common/helm/get-active-helm-repositories-channel.ts b/packages/core/src/common/helm/get-active-helm-repositories-channel.ts index 2ea5a80030..ba4e0ae956 100644 --- a/packages/core/src/common/helm/get-active-helm-repositories-channel.ts +++ b/packages/core/src/common/helm/get-active-helm-repositories-channel.ts @@ -4,10 +4,9 @@ */ import type { HelmRepo } from "./helm-repo"; import type { AsyncResult } from "@k8slens/utilities"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; -export type GetActiveHelmRepositoriesChannel = RequestChannel>; - -export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = { - id: "get-helm-active-list-repositories", -}; +export const getActiveHelmRepositoriesChannel = getRequestChannel< + void, + AsyncResult +>("get-helm-active-list-repositories"); diff --git a/packages/core/src/common/helm/remove-helm-repository-channel.ts b/packages/core/src/common/helm/remove-helm-repository-channel.ts index f1189cb580..09c7630f34 100644 --- a/packages/core/src/common/helm/remove-helm-repository-channel.ts +++ b/packages/core/src/common/helm/remove-helm-repository-channel.ts @@ -3,11 +3,10 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { AsyncResult } from "@k8slens/utilities"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; import type { HelmRepo } from "./helm-repo"; -export type RemoveHelmRepositoryChannel = RequestChannel>; - -export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = { - id: "remove-helm-repository-channel", -}; +export const removeHelmRepositoryChannel = getRequestChannel< + HelmRepo, + AsyncResult +>("remove-helm-repository-channel"); diff --git a/packages/core/src/common/hotbars/store.injectable.ts b/packages/core/src/common/hotbars/store.injectable.ts index cc15f93bf8..ea25840e11 100644 --- a/packages/core/src/common/hotbars/store.injectable.ts +++ b/packages/core/src/common/hotbars/store.injectable.ts @@ -14,7 +14,7 @@ import { hotbarStoreMigrationInjectionToken } from "./migrations-token"; import getBasenameOfPathInjectable from "../path/get-basename.injectable"; import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel-prefix"; import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; -import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; const hotbarStoreInjectable = getInjectable({ diff --git a/packages/core/src/common/kube-helpers/channels.ts b/packages/core/src/common/kube-helpers/channels.ts index b48f9f1f99..c5df4d7358 100644 --- a/packages/core/src/common/kube-helpers/channels.ts +++ b/packages/core/src/common/kube-helpers/channels.ts @@ -4,11 +4,9 @@ */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Asyncify } from "type-fest"; -import type { RequestChannelHandler } from "../../main/utils/channel/channel-listeners/listener-tokens"; import type { ClusterId } from "../cluster-types"; -import type { AsyncResult } from "@k8slens/utilities"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import type { AsyncResult, Result } from "@k8slens/utilities"; +import { getRequestChannel } from "@k8slens/messaging"; export interface KubectlApplyAllArgs { clusterId: ClusterId; @@ -16,11 +14,12 @@ export interface KubectlApplyAllArgs { extraArgs: string[]; } -export const kubectlApplyAllChannel: RequestChannel> = { - id: "kubectl-apply-all", -}; +export const kubectlApplyAllChannel = getRequestChannel< + KubectlApplyAllArgs, + Result +>("kubectl-apply-all"); -export type KubectlApplyAll = Asyncify>; +export type KubectlApplyAll = (req: KubectlApplyAllArgs) => AsyncResult; export const kubectlApplyAllInjectionToken = getInjectionToken({ id: "kubectl-apply-all", @@ -32,11 +31,12 @@ export interface KubectlDeleteAllArgs { extraArgs: string[]; } -export const kubectlDeleteAllChannel: RequestChannel> = { - id: "kubectl-delete-all", -}; +export const kubectlDeleteAllChannel = getRequestChannel< + KubectlDeleteAllArgs, + Result +>("kubectl-delete-all"); -export type KubectlDeleteAll = Asyncify>; +export type KubectlDeleteAll = (req: KubectlDeleteAllArgs) => AsyncResult; export const kubectlDeleteAllInjectionToken = getInjectionToken({ id: "kubectl-delete-all", diff --git a/packages/core/src/common/root-frame/root-frame-rendered-channel.ts b/packages/core/src/common/root-frame/root-frame-rendered-channel.ts index 060ae8735c..c4dc0cefa6 100644 --- a/packages/core/src/common/root-frame/root-frame-rendered-channel.ts +++ b/packages/core/src/common/root-frame/root-frame-rendered-channel.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export type RootFrameHasRenderedChannel = MessageChannel; diff --git a/packages/core/src/common/user-store/user-store.injectable.ts b/packages/core/src/common/user-store/user-store.injectable.ts index 3b45b03b1d..10806007a2 100644 --- a/packages/core/src/common/user-store/user-store.injectable.ts +++ b/packages/core/src/common/user-store/user-store.injectable.ts @@ -16,7 +16,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; import getBasenameOfPathInjectable from "../path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; import userStorePreferenceDescriptorsInjectable from "./preference-descriptors.injectable"; const userStoreInjectable = getInjectable({ diff --git a/packages/core/src/common/utils/channel/channel.test.ts b/packages/core/src/common/utils/channel/channel.test.ts deleted file mode 100644 index bc6043d349..0000000000 --- a/packages/core/src/common/utils/channel/channel.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainer } from "@ogre-tools/injectable"; -import { getInjectable } from "@ogre-tools/injectable"; -import type { SendMessageToChannel } from "./message-to-channel-injection-token"; -import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token"; -import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; -import type { MessageChannel } from "./message-channel-listener-injection-token"; -import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import type { RequestFromChannel } from "./request-from-channel-injection-token"; -import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token"; -import type { RequestChannel } from "./request-channel-listener-injection-token"; -import type { AsyncFnMock } from "@async-fn/jest"; -import asyncFn from "@async-fn/jest"; -import { getPromiseStatus } from "@k8slens/test-utils"; -import { runInAction } from "mobx"; -import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens"; -import { - getRequestChannelListenerInjectable, - requestChannelListenerInjectionToken, -} from "../../../main/utils/channel/channel-listeners/listener-tokens"; - -type TestMessageChannel = MessageChannel; -type TestRequestChannel = RequestChannel; - -describe("channel", () => { - describe("messaging from main to renderer, given listener for channel in a window and application has started", () => { - let messageListenerInWindowMock: jest.Mock; - let mainDi: DiContainer; - let messageToChannel: SendMessageToChannel; - let builder: ApplicationBuilder; - - beforeEach(async () => { - builder = getApplicationBuilder(); - - messageListenerInWindowMock = jest.fn(); - - const testChannelListenerInTestWindowInjectable = getInjectable({ - id: "test-channel-listener-in-test-window", - - instantiate: () => ({ - channel: testMessageChannel, - handler: messageListenerInWindowMock, - }), - - injectionToken: messageChannelListenerInjectionToken, - }); - - builder.beforeWindowStart(({ windowDi }) => { - runInAction(() => { - windowDi.register(testChannelListenerInTestWindowInjectable); - }); - }); - - mainDi = builder.mainDi; - - await builder.startHidden(); - - messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken); - }); - - describe("given window is started", () => { - let someWindowFake: LensWindow; - - beforeEach(async () => { - someWindowFake = builder.applicationWindow.create("some-window"); - - await someWindowFake.start(); - }); - - it("when sending message, triggers listener in window", () => { - messageToChannel(testMessageChannel, "some-message"); - - expect(messageListenerInWindowMock).toHaveBeenCalledWith("some-message"); - }); - - it("given window is hidden, when sending message, does not trigger listener in window", () => { - someWindowFake.close(); - - messageToChannel(testMessageChannel, "some-message"); - - expect(messageListenerInWindowMock).not.toHaveBeenCalled(); - }); - }); - - it("given multiple started windows, when sending message, triggers listeners in all windows", async () => { - const someWindowFake = builder.applicationWindow.create("some-window"); - const someOtherWindowFake = builder.applicationWindow.create("some-other-window"); - - await someWindowFake.start(); - await someOtherWindowFake.start(); - - messageToChannel(testMessageChannel, "some-message"); - - expect(messageListenerInWindowMock.mock.calls).toEqual([ - ["some-message"], - ["some-message"], - ]); - }); - }); - - describe("messaging from renderer to main, given listener for channel in a main and application has started", () => { - let messageListenerInMainMock: jest.Mock; - let messageToChannel: SendMessageToChannel; - - beforeEach(async () => { - const applicationBuilder = getApplicationBuilder(); - - messageListenerInMainMock = jest.fn(); - - const testChannelListenerInMainInjectable = getInjectable({ - id: "test-channel-listener-in-main", - - instantiate: () => ({ - channel: testMessageChannel, - handler: messageListenerInMainMock, - }), - - injectionToken: messageChannelListenerInjectionToken, - }); - - applicationBuilder.beforeApplicationStart(({ mainDi }) => { - runInAction(() => { - mainDi.register(testChannelListenerInMainInjectable); - }); - }); - - await applicationBuilder.render(); - - const windowDi = applicationBuilder.applicationWindow.only.di; - - messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken); - }); - - it("when sending message, triggers listener in main", () => { - messageToChannel(testMessageChannel, "some-message"); - - expect(messageListenerInMainMock).toHaveBeenCalledWith("some-message"); - }); - }); - - describe("requesting from main in renderer, given listener for channel in a main and application has started", () => { - let requestListenerInMainMock: AsyncFnMock>; - let requestFromChannel: RequestFromChannel; - - beforeEach(async () => { - const applicationBuilder = getApplicationBuilder(); - - requestListenerInMainMock = asyncFn(); - - const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ - channel: testRequestChannel, - handler: () => requestListenerInMainMock, - }); - - applicationBuilder.beforeApplicationStart(({ mainDi }) => { - runInAction(() => { - mainDi.register(testChannelListenerInMainInjectable); - }); - }); - - await applicationBuilder.render(); - - const windowDi = applicationBuilder.applicationWindow.only.di; - - requestFromChannel = windowDi.inject( - requestFromChannelInjectionToken, - ); - }); - - describe("when requesting from channel", () => { - let actualPromise: Promise; - - beforeEach(() => { - actualPromise = requestFromChannel(testRequestChannel, "some-request"); - }); - - it("triggers listener in main", () => { - expect(requestListenerInMainMock).toHaveBeenCalledWith("some-request"); - }); - - it("does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(actualPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - it("when main resolves with response, resolves with response", async () => { - await requestListenerInMainMock.resolve("some-response"); - - const actual = await actualPromise; - - expect(actual).toBe("some-response"); - }); - }); - }); - - it("when registering multiple handlers for the same channel, throws", async () => { - const applicationBuilder = getApplicationBuilder(); - - const someChannelListenerInjectable = getInjectable({ - id: "some-channel-listener", - - instantiate: () => ({ - channel: testRequestChannel, - handler: () => () => "irrelevant", - }), - - injectionToken: requestChannelListenerInjectionToken, - }); - - const someOtherChannelListenerInjectable = getInjectable({ - id: "some-other-channel-listener", - - instantiate: () => ({ - channel: testRequestChannel, - handler: () => () => "irrelevant", - }), - - injectionToken: requestChannelListenerInjectionToken, - }); - - applicationBuilder.beforeApplicationStart(({ mainDi }) => { - runInAction(() => { - mainDi.register(someChannelListenerInjectable); - mainDi.register(someOtherChannelListenerInjectable); - }); - }); - - await expect(applicationBuilder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.'); - }); -}); - -const testMessageChannel: TestMessageChannel = { - id: "some-message-channel-id", -}; - -const testRequestChannel: TestRequestChannel = { - id: "some-request-channel-id", -}; - diff --git a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts deleted file mode 100644 index d6db37cea2..0000000000 --- a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 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 { Disposer } from "@k8slens/utilities"; -import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token"; - -export type EnlistMessageChannelListener = (listener: MessageChannelListener>) => Disposer; - -export const enlistMessageChannelListenerInjectionToken = getInjectionToken({ - id: "enlist-message-channel-listener", -}); diff --git a/packages/core/src/common/utils/channel/get-request-channel.ts b/packages/core/src/common/utils/channel/get-request-channel.ts deleted file mode 100644 index 4dc5b4914e..0000000000 --- a/packages/core/src/common/utils/channel/get-request-channel.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { RequestChannel } from "./request-channel-listener-injection-token"; - -export const getRequestChannel = (id: string): RequestChannel => ({ - id, -}); diff --git a/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts b/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts deleted file mode 100644 index 6ebc9ca7c1..0000000000 --- a/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { getStartableStoppable } from "../get-startable-stoppable"; -import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token"; -import { disposer } from "@k8slens/utilities"; - -const listeningOnMessageChannelsInjectable = getInjectable({ - id: "listening-on-message-channels", - - instantiate: (di) => { - const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); - const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken); - - return getStartableStoppable("listening-on-channels", () => ( - disposer(messageChannelListeners.map(enlistMessageChannelListener)) - )); - }, -}); - - -export default listeningOnMessageChannelsInjectable; diff --git a/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts deleted file mode 100644 index 5bfc45a82d..0000000000 --- a/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainerForInjection } from "@ogre-tools/injectable"; -import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; - -export interface MessageChannel { - id: string; - _messageSignature?: Message; // only used to mark `Message` as used -} - -export type MessageChannelHandler = Channel extends MessageChannel - ? (message: Message) => void - : never; - -export interface MessageChannelListener { - channel: Channel; - handler: MessageChannelHandler; -} - -export const messageChannelListenerInjectionToken = getInjectionToken>>( - { - id: "message-channel-listener", - }, -); - -export interface GetMessageChannelListenerInfo< - Channel extends MessageChannel, - Message, -> { - id: string; - channel: Channel; - handler: (di: DiContainerForInjection) => MessageChannelHandler; - causesSideEffects?: boolean; -} - -export function getMessageChannelListenerInjectable< - Channel extends MessageChannel, - Message, ->(info: GetMessageChannelListenerInfo) { - return getInjectable({ - id: `${info.channel.id}-listener-${info.id}`, - instantiate: (di) => ({ - channel: info.channel, - handler: info.handler(di), - }), - injectionToken: messageChannelListenerInjectionToken, - causesSideEffects: info.causesSideEffects, - }); -} diff --git a/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts deleted file mode 100644 index 2f0b84a3cc..0000000000 --- a/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -export interface RequestChannel { - id: string; - _requestSignature?: Request; // used only to mark `Request` as "used" - _responseSignature?: Response; // used only to mark `Response` as "used" -} diff --git a/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts b/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts index c823a8a8f9..210112c0b7 100644 --- a/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts +++ b/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts @@ -2,10 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; -export type ResolveSystemProxyChannel = RequestChannel; - -export const resolveSystemProxyChannel: ResolveSystemProxyChannel = { - id: "resolve-system-proxy-channel", -}; +export const resolveSystemProxyChannel = getRequestChannel( + "resolve-system-proxy-channel", +); diff --git a/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts b/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts index a97d95d726..482886d178 100644 --- a/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts +++ b/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { syncBoxChannel } from "./channels"; -import { getMessageChannelListenerInjectable } from "../channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import syncBoxStateInjectable from "./sync-box-state.injectable"; const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({ id: "init", channel: syncBoxChannel, - handler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value), + getHandler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value), }); export default syncBoxChannelListenerInjectable; diff --git a/packages/core/src/common/utils/sync-box/channels.ts b/packages/core/src/common/utils/sync-box/channels.ts index 4df0462dc3..5178ff013c 100644 --- a/packages/core/src/common/utils/sync-box/channels.ts +++ b/packages/core/src/common/utils/sync-box/channels.ts @@ -2,20 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../channel/message-channel-listener-injection-token"; -import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; +import { getMessageChannel, getRequestChannel } from "@k8slens/messaging"; -export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>; +export const syncBoxChannel = + getMessageChannel<{ id: string; value: any }>("sync-box-channel"); -export const syncBoxChannel: SyncBoxChannel = { - id: "sync-box-channel", -}; - -export type SyncBoxInitialValueChannel = RequestChannel< +export const syncBoxInitialValueChannel = getRequestChannel< void, { id: string; value: any }[] ->; - -export const syncBoxInitialValueChannel: SyncBoxInitialValueChannel = { - id: "sync-box-initial-value-channel", -}; +>("sync-box-initial-value-channel"); diff --git a/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts b/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts index 4a01fe71a0..2a142dc573 100644 --- a/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts +++ b/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IObservableValue } from "mobx"; import { computed } from "mobx"; import { syncBoxChannel } from "./channels"; -import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import syncBoxStateInjectable from "./sync-box-state.injectable"; import type { SyncBox } from "./sync-box-injection-token"; import { toJS } from "../toJS"; diff --git a/packages/core/src/common/utils/sync-box/handler.injectable.ts b/packages/core/src/common/utils/sync-box/handler.injectable.ts deleted file mode 100644 index f520585474..0000000000 --- a/packages/core/src/common/utils/sync-box/handler.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannelHandler } from "../channel/message-channel-listener-injection-token"; -import type { SyncBoxChannel } from "./channels"; -import syncBoxStateInjectable from "./sync-box-state.injectable"; - -const syncBoxChannelHandlerInjectable = getInjectable({ - id: "sync-box-channel-handler", - instantiate: (di): MessageChannelHandler => { - const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); - - return ({ id, value }) => getSyncBoxState(id)?.set(value); - }, -}); - -export default syncBoxChannelHandlerInjectable; diff --git a/packages/core/src/common/vars/build-semantic-version.injectable.ts b/packages/core/src/common/vars/build-semantic-version.injectable.ts index 2a49327480..402fb9d442 100644 --- a/packages/core/src/common/vars/build-semantic-version.injectable.ts +++ b/packages/core/src/common/vars/build-semantic-version.injectable.ts @@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable"; import { SemVer } from "semver"; import type { InitializableState } from "../initializable-state/create"; import { createInitializableState } from "../initializable-state/create"; -import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import type { RequestChannel } from "@k8slens/messaging"; export const buildVersionInjectionToken = getInjectionToken>({ id: "build-version-token", diff --git a/packages/core/src/common/weblinks-store/weblink-store.injectable.ts b/packages/core/src/common/weblinks-store/weblink-store.injectable.ts index cf793a2e58..843c8716e5 100644 --- a/packages/core/src/common/weblinks-store/weblink-store.injectable.ts +++ b/packages/core/src/common/weblinks-store/weblink-store.injectable.ts @@ -11,7 +11,7 @@ import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../logger.injectable"; import getBasenameOfPathInjectable from "../path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; import { weblinkStoreMigrationInjectionToken } from "./migration-token"; import { WeblinkStore } from "./weblink-store"; diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts index 847ae37f03..2295608520 100644 --- a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts +++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts @@ -12,7 +12,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../../../common/base- import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../../common/base-store/disable-sync"; import { persistStateToConfigInjectionToken } from "../../../common/base-store/save-to-file"; import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../../../common/utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable"; import { registeredExtensionsInjectable } from "./registered-extensions.injectable"; diff --git a/packages/core/src/extensions/extension-store.ts b/packages/core/src/extensions/extension-store.ts index cf435fb474..fe9cff2a02 100644 --- a/packages/core/src/extensions/extension-store.ts +++ b/packages/core/src/extensions/extension-store.ts @@ -20,7 +20,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../common/base-store/ import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../common/base-store/disable-sync"; import { persistStateToConfigInjectionToken } from "../common/base-store/save-to-file"; import getBasenameOfPathInjectable from "../common/path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../common/utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; export interface ExtensionStoreParams extends BaseStoreParams { migrations?: Migrations; diff --git a/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts b/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts index 9f5ff83270..9e08a96aac 100644 --- a/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts +++ b/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts @@ -10,7 +10,7 @@ import { persistStateToConfigInjectionToken } from "../../common/base-store/save import getConfigurationFileModelInjectable from "../../common/get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../../common/logger.injectable"; import getBasenameOfPathInjectable from "../../common/path/get-basename.injectable"; -import { enlistMessageChannelListenerInjectionToken } from "../../common/utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; import storeMigrationVersionInjectable from "../../common/vars/store-migration-version.injectable"; import { ExtensionsStore } from "./extensions-store"; diff --git a/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts b/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts index 80bfd108fd..e5d95bf7d8 100644 --- a/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts +++ b/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { autorun } from "mobx"; -import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import populateApplicationMenuInjectable from "./populate-application-menu.injectable"; import applicationMenuItemCompositeInjectable from "./application-menu-item-composite.injectable"; diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts index 85c687e478..953aa2b45a 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { getStartableStoppable } from "../../../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import processCheckingForUpdatesInjectable from "../../../main/process-checking-for-updates.injectable"; import withOrphanPromiseInjectable from "../../../../../common/utils/with-orphan-promise/with-orphan-promise.injectable"; diff --git a/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts b/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts index 470debf981..87b8f76cf3 100644 --- a/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts +++ b/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export type RestartAndInstallUpdateChannel = MessageChannel; diff --git a/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts b/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts index 940856ad3b..768ad50ffd 100644 --- a/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts +++ b/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { restartAndInstallUpdateChannel } from "../../common/restart-and-install-update-channel"; -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable"; const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({ id: "restart", channel: restartAndInstallUpdateChannel, - handler: (di) => di.inject(quitAndInstallUpdateInjectable), + getHandler: (di) => di.inject(quitAndInstallUpdateInjectable), }); export default restartAndInstallUpdateListenerInjectable; diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts index bcad45a0ac..bd949194e6 100644 --- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts +++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { autorun } from "mobx"; -import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import setUpdateOnQuitInjectable from "../../../../main/electron-app/features/set-update-on-quit.injectable"; import selectedUpdateChannelInjectable from "../../common/selected-update-channel/selected-update-channel.injectable"; import type { ReleaseChannel, UpdateChannel } from "../../common/update-channels"; diff --git a/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts b/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts index 2502a599a2..d60f8da909 100644 --- a/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts +++ b/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts @@ -4,13 +4,13 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { restartAndInstallUpdateChannel } from "../common/restart-and-install-update-channel"; -import messageToChannelInjectable from "../../../renderer/utils/channel/message-to-channel.injectable"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; const restartAndInstallUpdateInjectable = getInjectable({ id: "restart-and-install-update", instantiate: (di) => { - const messageToChannel = di.inject(messageToChannelInjectable); + const messageToChannel = di.inject(sendMessageToChannelInjectionToken); return () => { messageToChannel(restartAndInstallUpdateChannel); diff --git a/packages/core/src/features/certificate-authorities/common/channel.ts b/packages/core/src/features/certificate-authorities/common/channel.ts index 5fb58ee1ca..c81ba9be44 100644 --- a/packages/core/src/features/certificate-authorities/common/channel.ts +++ b/packages/core/src/features/certificate-authorities/common/channel.ts @@ -2,7 +2,6 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - -import { getRequestChannel } from "../../../common/utils/channel/get-request-channel"; +import { getRequestChannel } from "@k8slens/messaging"; export const casChannel = getRequestChannel("certificate-authorities"); diff --git a/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts b/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts index 62882fb49f..a7c52503c5 100644 --- a/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts +++ b/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts @@ -8,6 +8,7 @@ import { casChannel } from "../common/channel"; import certificateAuthoritiesChannelListenerInjectable from "./channel-handler.injectable"; export default getGlobalOverride(certificateAuthoritiesChannelListenerInjectable, () => ({ + id: "certificate-authorities-channel-listener", channel: casChannel, handler: () => [], })); diff --git a/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts b/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts index 206a68ba94..d776e9fcce 100644 --- a/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts +++ b/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts @@ -2,14 +2,15 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { casChannel } from "../common/channel"; import { globalAgent } from "https"; import { isString } from "@k8slens/utilities"; const certificateAuthoritiesChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "certificate-authorities-channel-listener", channel: casChannel, - handler: () => () => { + getHandler: () => () => { if (Array.isArray(globalAgent.options.ca)) { return globalAgent.options.ca.filter(isString); } diff --git a/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts b/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts index e3c840a95a..e9ac074989 100644 --- a/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts +++ b/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { casChannel } from "../common/channel"; import { requestSystemCAsInjectionToken } from "../common/request-system-cas-token"; diff --git a/packages/core/src/features/cluster/activation/common/channels.ts b/packages/core/src/features/cluster/activation/common/channels.ts index 3631c4d9b8..55172e75fc 100644 --- a/packages/core/src/features/cluster/activation/common/channels.ts +++ b/packages/core/src/features/cluster/activation/common/channels.ts @@ -4,7 +4,7 @@ */ import type { ClusterId } from "../../../../common/cluster-types"; -import { getRequestChannel } from "../../../../common/utils/channel/get-request-channel"; +import { getRequestChannel } from "@k8slens/messaging"; export interface ActivateCluster { clusterId: ClusterId; diff --git a/packages/core/src/features/cluster/activation/common/request-token.ts b/packages/core/src/features/cluster/activation/common/request-token.ts index 5bee44208f..0abe5775b3 100644 --- a/packages/core/src/features/cluster/activation/common/request-token.ts +++ b/packages/core/src/features/cluster/activation/common/request-token.ts @@ -4,7 +4,7 @@ */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { ChannelRequester } from "../../../../common/utils/channel/request-from-channel-injection-token"; +import type { ChannelRequester } from "@k8slens/messaging"; import type { activateClusterChannel, deactivateClusterChannel } from "./channels"; export type RequestClusterActivation = ChannelRequester; diff --git a/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts b/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts index 4ce22e6311..08b068abef 100644 --- a/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts +++ b/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts @@ -2,13 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { activateClusterChannel } from "../common/channels"; import requestClusterActivationInjectable from "./request-activation.injectable"; const activateClusterRequestChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "activate-cluster-request-channel-listener", channel: activateClusterChannel, - handler: (di) => di.inject(requestClusterActivationInjectable), + getHandler: (di) => di.inject(requestClusterActivationInjectable), }); export default activateClusterRequestChannelListenerInjectable; diff --git a/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts b/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts index e24ce48ba6..bbfe79a41d 100644 --- a/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts +++ b/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts @@ -2,13 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { deactivateClusterChannel } from "../common/channels"; import requestClusterDeactivationInjectable from "./request-deactivation.injectable"; const clusterDeactivationRequestChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "cluster-deactivation-request-channel-listener", channel: deactivateClusterChannel, - handler: (di) => di.inject(requestClusterDeactivationInjectable), + getHandler: (di) => di.inject(requestClusterDeactivationInjectable), }); export default clusterDeactivationRequestChannelListenerInjectable; diff --git a/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts b/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts index 1677d67792..6609516918 100644 --- a/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts +++ b/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts @@ -3,14 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { activateClusterChannel } from "../common/channels"; import { requestClusterActivationInjectionToken } from "../common/request-token"; const requestClusterActivationInjectable = getInjectable({ id: "request-cluster-activation", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return (req) => requestFromChannel(activateClusterChannel, req); }, diff --git a/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts b/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts index 362784e91b..e019b8b615 100644 --- a/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts +++ b/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts @@ -3,14 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { deactivateClusterChannel } from "../common/channels"; import { requestClusterDeactivationInjectionToken } from "../common/request-token"; const requestClusterDeactivationInjectable = getInjectable({ id: "request-cluster-deactivation", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return (clusterId) => requestFromChannel(deactivateClusterChannel, clusterId); }, diff --git a/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts index bf33a23165..f6bdc1d072 100644 --- a/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts +++ b/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts @@ -3,10 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; -export type ClearClusterAsDeletingChannel = RequestChannel; - -export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = { - id: "clear-cluster-as-deleting", -}; +export const clearClusterAsDeletingChannel = getRequestChannel( + "clear-cluster-as-deleting", +); diff --git a/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts index 0e9142fcd3..b3a007b1bd 100644 --- a/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts +++ b/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts @@ -3,10 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannel } from "@k8slens/messaging"; +import { getRequestChannel } from "@k8slens/messaging"; export type DeleteClusterChannel = RequestChannel; -export const deleteClusterChannel: DeleteClusterChannel = { - id: "delete-cluster", -}; +export const deleteClusterChannel = getRequestChannel( + "delete-cluster", +); diff --git a/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts index 57ef2e3a8d..7b93b292d5 100644 --- a/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts +++ b/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts @@ -3,10 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import { getRequestChannel } from "@k8slens/messaging"; -export type SetClusterAsDeletingChannel = RequestChannel; - -export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = { - id: "set-cluster-as-deleting", -}; +export const setClusterAsDeletingChannel = getRequestChannel( + "set-cluster-as-deleting", +); diff --git a/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts index a8dd2a80b0..a83de06acb 100644 --- a/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "clear-cluster-as-deleting-channel-listener", channel: clearClusterAsDeletingChannel, - handler: (di) => { + getHandler: (di) => { const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); return (clusterId) => { diff --git a/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts index 94caf169ba..30d976c59c 100644 --- a/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts @@ -10,12 +10,13 @@ import removePathInjectable from "../../../../common/fs/remove.injectable"; import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; import clusterConnectionInjectable from "../../../../main/cluster/cluster-connection.injectable"; import { noop } from "@k8slens/utilities"; -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { deleteClusterChannel } from "../common/delete-channel"; const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "delete-cluster-channel-listener", channel: deleteClusterChannel, - handler: (di) => { + getHandler: (di) => { const emitAppEvent = di.inject(emitAppEventInjectable); const clusterStore = di.inject(clusterStoreInjectable); const clusterFrames = di.inject(clusterFramesInjectable); diff --git a/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts index f532b4a81f..74bd168723 100644 --- a/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({ + id: "set-cluster-as-deleting-channel-handler", channel: setClusterAsDeletingChannel, - handler: (di) => { + getHandler: (di) => { const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); return (clusterId) => { diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts index e476998ca0..1e3125a52a 100644 --- a/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -12,7 +12,7 @@ export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise { - const requestChannel = di.inject(requestFromChannelInjectable); + const requestChannel = di.inject(requestFromChannelInjectionToken); return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId); }, diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts index c1286e3103..9e415e79d0 100644 --- a/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { deleteClusterChannel } from "../common/delete-channel"; export type RequestDeleteCluster = (clusterId: ClusterId) => Promise; @@ -12,7 +12,7 @@ export type RequestDeleteCluster = (clusterId: ClusterId) => Promise; const requestDeleteClusterInjectable = getInjectable({ id: "request-delete-cluster", instantiate: (di): RequestDeleteCluster => { - const requestChannel = di.inject(requestFromChannelInjectable); + const requestChannel = di.inject(requestFromChannelInjectionToken); return (clusterId) => requestChannel(deleteClusterChannel, clusterId); }, diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts index de3a6393b3..0e86632f89 100644 --- a/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts +++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -12,7 +12,7 @@ export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise { - const requestChannel = di.inject(requestFromChannelInjectable); + const requestChannel = di.inject(requestFromChannelInjectionToken); return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId); }, diff --git a/packages/core/src/features/cluster/state-sync/common/channels.ts b/packages/core/src/features/cluster/state-sync/common/channels.ts index 7ceeb82f84..66ce718955 100644 --- a/packages/core/src/features/cluster/state-sync/common/channels.ts +++ b/packages/core/src/features/cluster/state-sync/common/channels.ts @@ -4,8 +4,7 @@ */ import type { ClusterId, ClusterState } from "../../../../common/cluster-types"; -import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { MessageChannel, RequestChannel } from "@k8slens/messaging"; export interface ClusterStateSync { clusterId: ClusterId; diff --git a/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts b/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts index 8cadd32864..4499d2ac66 100644 --- a/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts @@ -3,18 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import type { ClusterStateSync } from "../common/channels"; import { clusterStateSyncChannel } from "../common/channels"; -export type EmitClusterStateUpdate = MessageChannelHandler; - const emitClusterStateUpdateInjectable = getInjectable({ id: "emit-cluster-state-update", - instantiate: (di): EmitClusterStateUpdate => { + instantiate: (di) => { const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); - return (message) => sendMessageToChannel(clusterStateSyncChannel, message); + return (message: ClusterStateSync) => sendMessageToChannel(clusterStateSyncChannel, message); }, }); diff --git a/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts b/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts index 708f032d48..db65024973 100644 --- a/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { initialClusterStatesChannel } from "../common/channels"; const handleInitialClusterStateSyncInjectable = getRequestChannelListenerInjectable({ + id: "handle-initial-cluster-state-sync", channel: initialClusterStatesChannel, - handler: (di) => { + getHandler: (di) => { const clusterStore = di.inject(clusterStoreInjectable); return () => clusterStore.clustersList.map(cluster => ({ diff --git a/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts b/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts index 9863a391e8..a3778d096e 100644 --- a/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable"; -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import { clusterStateSyncChannel } from "../common/channels"; const clusterStateListenerInjectable = getMessageChannelListenerInjectable({ channel: clusterStateSyncChannel, id: "main", - handler: (di) => { + getHandler: (di) => { const getClusterById = di.inject(getClusterByIdInjectable); return ({ clusterId, state }) => getClusterById(clusterId)?.setState(state); diff --git a/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts b/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts index 89f72fbcf5..497d2c5aaf 100644 --- a/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import type { RequestChannelHandler } from "@k8slens/messaging"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { initialClusterStatesChannel } from "../common/channels"; export type RequestInitialClusterStates = RequestChannelHandler; @@ -12,7 +12,7 @@ export type RequestInitialClusterStates = RequestChannelHandler { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return () => requestFromChannel(initialClusterStatesChannel); }, diff --git a/packages/core/src/features/extensions/navigate/common/channel.ts b/packages/core/src/features/extensions/navigate/common/channel.ts index 4c6892e6cb..ec7bc967dc 100644 --- a/packages/core/src/features/extensions/navigate/common/channel.ts +++ b/packages/core/src/features/extensions/navigate/common/channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export interface NavigateForExtensionArgs { extId: string; diff --git a/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts b/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts index fccf0efca6..2397def4f6 100644 --- a/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts +++ b/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts @@ -2,15 +2,15 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable"; import type { LensRendererExtension } from "../../../../extensions/lens-renderer-extension"; import { navigateForExtensionChannel } from "../common/channel"; const navigateForExtensionListenerInjectable = getMessageChannelListenerInjectable({ channel: navigateForExtensionChannel, - id: "main", - handler: (di) => { + id: "renderer", + getHandler: (di) => { const extensionLoader = di.inject(extensionLoaderInjectable); return ({ extId, pageId, params }) => { diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts index 7a0d5e6b47..b4195a876f 100644 --- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts +++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { asyncComputed } from "@ogre-tools/injectable-react"; import { getActiveHelmRepositoriesChannel } from "../../../../../common/helm/get-active-helm-repositories-channel"; -import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import showErrorNotificationInjectable from "../../../../../renderer/components/notifications/show-error-notification.injectable"; import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable"; import { runInAction } from "mobx"; diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts index 6b39d8dddf..3c2199c490 100644 --- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts +++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { HelmRepo } from "../../../../../../../common/helm/helm-repo"; -import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable"; import showErrorNotificationInjectable from "../../../../../../../renderer/components/notifications/show-error-notification.injectable"; import showSuccessNotificationInjectable from "../../../../../../../renderer/components/notifications/show-success-notification.injectable"; diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts index 3aa56a4b04..4af5543c28 100644 --- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts +++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { HelmRepo } from "../../../../../common/helm/helm-repo"; -import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable"; import { removeHelmRepositoryChannel } from "../../../../../common/helm/remove-helm-repository-channel"; diff --git a/packages/core/src/features/navigation/reload-page/common/channel.ts b/packages/core/src/features/navigation/reload-page/common/channel.ts index b920067a4d..50cdaa8918 100644 --- a/packages/core/src/features/navigation/reload-page/common/channel.ts +++ b/packages/core/src/features/navigation/reload-page/common/channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export type ReloadPageChannel = MessageChannel; diff --git a/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts b/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts index 9953ddcbf9..4b9842cf7d 100644 --- a/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts +++ b/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts @@ -8,6 +8,7 @@ import { reloadPageChannel } from "../common/channel"; import reloadPageChannelListenerInjectable from "./register-listener.injectable"; export default getGlobalOverride(reloadPageChannelListenerInjectable, () => ({ + id: "reload-page-channel-listener", channel: reloadPageChannel, handler: () => {}, })); diff --git a/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts b/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts index a42d818729..f71096bebf 100644 --- a/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts +++ b/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts @@ -2,13 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import { reloadPageChannel } from "../common/channel"; const reloadPageChannelListenerInjectable = getMessageChannelListenerInjectable({ id: "handler", channel: reloadPageChannel, - handler: () => () => location.reload(), + getHandler: () => () => location.reload(), causesSideEffects: true, }); diff --git a/packages/core/src/features/path-picking-dialog/common/channel.ts b/packages/core/src/features/path-picking-dialog/common/channel.ts index 98c19b4ad6..c5e8b9386d 100644 --- a/packages/core/src/features/path-picking-dialog/common/channel.ts +++ b/packages/core/src/features/path-picking-dialog/common/channel.ts @@ -4,7 +4,7 @@ */ import type { OpenDialogOptions } from "electron"; -import type { RequestChannel } from "../../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannel } from "@k8slens/messaging"; export type PathPickingResponse = { canceled: true; diff --git a/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts b/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts index d566ac9728..dded293c83 100644 --- a/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts +++ b/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts @@ -4,12 +4,13 @@ */ import askUserForFilePathsInjectable from "../../../main/ipc/ask-user-for-file-paths.injectable"; -import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { openPathPickingDialogChannel } from "../common/channel"; const openPathPickingDialogListener = getRequestChannelListenerInjectable({ + id: "open-path-picking-dialog", channel: openPathPickingDialogChannel, - handler: (di) => di.inject(askUserForFilePathsInjectable), + getHandler: (di) => di.inject(askUserForFilePathsInjectable), }); export default openPathPickingDialogListener; diff --git a/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts b/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts index 5dde31f46d..528bffc634 100644 --- a/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts +++ b/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { PathPickOpts } from "../../../renderer/components/path-picker"; -import requestFromChannelInjectable from "../../../renderer/utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { openPathPickingDialogChannel } from "../common/channel"; export type OpenPathPickingDialog = (options: PathPickOpts) => Promise; @@ -12,7 +12,7 @@ export type OpenPathPickingDialog = (options: PathPickOpts) => Promise; const openPathPickingDialogInjectable = getInjectable({ id: "open-path-picking-dialog", instantiate: (di): OpenPathPickingDialog => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return async (options) => { const { onPick, onCancel, ...dialogOptions } = options; diff --git a/packages/core/src/features/shell-sync/common/failure-channel.ts b/packages/core/src/features/shell-sync/common/failure-channel.ts index aed25b0da0..268640fe89 100644 --- a/packages/core/src/features/shell-sync/common/failure-channel.ts +++ b/packages/core/src/features/shell-sync/common/failure-channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel } from "@k8slens/messaging"; export const shellSyncFailedChannel: MessageChannel = { id: "shell-sync-failed-channel", diff --git a/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts b/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts index 5abdfafa52..7dbfb094f2 100644 --- a/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts +++ b/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts @@ -3,16 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannelSender } from "../../../common/utils/channel/message-to-channel-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import { shellSyncFailedChannel } from "../common/failure-channel"; const emitShellSyncFailedInjectable = getInjectable({ id: "emit-shell-sync-failed", - instantiate: (di): MessageChannelSender => { + instantiate: (di) => { const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); - return (error) => sendMessageToChannel(shellSyncFailedChannel, error); + return (error: string) => sendMessageToChannel(shellSyncFailedChannel, error); }, }); diff --git a/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts b/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts index 2014397fad..135143b3a6 100644 --- a/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts +++ b/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts @@ -2,14 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import showErrorNotificationInjectable from "../../../renderer/components/notifications/show-error-notification.injectable"; import { shellSyncFailedChannel } from "../common/failure-channel"; const shellSyncFailureListenerInjectable = getMessageChannelListenerInjectable({ id: "notification", channel: shellSyncFailedChannel, - handler: (di) => { + getHandler: (di) => { const showErrorNotification = di.inject(showErrorNotificationInjectable); return (errorMessage) => showErrorNotification(`Failed to sync shell environment: ${errorMessage}`); diff --git a/packages/core/src/features/theme/system-type/common/channels.ts b/packages/core/src/features/theme/system-type/common/channels.ts index 3134f20378..49fb96ef0a 100644 --- a/packages/core/src/features/theme/system-type/common/channels.ts +++ b/packages/core/src/features/theme/system-type/common/channels.ts @@ -3,8 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { MessageChannel, RequestChannel } from "@k8slens/messaging"; export type SystemThemeType = "dark" | "light"; diff --git a/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts b/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts index c085e6615a..d078e81e33 100644 --- a/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts +++ b/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts @@ -3,18 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import type { SystemThemeType } from "../common/channels"; import { systemThemeTypeUpdateChannel } from "../common/channels"; -export type EmitSystemThemeTypeUpdate = MessageChannelHandler; - const emitSystemThemeTypeUpdateInjectable = getInjectable({ id: "emit-system-theme-type-update", - instantiate: (di): EmitSystemThemeTypeUpdate => { + instantiate: (di) => { const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); - return (type) => sendMessageToChannel(systemThemeTypeUpdateChannel, type); + return (type: SystemThemeType) => sendMessageToChannel(systemThemeTypeUpdateChannel, type); }, }); diff --git a/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts b/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts index 1468b1eeda..7af8a0a069 100644 --- a/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts +++ b/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts @@ -4,12 +4,13 @@ */ import operatingSystemThemeInjectable from "../../../../main/theme/operating-system-theme.injectable"; -import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import { initialSystemThemeTypeChannel } from "../common/channels"; const initialSystemThemeTypeHandler = getRequestChannelListenerInjectable({ + id: "initial-system-theme-type-listener", channel: initialSystemThemeTypeChannel, - handler: (di) => { + getHandler: (di) => { const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); return () => operatingSystemTheme.get(); diff --git a/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts b/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts index 74fe73cf03..fd84d7f90c 100644 --- a/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts +++ b/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; -import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; +import type { RequestChannelHandler } from "@k8slens/messaging"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { initialSystemThemeTypeChannel } from "../common/channels"; export type RequestInitialSystemThemeType = RequestChannelHandler; @@ -12,7 +12,7 @@ export type RequestInitialSystemThemeType = RequestChannelHandler { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return () => requestFromChannel(initialSystemThemeTypeChannel); }, diff --git a/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts b/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts index 4eb57c9b85..dac9061c28 100644 --- a/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts +++ b/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts @@ -2,14 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable"; import { systemThemeTypeUpdateChannel } from "../common/channels"; const systemThemeTypeUpdateListenerInjectable = getMessageChannelListenerInjectable({ channel: systemThemeTypeUpdateChannel, id: "main", - handler: (di) => { + getHandler: (di) => { const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable); return (type) => systemThemeConfiguration.set(type); diff --git a/packages/core/src/jest-after-env.setup.ts b/packages/core/src/jest-after-env.setup.ts index 69b18161a8..df0fcfff4d 100644 --- a/packages/core/src/jest-after-env.setup.ts +++ b/packages/core/src/jest-after-env.setup.ts @@ -4,3 +4,8 @@ */ import "@testing-library/jest-dom"; + +// Note: This is a kludge to prevent "Hooks cannot be defined inside tests" error +// when importing a test util inside a test suite. +import { render } from "@testing-library/react"; +void render; diff --git a/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts b/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts index 568d63f1ea..ccf8be5054 100644 --- a/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts +++ b/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts @@ -4,11 +4,12 @@ */ import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; import appPathsInjectable from "../../common/app-paths/app-paths.injectable"; -import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "app-paths-request-channel-listener", channel: appPathsChannel, - handler: (di) => { + getHandler: (di) => { const appPaths = di.inject(appPathsInjectable); return () => appPaths; diff --git a/packages/core/src/main/build-version/setup-channel.injectable.ts b/packages/core/src/main/build-version/setup-channel.injectable.ts index 05da92db6e..88661c899f 100644 --- a/packages/core/src/main/build-version/setup-channel.injectable.ts +++ b/packages/core/src/main/build-version/setup-channel.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { buildVersionChannel } from "../../common/vars/build-semantic-version.injectable"; -import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import buildVersionInjectable from "../vars/build-version/build-version.injectable"; const buildVersionChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "build-version-channel-listener", channel: buildVersionChannel, - handler: (di) => { + getHandler: (di) => { const buildVersion = di.inject(buildVersionInjectable); return () => buildVersion.get(); diff --git a/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts index cd77332185..a2fe077c1d 100644 --- a/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts +++ b/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts @@ -7,7 +7,7 @@ import { reaction } from "mobx"; import ipcMainInjectionToken from "../../common/ipc/ipc-main-injection-token"; import { catalogInitChannel } from "../../common/ipc/catalog"; import { disposer } from "@k8slens/utilities"; -import { getStartableStoppable } from "../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable"; import catalogSyncBroadcasterInjectable from "./broadcaster.injectable"; import { toJS } from "../../common/utils"; diff --git a/packages/core/src/main/cluster/visibility-handler.injectable.ts b/packages/core/src/main/cluster/visibility-handler.injectable.ts index 31f6ff13ec..ef4277e905 100644 --- a/packages/core/src/main/cluster/visibility-handler.injectable.ts +++ b/packages/core/src/main/cluster/visibility-handler.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { clusterVisibilityChannel } from "../../common/cluster/visibility-channel"; -import { getMessageChannelListenerInjectable } from "../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import visibleClusterInjectable from "./visible-cluster.injectable"; const clusterVisibilityHandlerInjectable = getMessageChannelListenerInjectable({ channel: clusterVisibilityChannel, id: "base", - handler: (di) => { + getHandler: (di) => { const visibleCluster = di.inject(visibleClusterInjectable); return (clusterId) => visibleCluster.set(clusterId); diff --git a/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts b/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts index 818bf938ec..02f0c916b6 100644 --- a/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts +++ b/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import operatingSystemThemeStateInjectable from "../../theme/operating-system-theme-state.injectable"; import nativeThemeInjectable from "./native-theme.injectable"; import getElectronThemeInjectable from "./get-electron-theme.injectable"; diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts index 0712f1e128..b374eec1ca 100644 --- a/packages/core/src/main/getDiForUnitTesting.ts +++ b/packages/core/src/main/getDiForUnitTesting.ts @@ -29,6 +29,8 @@ import { setLegacyGlobalDiForExtensionApi, } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeature, testUtils as messagingTestUtils } from "@k8slens/messaging"; export function getDiForUnitTesting() { const di = createContainer("main"); @@ -36,6 +38,11 @@ export function getDiForUnitTesting() { registerMobX(di); setLegacyGlobalDiForExtensionApi(di, "main"); + runInAction(() => { + registerFeature(di, messagingFeature, messagingTestUtils.messagingFeatureForUnitTesting); + + }); + di.preventSideEffects(); runInAction(() => { diff --git a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts index 1c68bf6fd7..d5343b1d4f 100644 --- a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts +++ b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts @@ -3,12 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel"; -import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import addHelmRepositoryInjectable from "./add-helm-repository.injectable"; -const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ - channel: addHelmRepositoryChannel, - handler: (di) => di.inject(addHelmRepositoryInjectable), -}); +const addHelmRepositoryChannelListenerInjectable = + getRequestChannelListenerInjectable({ + id: "add-helm-repository-channel-listener", + channel: addHelmRepositoryChannel, + getHandler: (di) => di.inject(addHelmRepositoryInjectable), + }); export default addHelmRepositoryChannelListenerInjectable; diff --git a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts index 5292f8a662..27272a76f3 100644 --- a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts +++ b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts @@ -5,17 +5,16 @@ import { getInjectable } from "@ogre-tools/injectable"; import execHelmInjectable from "../../exec-helm/exec-helm.injectable"; import loggerInjectable from "../../../../common/logger.injectable"; -import type { AddHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel"; -import type { RequestChannelHandler } from "../../../utils/channel/channel-listeners/listener-tokens"; +import type { HelmRepo } from "../../../../common/helm/helm-repo"; const addHelmRepositoryInjectable = getInjectable({ id: "add-helm-repository", - instantiate: (di): RequestChannelHandler => { + instantiate: (di) => { const execHelm = di.inject(execHelmInjectable); const logger = di.inject(loggerInjectable); - return async (repo) => { + return async (repo: HelmRepo) => { const { name, url, @@ -59,12 +58,12 @@ const addHelmRepositoryInjectable = getInjectable({ if (result.callWasSuccessful) { return { - callWasSuccessful: true, + callWasSuccessful: true as const, }; } return { - callWasSuccessful: false, + callWasSuccessful: false as const, error: result.error.stderr || result.error.message, }; }; diff --git a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts index 5ef0f2b5a4..a3cd9f2529 100644 --- a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts +++ b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel"; -import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable"; const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "get-active-helm-repositories-channel-listener", channel: getActiveHelmRepositoriesChannel, - handler: (di) => di.inject(getActiveHelmRepositoriesInjectable), + getHandler: (di) => di.inject(getActiveHelmRepositoriesInjectable), }); export default getActiveHelmRepositoriesChannelListenerInjectable; diff --git a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts index 8a4e04b87c..84b147fed1 100644 --- a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts +++ b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts @@ -4,11 +4,12 @@ */ import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable"; import { removeHelmRepositoryChannel } from "../../../../common/helm/remove-helm-repository-channel"; -import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "remove-helm-repository-channel-listener", channel: removeHelmRepositoryChannel, - handler: (di) => di.inject(removeHelmRepositoryInjectable), + getHandler: (di) => di.inject(removeHelmRepositoryInjectable), }); export default removeHelmRepositoryChannelListenerInjectable; diff --git a/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts b/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts index f8a0685d7c..3d0326711e 100644 --- a/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts +++ b/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import showApplicationWindowInjectable from "../start-main-application/lens-window/show-application-window.injectable"; -import type { RequestChannelHandler } from "../utils/channel/channel-listeners/listener-tokens"; +import type { RequestChannelHandler } from "@k8slens/messaging"; import type { openPathPickingDialogChannel } from "../../features/path-picking-dialog/common/channel"; import showOpenDialogInjectable from "../electron-app/features/show-open-dialog.injectable"; diff --git a/packages/core/src/main/kubectl/apply-all-handler.injectable.ts b/packages/core/src/main/kubectl/apply-all-handler.injectable.ts index 7f62ca14fc..00f58e5e3f 100644 --- a/packages/core/src/main/kubectl/apply-all-handler.injectable.ts +++ b/packages/core/src/main/kubectl/apply-all-handler.injectable.ts @@ -6,11 +6,12 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.inject import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; import { kubectlApplyAllChannel } from "../../common/kube-helpers/channels"; import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; -import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjectable({ + id: "kubectl-apply-all-channel-handler-listener", channel: kubectlApplyAllChannel, - handler: (di) => { + getHandler: (di) => { const getClusterById = di.inject(getClusterByIdInjectable); const emitAppEvent = di.inject(emitAppEventInjectable); diff --git a/packages/core/src/main/kubectl/delete-all-handler.injectable.ts b/packages/core/src/main/kubectl/delete-all-handler.injectable.ts index 715eb0caf9..5d207be482 100644 --- a/packages/core/src/main/kubectl/delete-all-handler.injectable.ts +++ b/packages/core/src/main/kubectl/delete-all-handler.injectable.ts @@ -6,11 +6,12 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.inject import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; import { kubectlDeleteAllChannel } from "../../common/kube-helpers/channels"; import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; -import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInjectable({ + id: "kubectl-delete-all-channel-handler-listener", channel: kubectlDeleteAllChannel, - handler: (di) => { + getHandler: (di) => { const emitAppEvent = di.inject(emitAppEventInjectable); const getClusterById = di.inject(getClusterByIdInjectable); diff --git a/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts b/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts index 5f6938912a..6f35450273 100644 --- a/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts +++ b/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { lensProxyCertificateChannel } from "../../common/certificate/lens-proxy-certificate-channel"; -import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable"; const lensProxyCertificateRequestHandlerInjectable = getRequestChannelListenerInjectable({ + id: "lens-proxy-certificate-request-handler-listener", channel: lensProxyCertificateChannel, - handler: (di) => { + getHandler: (di) => { const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get(); return () => ({ diff --git a/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts b/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts index d29210cda1..11d23e6a4f 100644 --- a/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts @@ -3,17 +3,17 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { currentClusterMessageChannel } from "../../../../common/cluster/current-cluster-channel"; -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import currentClusterFrameClusterIdStateInjectable from "./current-cluster-frame-cluster-id-state.injectable"; -const currentVisibileClusterListenerInjectable = getMessageChannelListenerInjectable({ - id: "current-visibile-cluster", +const currentVisibleClusterListenerInjectable = getMessageChannelListenerInjectable({ + id: "current-visible-cluster", channel: currentClusterMessageChannel, - handler: (di) => { + getHandler: (di) => { const currentClusterFrameState = di.inject(currentClusterFrameClusterIdStateInjectable); return clusterId => currentClusterFrameState.set(clusterId); }, }); -export default currentVisibileClusterListenerInjectable; +export default currentVisibleClusterListenerInjectable; diff --git a/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts b/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts index 8b906c79e9..4769c12256 100644 --- a/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import { rootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel"; import { runManyFor } from "@k8slens/run-many"; import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phases"; @@ -10,7 +10,7 @@ import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phase const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({ id: "action", channel: rootFrameHasRenderedChannel, - handler: (di) => { + getHandler: (di) => { const runMany = runManyFor(di); return runMany(afterRootFrameIsReadyInjectionToken); diff --git a/packages/core/src/main/tray/menu-icon/reactive.injectable.ts b/packages/core/src/main/tray/menu-icon/reactive.injectable.ts index 8c6d358477..4fbc8c2448 100644 --- a/packages/core/src/main/tray/menu-icon/reactive.injectable.ts +++ b/packages/core/src/main/tray/menu-icon/reactive.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { reaction } from "mobx"; -import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import electronTrayInjectable from "../electron-tray/electron-tray.injectable"; import trayIconInjectable from "./tray-icon.injectable"; diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts index 378bceafd9..a216675b01 100644 --- a/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts +++ b/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; +import { getStartableStoppable } from "@k8slens/startable-stoppable"; import { reaction } from "mobx"; import type { MinimalTrayMenuItem } from "../electron-tray/electron-tray.injectable"; import electronTrayInjectable from "../electron-tray/electron-tray.injectable"; diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts deleted file mode 100644 index db6435ea56..0000000000 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { IpcMainEvent } from "electron"; -import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token"; - -const enlistMessageChannelListenerInjectable = getInjectable({ - id: "enlist-message-channel-listener-for-main", - - instantiate: (di) => { - const ipcMain = di.inject(ipcMainInjectionToken); - - return ({ channel, handler }) => { - const nativeOnCallback = (_: IpcMainEvent, message: unknown) => { - handler(message); - }; - - ipcMain.on(channel.id, nativeOnCallback); - - return () => { - ipcMain.off(channel.id, nativeOnCallback); - }; - }; - }, - - injectionToken: enlistMessageChannelListenerInjectionToken, -}); - -export default enlistMessageChannelListenerInjectable; diff --git a/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts deleted file mode 100644 index 1e6d0f296c..0000000000 --- a/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { disposer } from "@k8slens/utilities"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable"; -import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; -import { requestChannelListenerInjectionToken } from "./listener-tokens"; - -const listeningOnRequestChannelsInjectable = getInjectable({ - id: "listening-on-request-channels", - instantiate: (di) => { - const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable); - const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken); - - return getStartableStoppable("listening-on-request-channels", () => { - const seenChannels = new Set>(); - - for (const listener of requestChannelListeners) { - if (seenChannels.has(listener.channel)) { - throw new Error(`Tried to register a multiple channel handlers for "${listener.channel.id}", only one handler is supported for a request channel.`); - } - - seenChannels.add(listener.channel); - } - - return disposer(requestChannelListeners.map(enlistRequestChannelListener)); - }); - }, -}); - -export default listeningOnRequestChannelsInjectable; diff --git a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts deleted file mode 100644 index c83425109c..0000000000 --- a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; -import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; -import listeningOnRequestChannelsInjectable from "./listening-on-request-channels.injectable"; - -const startListeningOnChannelsInjectable = getInjectable({ - id: "start-listening-on-channels-main", - - instantiate: (di) => ({ - run: () => { - const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); - const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); - - listeningOnMessageChannels.start(); - listeningOnRequestChannels.start(); - }, - }), - - injectionToken: onLoadOfApplicationInjectionToken, -}); - -export default startListeningOnChannelsInjectable; diff --git a/packages/core/src/main/utils/channel/message-to-channel.injectable.ts b/packages/core/src/main/utils/channel/message-to-channel.injectable.ts deleted file mode 100644 index 392120509d..0000000000 --- a/packages/core/src/main/utils/channel/message-to-channel.injectable.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; -import clusterFramesInjectable from "../../../common/cluster-frames.injectable"; - -const messageToChannelInjectable = getInjectable({ - id: "message-to-channel", - - instantiate: (di) => { - const getVisibleWindows = di.inject(getVisibleWindowsInjectable); - const clusterFrames = di.inject(clusterFramesInjectable); - - return ((channel, data) => { - for (const window of getVisibleWindows()) { - window.send({ channel: channel.id, data }); - - clusterFrames.forEach(frameInfo => { - window.send({ channel: channel.id, data, frameInfo }); - }); - } - }) as SendMessageToChannel; - }, - - injectionToken: sendMessageToChannelInjectionToken, -}); - -export default messageToChannelInjectable; diff --git a/packages/core/src/main/utils/channel/message-to-channel.test.ts b/packages/core/src/main/utils/channel/message-to-channel.test.ts deleted file mode 100644 index 8e544c47dd..0000000000 --- a/packages/core/src/main/utils/channel/message-to-channel.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; -import clusterFramesInjectable from "../../../common/cluster-frames.injectable"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { DiContainer } from "@ogre-tools/injectable"; -import type { ClusterFrameInfo } from "../../../common/cluster-frames.injectable"; - -describe("message-to-channel", () => { - let di: DiContainer; - let sendToWindowMock: jest.Mock; - - beforeEach(() => { - di = getDiForUnitTesting(); - - sendToWindowMock = jest.fn(); - - di.override(getVisibleWindowsInjectable, () => () => [ - { - id: "some-window", - send: sendToWindowMock, - show: () => {}, - reload: () => {}, - isStarting: false, - start: async () => {}, - close: () => {}, - isVisible: true, - }, - - { - id: "some-other-window", - send: sendToWindowMock, - show: () => {}, - reload: () => {}, - isStarting: false, - start: async () => {}, - close: () => {}, - isVisible: true, - }, - ]); - - di.override( - clusterFramesInjectable, - () => - new Map([ - [ - "some-cluster-id", - { frameId: 42, processId: 84 }, - ], - [ - "some-other-cluster-id", - { frameId: 126, processId: 168 }, - ], - ]), - ); - }); - - describe("when sending message", () => { - beforeEach(() => { - const sendMessageToChannel = di.inject( - sendMessageToChannelInjectionToken, - ); - - sendMessageToChannel(someChannel, 42); - }); - - it("sends to each window and cluster frames", () => { - expect(sendToWindowMock.mock.calls).toEqual([ - [{ channel: "some-channel-id", data: 42 }], - - [ - { - channel: "some-channel-id", - data: 42, - frameInfo: { frameId: 42, processId: 84 }, - }, - ], - - [ - { - channel: "some-channel-id", - data: 42, - frameInfo: { frameId: 126, processId: 168 }, - }, - ], - - [{ channel: "some-channel-id", data: 42 }], - - [ - { - channel: "some-channel-id", - data: 42, - frameInfo: { frameId: 42, processId: 84 }, - }, - ], - - [ - { - channel: "some-channel-id", - data: 42, - frameInfo: { frameId: 126, processId: 168 }, - }, - ], - ]); - }); - }); -}); - -const someChannel: MessageChannel = { - id: "some-channel-id", -}; diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts index a2cd605633..16229a0fb7 100644 --- a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts +++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts @@ -3,12 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; -import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable"; const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({ + id: "resolve-system-proxy-channel-responder-listener", channel: resolveSystemProxyChannel, - handler: (di) => di.inject(resolveSystemProxyInjectable), + getHandler: (di) => di.inject(resolveSystemProxyInjectable), }); export default resolveSystemProxyChannelResponderInjectable; diff --git a/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts b/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts index da78d76c36..fafb32e7e9 100644 --- a/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts +++ b/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts @@ -4,11 +4,12 @@ */ import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token"; -import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "@k8slens/messaging"; const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({ + id: "sync-box-initial-value-channel-listener", channel: syncBoxInitialValueChannel, - handler: (di) => { + getHandler: (di) => { const syncBoxes = di.injectMany(syncBoxInjectionToken); return () => syncBoxes.map((box) => ({ diff --git a/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts b/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts index d80cc668ac..af5c3cebc6 100644 --- a/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts +++ b/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts @@ -4,9 +4,9 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable"; -import { beforeFrameStartsFirstInjectionToken } from "../before-frame-starts/tokens"; import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; -import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; const setupAppPathsInjectable = getInjectable({ id: "setup-app-paths", @@ -21,7 +21,7 @@ const setupAppPathsInjectable = getInjectable({ }, }), - injectionToken: beforeFrameStartsFirstInjectionToken, + injectionToken: beforeApplicationIsLoadingInjectionToken, }); export default setupAppPathsInjectable; diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts index 0d9c8bc65a..e60eb3fae1 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { reaction } from "mobx"; import { currentClusterMessageChannel } from "../../../common/cluster/current-cluster-channel"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.injectable"; import { beforeMainFrameStartsFirstInjectionToken } from "../tokens"; diff --git a/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts b/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts index e1322096bf..f80911c7a5 100644 --- a/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts +++ b/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts @@ -4,12 +4,12 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { lensProxyCertificateChannel } from "../../common/certificate/lens-proxy-certificate-channel"; -import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; const requestLensProxyCertificateInjectable = getInjectable({ id: "request-lens-proxy-certificate", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return () => requestFromChannel(lensProxyCertificateChannel); }, diff --git a/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx b/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx index 523a91596e..8f2e5692d1 100644 --- a/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx +++ b/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx @@ -26,6 +26,7 @@ export interface ExtensionInfo { requireConfirmation?: boolean; } +// @ts-ignore interface NpmPackageVersionDescriptor extends PackageJson { dist: { integrity: string; diff --git a/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts b/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts index 08a49bb496..7420fa680a 100644 --- a/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts +++ b/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts @@ -10,7 +10,6 @@ import { onceDefined } from "@k8slens/utilities"; import assert from "assert"; import type { Logger } from "../../../common/logger"; import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable"; -import type { EmitClusterVisibility } from "./emit-cluster-visibility.injectable"; import { getClusterFrameUrl } from "../../../common/utils"; export interface LensView { @@ -21,7 +20,7 @@ export interface LensView { interface Dependencies { readonly logger: Logger; getClusterById: GetClusterById; - emitClusterVisibility: EmitClusterVisibility; + emitClusterVisibility: (clusterId: ClusterId | null) => void; } export class ClusterFrameHandler { diff --git a/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts b/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts index 261582d136..5c941c60e6 100644 --- a/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts +++ b/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts @@ -3,18 +3,16 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannelHandler } from "../../../common/utils/channel/message-channel-listener-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import { clusterVisibilityChannel } from "../../../common/cluster/visibility-channel"; - -export type EmitClusterVisibility = MessageChannelHandler; +import type { ClusterId } from "../../../common/cluster-types"; const emitClusterVisibilityInjectable = getInjectable({ id: "emit-cluster-visibility", - instantiate: (di): EmitClusterVisibility => { + instantiate: (di) => { const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); - return (id) => sendMessageToChannel(clusterVisibilityChannel, id); + return (id: ClusterId | null) => sendMessageToChannel(clusterVisibilityChannel, id); }, }); diff --git a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx index 0d202aa1e5..4ae3441e76 100644 --- a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx +++ b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx @@ -29,7 +29,6 @@ import type { MinimalTrayMenuItem } from "../../../main/tray/electron-tray/elect import electronTrayInjectable from "../../../main/tray/electron-tray/electron-tray.injectable"; import { getDiForUnitTesting as getRendererDi } from "../../getDiForUnitTesting"; import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTesting"; -import { overrideChannels } from "../../../test-utils/channel-fakes/override-channels"; import assert from "assert"; import { openMenu } from "react-select-event"; import userEvent from "@testing-library/user-event"; @@ -40,7 +39,7 @@ import { navigateToRouteInjectionToken } from "../../../common/front-end-routing import type { LensMainExtension } from "../../../extensions/lens-main-extension"; import type { LensExtension } from "../../../extensions/lens-extension"; import extensionInjectable from "../../../extensions/extension-loader/extension/extension.injectable"; -import { renderFor } from "./renderFor"; +import { renderFor } from "@k8slens/test-utils"; import { RootFrame } from "../../frames/root-frame/root-frame"; import { ClusterFrame } from "../../frames/cluster-frame/cluster-frame"; import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; @@ -71,6 +70,8 @@ import { registerFeature } from "@k8slens/feature-core"; import { applicationFeatureForElectronMain, testUtils as applicationForElectronTestUtils } from "@k8slens/application-for-electron-main"; import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge"; type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise; type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise; @@ -179,7 +180,9 @@ export const getApplicationBuilder = () => { testUsingFakeTime(); - const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); + const messageBridgeFake = getMessageBridgeFake(); + + messageBridgeFake.involve(mainDi); const beforeApplicationStartCallbacks: MainDiCallback[] = []; const afterApplicationStartCallbacks: MainDiCallback[] = []; @@ -229,7 +232,8 @@ export const getApplicationBuilder = () => { const windowDi = getRendererDi(); - overrideForWindow(windowDi, windowId); + messageBridgeFake.involve(windowDi); + overrideFsWithFakes(windowDi); runInAction(() => { @@ -284,8 +288,10 @@ export const getApplicationBuilder = () => { ); }, - send: (arg) => { - sendToWindow(windowId, arg); + send: ({ channel: channelId, data }) => { + const sendMessageToChannel = mainDi.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel({ id: channelId }, data); }, reload: () => { diff --git a/packages/core/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts b/packages/core/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts index 841d19e002..dd43cbd301 100644 --- a/packages/core/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts +++ b/packages/core/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; import { rootFrameHasRenderedChannel } from "../../../common/root-frame/root-frame-rendered-channel"; const broadcastThatRootFrameIsRenderedInjectable = getInjectable({ diff --git a/packages/core/src/renderer/getDiForUnitTesting.tsx b/packages/core/src/renderer/getDiForUnitTesting.tsx index fbee046de2..ec389e1b10 100644 --- a/packages/core/src/renderer/getDiForUnitTesting.tsx +++ b/packages/core/src/renderer/getDiForUnitTesting.tsx @@ -5,7 +5,6 @@ import { noop, chunk } from "lodash/fp"; import { createContainer, isInjectable } from "@ogre-tools/injectable"; -import requestFromChannelInjectable from "./utils/channel/request-from-channel.injectable"; import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes"; import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable"; import hostedClusterIdInjectable from "./cluster-frame-context/hosted-cluster-id.injectable"; @@ -18,6 +17,8 @@ import type { GlobalOverride } from "@k8slens/test-utils"; import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; import { registerInjectableReact } from "@ogre-tools/injectable-react"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeature, testUtils as messagingTestUtils } from "@k8slens/messaging"; export const getDiForUnitTesting = () => { const environment = "renderer"; @@ -27,6 +28,10 @@ export const getDiForUnitTesting = () => { registerInjectableReact(di); setLegacyGlobalDiForExtensionApi(di, environment); + runInAction(() => { + registerFeature(di, messagingFeature, messagingTestUtils.messagingFeatureForUnitTesting); + }); + di.preventSideEffects(); runInAction(() => { @@ -63,8 +68,6 @@ export const getDiForUnitTesting = () => { di.override(requestAnimationFrameInjectable, () => (callback) => callback()); di.override(watchHistoryStateInjectable, () => () => () => {}); - di.override(requestFromChannelInjectable, () => () => Promise.resolve(undefined as never)); - getOverrideFsWithFakes()(di); return di; diff --git a/packages/core/src/renderer/kubectl/apply-all.injectable.ts b/packages/core/src/renderer/kubectl/apply-all.injectable.ts index 989017f9d9..ffc5be14ba 100644 --- a/packages/core/src/renderer/kubectl/apply-all.injectable.ts +++ b/packages/core/src/renderer/kubectl/apply-all.injectable.ts @@ -4,12 +4,12 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { kubectlApplyAllChannel, kubectlApplyAllInjectionToken } from "../../common/kube-helpers/channels"; -import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; const kubectlApplyAllInjectable = getInjectable({ id: "kubectl-apply-all", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return (req) => requestFromChannel(kubectlApplyAllChannel, req); }, diff --git a/packages/core/src/renderer/kubectl/delete-all.injectable.ts b/packages/core/src/renderer/kubectl/delete-all.injectable.ts index 586895c75c..4a3ee05f54 100644 --- a/packages/core/src/renderer/kubectl/delete-all.injectable.ts +++ b/packages/core/src/renderer/kubectl/delete-all.injectable.ts @@ -4,12 +4,12 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { kubectlDeleteAllChannel, kubectlDeleteAllInjectionToken } from "../../common/kube-helpers/channels"; -import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; const kubectlDeleteAllInjectable = getInjectable({ id: "kubectl-delete-all", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return (req) => requestFromChannel(kubectlDeleteAllChannel, req); }, diff --git a/packages/core/src/renderer/navigation/navigation-channel-listener.injectable.ts b/packages/core/src/renderer/navigation/navigation-channel-listener.injectable.ts index 1b33b4fe2c..fbb66689e1 100644 --- a/packages/core/src/renderer/navigation/navigation-channel-listener.injectable.ts +++ b/packages/core/src/renderer/navigation/navigation-channel-listener.injectable.ts @@ -2,25 +2,25 @@ * 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 { getInjectable } from "@ogre-tools/injectable"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; import { appNavigationChannel } from "../../common/front-end-routing/app-navigation-channel"; import { clusterFrameNavigationChannel } from "../../common/front-end-routing/cluster-frame-navigation-channel"; import focusWindowInjectable from "./focus-window.injectable"; import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; -import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel, MessageChannelListener } from "@k8slens/messaging"; +import { messageChannelListenerInjectionToken } from "@k8slens/messaging"; const navigationChannelListenerInjectable = getInjectable({ id: "navigation-channel-listener", - instantiate: (di) => { + instantiate: (di): MessageChannelListener> => { const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable); const focusWindow = di.inject(focusWindowInjectable); const navigateToUrl = di.inject(navigateToUrlInjectionToken); return { + id: "navigation-channel-listener", channel: currentlyInClusterFrame ? clusterFrameNavigationChannel : appNavigationChannel, @@ -34,7 +34,8 @@ const navigationChannelListenerInjectable = getInjectable({ }, }; }, - injectionToken: messageChannelListenerInjectionToken as InjectionToken>, void>, + + injectionToken: messageChannelListenerInjectionToken, }); export default navigationChannelListenerInjectable; diff --git a/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts deleted file mode 100644 index c11b34e7e3..0000000000 --- a/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { beforeFrameStartsSecondInjectionToken } from "../../../before-frame-starts/tokens"; -import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; - -const startListeningOfChannelsInjectable = getInjectable({ - id: "start-listening-of-channels-renderer", - - instantiate: (di) => ({ - run: () => { - const listeningOfChannels = di.inject(listeningOnMessageChannelsInjectable); - - listeningOfChannels.start(); - }, - }), - - injectionToken: beforeFrameStartsSecondInjectionToken, -}); - -export default startListeningOfChannelsInjectable; diff --git a/packages/core/src/renderer/utils/channel/message-to-channel.injectable.ts b/packages/core/src/renderer/utils/channel/message-to-channel.injectable.ts deleted file mode 100644 index eab7e4ec7f..0000000000 --- a/packages/core/src/renderer/utils/channel/message-to-channel.injectable.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import sendToMainInjectable from "./send-to-main.injectable"; - -const messageToChannelInjectable = getInjectable({ - id: "message-to-channel", - - instantiate: (di) => { - const sendToMain = di.inject(sendToMainInjectable); - - return ((channel, message) => { - sendToMain(channel.id, message); - }) as SendMessageToChannel; - }, - - injectionToken: sendMessageToChannelInjectionToken, -}); - -export default messageToChannelInjectable; diff --git a/packages/core/src/renderer/utils/channel/request-from-channel.injectable.ts b/packages/core/src/renderer/utils/channel/request-from-channel.injectable.ts deleted file mode 100644 index fd0815b1a3..0000000000 --- a/packages/core/src/renderer/utils/channel/request-from-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; -import type { RequestFromChannel } from "../../../common/utils/channel/request-from-channel-injection-token"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; - -const requestFromChannelInjectable = getInjectable({ - id: "request-from-channel", - - instantiate: (di) => { - const ipcRenderer = di.inject(ipcRendererInjectable); - - return ((channel, request) => ipcRenderer.invoke(channel.id, request)) as RequestFromChannel; - }, - - injectionToken: requestFromChannelInjectionToken, -}); - -export default requestFromChannelInjectable; diff --git a/packages/core/src/renderer/utils/channel/send-to-main.injectable.ts b/packages/core/src/renderer/utils/channel/send-to-main.injectable.ts deleted file mode 100644 index 6eb4540062..0000000000 --- a/packages/core/src/renderer/utils/channel/send-to-main.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; - -const sendToMainInjectable = getInjectable({ - id: "send-to-main", - - instantiate: (di) => { - const ipcRenderer = di.inject(ipcRendererInjectable); - - return (channelId: string, message: any) => { - ipcRenderer.send(channelId, message); - }; - }, -}); - -export default sendToMainInjectable; diff --git a/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts b/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts index 75d61908cd..804fe4ebf1 100644 --- a/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts +++ b/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts @@ -11,7 +11,7 @@ import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectab import loggerInjectable from "../../../common/logger.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import setupAppPathsInjectable from "../../app-paths/setup-app-paths.injectable"; -import { beforeFrameStartsFirstInjectionToken } from "../../before-frame-starts/tokens"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; import { storageHelperLogPrefix } from "../storage-helper"; import lensLocalStorageStateInjectable from "./state.injectable"; @@ -68,7 +68,7 @@ const initializeStateInjectable = getInjectable({ }, runAfter: setupAppPathsInjectable, }), - injectionToken: beforeFrameStartsFirstInjectionToken, + injectionToken: beforeApplicationIsLoadingInjectionToken, }); export default initializeStateInjectable; diff --git a/packages/core/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts b/packages/core/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts index 5468a8c7b7..55cd0d66d5 100644 --- a/packages/core/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts +++ b/packages/core/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts @@ -4,14 +4,14 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { resolveSystemProxyInjectionToken } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; -import requestFromChannelInjectable from "../channel/request-from-channel.injectable"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; const resolveSystemProxyInjectable = getInjectable({ id: "resolve-system-proxy-for-renderer", instantiate: (di) => { - const requestFromChannel = di.inject(requestFromChannelInjectable); + const requestFromChannel = di.inject(requestFromChannelInjectionToken); return async (url) => requestFromChannel(resolveSystemProxyChannel, url); }, diff --git a/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts b/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts index aceb20cea4..b4eb648c87 100644 --- a/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts +++ b/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { beforeFrameStartsSecondInjectionToken } from "../../before-frame-starts/tokens"; import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import createSyncBoxStateInjectable from "../../../common/utils/sync-box/sync-box-state.injectable"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { runInAction } from "mobx"; import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token"; import assert from "assert"; diff --git a/packages/core/src/renderer/vars/build-version/build-version.injectable.ts b/packages/core/src/renderer/vars/build-version/build-version.injectable.ts index a63a4102b0..f9ba5e34b0 100644 --- a/packages/core/src/renderer/vars/build-version/build-version.injectable.ts +++ b/packages/core/src/renderer/vars/build-version/build-version.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { createInitializableState } from "../../../common/initializable-state/create"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; import { buildVersionChannel, buildVersionInjectionToken } from "../../../common/vars/build-semantic-version.injectable"; const buildVersionInjectable = createInitializableState({ diff --git a/packages/core/src/test-utils/channel-fakes/override-channels.ts b/packages/core/src/test-utils/channel-fakes/override-channels.ts deleted file mode 100644 index 798fcd84af..0000000000 --- a/packages/core/src/test-utils/channel-fakes/override-channels.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainer } from "@ogre-tools/injectable"; -import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; -import { overrideMessagingFromMainToWindow } from "./override-messaging-from-main-to-window"; -import { overrideMessagingFromWindowToMain } from "./override-messaging-from-window-to-main"; -import { overrideRequestingFromWindowToMain } from "./override-requesting-from-window-to-main"; - -export interface OverrideChannels { - overrideForWindow: (windowDi: DiContainer, windowId: string) => void; - sendToWindow: (windowId: string, args: SendToViewArgs) => void; -} - -export const overrideChannels = (mainDi: DiContainer): OverrideChannels => { - const { overrideEnlistForWindow, sendToWindow } = overrideMessagingFromMainToWindow(); - const overrideMessagingFromWindowToForWindow = overrideMessagingFromWindowToMain(mainDi); - const overrideRequestingFromWindowToMainForWindow = overrideRequestingFromWindowToMain(mainDi); - - return { - overrideForWindow: (windowDi, windowId) => { - overrideEnlistForWindow(windowDi, windowId); - overrideMessagingFromWindowToForWindow(windowDi); - overrideRequestingFromWindowToMainForWindow(windowDi); - }, - sendToWindow, - }; -}; diff --git a/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts b/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts deleted file mode 100644 index 1b69f13016..0000000000 --- a/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; -import type { DiContainer } from "@ogre-tools/injectable"; -import { getOrInsert, getOrInsertSet } from "@k8slens/utilities"; -import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; -import { deserialize, serialize } from "v8"; - -type ListenerSet = Set>; -type WindowListenerMap = Map; -type ListenerFakeMap = Map; - -export interface OverriddenWindowMessaging { - sendToWindow(windowId: string, args: SendToViewArgs): void; - overrideEnlistForWindow(windowDi: DiContainer, windowId: string): void; -} - -export const overrideMessagingFromMainToWindow = (): OverriddenWindowMessaging => { - const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map(); - - const getWindowListeners = (channelId: string, windowId: string) => { - const channelListeners = getOrInsert( - messageChannelListenerFakesForRenderer, - channelId, - new Map(), - ); - - return getOrInsertSet(channelListeners, windowId); - }; - - return { - overrideEnlistForWindow: (windowDi, windowId) => { - windowDi.override( - enlistMessageChannelListenerInjectableInRenderer, - - () => (listener) => { - const windowListeners = getWindowListeners( - listener.channel.id, - windowId, - ); - - windowListeners.add(listener); - - return () => { - windowListeners.delete(listener); - }; - }, - ); - }, - sendToWindow: (windowId, { channel, data, frameInfo }) => { - try { - data = deserialize(serialize(data)); - } catch (error) { - throw new Error(`Tried to send a message to channel "${channel}" that is not compatible with StructuredClone: ${error}`); - } - - const windowListeners = getWindowListeners(channel, windowId); - - if (frameInfo) { - throw new Error( - `Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channel}" which isn't supported yet.`, - ); - } - - if (windowListeners.size === 0) { - throw new Error( - `Tried to send message to channel "${channel}" but there where no listeners. Current channels with listeners: "${[ - ...messageChannelListenerFakesForRenderer.keys(), - ].join('", "')}"`, - ); - } - - windowListeners.forEach((listener) => listener.handler(data)); - }, - }; -}; diff --git a/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts b/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts deleted file mode 100644 index 8adc35c4d5..0000000000 --- a/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainer } from "@ogre-tools/injectable"; -import { deserialize, serialize } from "v8"; -import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import enlistMessageChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; -import { getOrInsertSet } from "@k8slens/utilities"; -import sendToMainInjectable from "../../renderer/utils/channel/send-to-main.injectable"; - -export const overrideMessagingFromWindowToMain = (mainDi: DiContainer) => { - const messageChannelListenerFakesForMain = new Map< - string, - Set>> - >(); - - mainDi.override( - enlistMessageChannelListenerInjectableInMain, - - () => (listener) => { - const listeners = getOrInsertSet(messageChannelListenerFakesForMain, listener.channel.id); - - listeners.add(listener); - - return () => { - listeners.delete(listener); - }; - }, - ); - - return (windowDi: DiContainer) => { - windowDi.override(sendToMainInjectable, () => (channelId, message) => { - const listeners = messageChannelListenerFakesForMain.get(channelId); - - if (!listeners || listeners.size === 0) { - throw new Error( - `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ - ...messageChannelListenerFakesForMain.keys(), - ].join('", "')}"`, - ); - } - - try { - message = deserialize(serialize(message)); - } catch (error) { - throw new Error(`Tried to send a message to channel "${channelId}" that is not compatible with StructuredClone: ${error}`); - } - - listeners.forEach((listener) => listener.handler(message)); - }); - }; -}; diff --git a/packages/core/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts b/packages/core/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts deleted file mode 100644 index 70526bd84c..0000000000 --- a/packages/core/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainer } from "@ogre-tools/injectable"; -import { deserialize, serialize } from "v8"; -import type { RequestChannel } from "../../common/utils/channel/request-channel-listener-injection-token"; -import type { RequestFromChannel } from "../../common/utils/channel/request-from-channel-injection-token"; -import enlistRequestChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable"; -import type { RequestChannelListener } from "../../main/utils/channel/channel-listeners/listener-tokens"; -import requestFromChannelInjectable from "../../renderer/utils/channel/request-from-channel.injectable"; - -export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { - const requestChannelListenerFakesForMain = new Map< - string, - RequestChannelListener> - >(); - - mainDi.override( - enlistRequestChannelListenerInjectableInMain, - - () => (listener) => { - if (requestChannelListenerFakesForMain.has(listener.channel.id)) { - throw new Error( - `Tried to enlist listener for channel "${listener.channel.id}", but it was already enlisted`, - ); - } - - requestChannelListenerFakesForMain.set(listener.channel.id, listener); - - return () => { - requestChannelListenerFakesForMain.delete(listener.channel.id); - }; - }, - ); - - return (windowDi: DiContainer) => { - windowDi.override( - requestFromChannelInjectable, - - () => (async (channel, request) => { - const requestListener = requestChannelListenerFakesForMain.get(channel.id); - - if (!requestListener) { - throw new Error( - `Tried to get value from channel "${channel.id}", but no listeners were registered`, - ); - } - - try { - request = deserialize(serialize(request)); - } catch (error) { - throw new Error(`Tried to request from channel "${channel.id}" with data that is not compatible with StructuredClone: ${error}`); - } - - return requestListener.handler(request); - }) as RequestFromChannel, - ); - }; -}; diff --git a/packages/infrastructure/eslint-config/bin/lint b/packages/infrastructure/eslint-config/bin/lint index 2abf180561..22d262e0cb 100755 --- a/packages/infrastructure/eslint-config/bin/lint +++ b/packages/infrastructure/eslint-config/bin/lint @@ -8,13 +8,7 @@ const shouldDoTheFix = argv.includes('--fix'); try { execSync(`eslint ${shouldDoTheFix ? "--fix " : " "}--ext ts,tsx --max-warnings=0 .`); } catch (error) { - console.log(error.stdout.toString()); -} + console.error(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()); + process.exit(1); } diff --git a/packages/infrastructure/eslint-config/eslint-config.js b/packages/infrastructure/eslint-config/eslint-config.js index 561541838d..2e59a31da7 100644 --- a/packages/infrastructure/eslint-config/eslint-config.js +++ b/packages/infrastructure/eslint-config/eslint-config.js @@ -15,6 +15,7 @@ module.exports = { "xss", "no-unsanitized" ], + ignorePatterns: ["dist/*"], rules: { "react/react-in-jsx-scope": 0, "security/detect-object-injection": "off", @@ -125,7 +126,7 @@ module.exports = { "@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/no-floating-promises": "off", "@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", diff --git a/packages/infrastructure/jest/jest-28-resolver.js b/packages/infrastructure/jest/jest-28-resolver.js new file mode 100644 index 0000000000..118a17f09d --- /dev/null +++ b/packages/infrastructure/jest/jest-28-resolver.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +module.exports = (path, options) => { + // Call the defaultResolver, so we leverage its cache, error handling, etc. + return options.defaultResolver(path, { + ...options, + // Use packageFilter to process parsed `package.json` before the resolution (see https://www.npmjs.com/package/resolve#resolveid-opts-cb) + packageFilter: pkg => { + // This is a workaround for https://github.com/uuidjs/uuid/pull/616 + // + // jest-environment-jsdom 28+ tries to use browser exports instead of default exports, + // but uuid only offers an ESM browser export and not a CommonJS one. Jest does not yet + // support ESM modules natively, so this causes a Jest error related to trying to parse + // "export" syntax. + // + // This workaround prevents Jest from considering uuid's module-based exports at all; + // it falls back to uuid's CommonJS+node "main" property. + // + // Once we're able to migrate our Jest config to ESM and a browser crypto + // implementation is available for the browser+ESM version of uuid to use (eg, via + // https://github.com/jsdom/jsdom/pull/3352 or a similar polyfill), this can go away. + switch (pkg.name) { + case "uuid": + delete pkg["exports"]; + delete pkg["module"]; + break; + } + + return pkg; + }, + }); +}; diff --git a/packages/infrastructure/jest/monorepo-package-config.js b/packages/infrastructure/jest/monorepo-package-config.js index 6c68fcd8d8..17b24ba342 100644 --- a/packages/infrastructure/jest/monorepo-package-config.js +++ b/packages/infrastructure/jest/monorepo-package-config.js @@ -1,5 +1,9 @@ +const path = require('path'); + module.exports = (rootDir) => { const shared = { + "resolver": path.join(__dirname, "jest-28-resolver.js"), + transform: { "^.+\\.(t|j)sx?$": ["@swc/jest", { cwd: rootDir }], }, @@ -15,6 +19,8 @@ module.exports = (rootDir) => { collectCoverageFrom: [ "/src/**/*.{ts,tsx}", "!/src/**/*.no-coverage.ts", + "!/src/**/test-utils/**/*.{ts,tsx}", + "!/src/**/index.{ts,tsx}", ], moduleNameMapper: { diff --git a/packages/legacy-extension-example/jest.config.js b/packages/legacy-extension-example/jest.config.js index c6074967eb..6d3d6ff231 100644 --- a/packages/legacy-extension-example/jest.config.js +++ b/packages/legacy-extension-example/jest.config.js @@ -1 +1,2 @@ -module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/legacy-extension-example/package.json b/packages/legacy-extension-example/package.json index 857be916fa..e175eeb1f1 100644 --- a/packages/legacy-extension-example/package.json +++ b/packages/legacy-extension-example/package.json @@ -33,7 +33,6 @@ "clean": "rimraf dist/", "build": "webpack --config webpack.ts", "dev": "webpack --mode=development --watch --config webpack.ts", - "test": "jest --coverage --runInBand", "lint": "lens-lint", "lint:fix": "lens-lint --fix" }, diff --git a/packages/open-lens/package.json b/packages/open-lens/package.json index 539f3ecb55..f59563de3f 100644 --- a/packages/open-lens/package.json +++ b/packages/open-lens/package.json @@ -203,7 +203,11 @@ "@k8slens/generate-tray-icons": "^6.5.0-alpha.1", "@k8slens/legacy-extension-example": "^1.0.0-alpha.1", "@k8slens/legacy-extensions": "^1.0.0-alpha.1", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/messaging-for-main": "^1.0.0-alpha.1", + "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", "@ogre-tools/fp": "^15.1.2", diff --git a/packages/open-lens/src/main/index.ts b/packages/open-lens/src/main/index.ts index 5329be4595..84e187ba5c 100644 --- a/packages/open-lens/src/main/index.ts +++ b/packages/open-lens/src/main/index.ts @@ -10,6 +10,7 @@ import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; import { registerFeature } from "@k8slens/feature-core"; import { applicationFeature, startApplicationInjectionToken } from '@k8slens/application' import { applicationFeatureForElectronMain } from '@k8slens/application-for-electron-main' +import { messagingFeatureForMain } from "@k8slens/messaging-for-main"; const environment = "main"; @@ -20,7 +21,7 @@ registerMobX(di); runInAction(() => { registerLensCore(di, environment); - registerFeature(di, applicationFeature, applicationFeatureForElectronMain); + registerFeature(di, applicationFeature, applicationFeatureForElectronMain, messagingFeatureForMain); try { autoRegister({ diff --git a/packages/open-lens/src/renderer/index.ts b/packages/open-lens/src/renderer/index.ts index 9f0770de26..207fc2265c 100644 --- a/packages/open-lens/src/renderer/index.ts +++ b/packages/open-lens/src/renderer/index.ts @@ -14,6 +14,7 @@ import { import { createContainer } from "@ogre-tools/injectable"; import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; import { registerInjectableReact } from "@ogre-tools/injectable-react"; +import { messagingFeatureForRenderer } from "@k8slens/messaging-for-renderer"; const environment = "renderer"; @@ -23,7 +24,7 @@ runInAction(() => { registerMobX(di); registerInjectableReact(di); registerLensCore(di, environment); - registerFeature(di, applicationFeature); + registerFeature(di, applicationFeature, messagingFeatureForRenderer); autoRegister({ di, diff --git a/packages/technical-features/application/agnostic/index.ts b/packages/technical-features/application/agnostic/index.ts index 239e938cd2..2e5595a816 100644 --- a/packages/technical-features/application/agnostic/index.ts +++ b/packages/technical-features/application/agnostic/index.ts @@ -5,5 +5,5 @@ export * from "./src/start-application/time-slots"; export type { StartApplication } from "./src/start-application/start-application.injectable"; export { startApplicationInjectionToken } from "./src/start-application/start-application.injectable"; -export { applicationInformationToken } from "./src/application-information-token"; -export type { ApplicationInformation } from "./src/application-information-token"; +export { applicationInformationToken } from "./src/application-information-token.no-coverage"; +export type { ApplicationInformation } from "./src/application-information-token.no-coverage"; diff --git a/packages/technical-features/application/agnostic/package.json b/packages/technical-features/application/agnostic/package.json index 78069b1ae6..ab869a87c0 100644 --- a/packages/technical-features/application/agnostic/package.json +++ b/packages/technical-features/application/agnostic/package.json @@ -26,7 +26,7 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand", + "test:unit": "jest --coverage --runInBand", "lint": "lens-lint", "lint:fix": "lens-lint --fix" }, diff --git a/packages/technical-features/application/agnostic/src/application-information-token.ts b/packages/technical-features/application/agnostic/src/application-information-token.no-coverage.ts similarity index 100% rename from packages/technical-features/application/agnostic/src/application-information-token.ts rename to packages/technical-features/application/agnostic/src/application-information-token.no-coverage.ts diff --git a/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts index 895462f08e..87f6d1f7db 100644 --- a/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts +++ b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts @@ -4,17 +4,18 @@ import * as timeSlots from "./time-slots"; export type StartApplication = () => Promise; -export const startApplicationInjectionToken = - getInjectionToken({ - id: "start-application-injection-token", - }); +export const startApplicationInjectionToken = getInjectionToken({ + id: "start-application-injection-token", +}); const startApplicationInjectable = getInjectable({ id: "start-application", instantiate: (di): StartApplication => { - const runManyAsync = runManyFor(di) - const beforeApplicationIsLoading = runManyAsync(timeSlots.beforeApplicationIsLoadingInjectionToken); + const runManyAsync = runManyFor(di); + const beforeApplicationIsLoading = runManyAsync( + timeSlots.beforeApplicationIsLoadingInjectionToken, + ); const onLoadOfApplication = runManyAsync(timeSlots.onLoadOfApplicationInjectionToken); const afterApplicationIsLoaded = runManyAsync(timeSlots.afterApplicationIsLoadedInjectionToken); diff --git a/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts index 69219d4a08..672e3a0f01 100644 --- a/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts +++ b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts @@ -4,6 +4,7 @@ import { applicationFeature } from "../feature"; import { startApplicationInjectionToken } from "./start-application.injectable"; import * as timeSlots from "./time-slots"; import asyncFn, { AsyncFnMock } from "@async-fn/jest"; +import { getPromiseStatus } from "@k8slens/test-utils"; describe("starting-of-application", () => { let di: DiContainer; @@ -47,10 +48,12 @@ describe("starting-of-application", () => { }); describe("when application is started", () => { + let actualPromise: Promise; + beforeEach(() => { const startApplication = di.inject(startApplicationInjectionToken); - void startApplication(); + actualPromise = startApplication(); }); it("calls runnables registered in before application is loading", () => { @@ -66,10 +69,28 @@ describe("starting-of-application", () => { expect(onLoadOfApplicationMock).toHaveBeenCalled(); }); - it("when runnables in before application is loading resolve, calls runnables registered in after load of application", async () => { - await onLoadOfApplicationMock.resolve(); + describe("when runnables in before application is loading resolve", () => { + beforeEach(async () => { + await onLoadOfApplicationMock.resolve(); + }); - expect(afterApplicationIsLoadedMock).toHaveBeenCalled(); + it("calls runnables registered in after load of application", async () => { + expect(afterApplicationIsLoadedMock).toHaveBeenCalled(); + }); + + it("does not resolve yet", async () => { + const promiseStatus = await getPromiseStatus(actualPromise); + + expect(promiseStatus.fulfilled).toBe(false); + }); + + it("when runnables in after application is loaded resolve, resolves", async () => { + await afterApplicationIsLoadedMock.resolve(); + + const promiseStatus = await getPromiseStatus(actualPromise); + + expect(promiseStatus.fulfilled).toBe(true); + }); }); }); }); diff --git a/packages/technical-features/application/electron-main/index.ts b/packages/technical-features/application/electron-main/index.ts index 238b564a47..da354760c2 100644 --- a/packages/technical-features/application/electron-main/index.ts +++ b/packages/technical-features/application/electron-main/index.ts @@ -1,4 +1,4 @@ -import { overrideSideEffectsWithFakes } from "./src/override-side-effects-with-fakes"; +import { overrideSideEffectsWithFakes } from "./src/test-utils/override-side-effects-with-fakes"; export * from "./src/start-application/time-slots"; diff --git a/packages/technical-features/application/electron-main/package.json b/packages/technical-features/application/electron-main/package.json index 625c23fe93..f32de6f301 100644 --- a/packages/technical-features/application/electron-main/package.json +++ b/packages/technical-features/application/electron-main/package.json @@ -26,7 +26,7 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand", + "test:unit": "jest --coverage --runInBand", "lint": "lens-lint", "lint:fix": "lens-lint --fix" }, diff --git a/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts b/packages/technical-features/application/electron-main/src/test-utils/override-side-effects-with-fakes.ts similarity index 69% rename from packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts rename to packages/technical-features/application/electron-main/src/test-utils/override-side-effects-with-fakes.ts index a795dbd04b..8873bf7f99 100644 --- a/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts +++ b/packages/technical-features/application/electron-main/src/test-utils/override-side-effects-with-fakes.ts @@ -1,5 +1,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) => { di.override(whenAppIsReadyInjectable, () => () => Promise.resolve()); diff --git a/packages/technical-features/application/legacy-extensions/jest.config.js b/packages/technical-features/application/legacy-extensions/jest.config.js index c6074967eb..6d3d6ff231 100644 --- a/packages/technical-features/application/legacy-extensions/jest.config.js +++ b/packages/technical-features/application/legacy-extensions/jest.config.js @@ -1 +1,2 @@ -module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/application/legacy-extensions/package.json b/packages/technical-features/application/legacy-extensions/package.json index 5b7c436da5..6e92ca7c02 100644 --- a/packages/technical-features/application/legacy-extensions/package.json +++ b/packages/technical-features/application/legacy-extensions/package.json @@ -26,7 +26,6 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand", "lint": "lens-lint", "lint:fix": "lens-lint --fix" }, diff --git a/packages/technical-features/feature-core/package.json b/packages/technical-features/feature-core/package.json index 59f4186c6d..cabb6e17a0 100644 --- a/packages/technical-features/feature-core/package.json +++ b/packages/technical-features/feature-core/package.json @@ -26,7 +26,7 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand", + "test:unit": "jest --coverage --runInBand", "lint": "lens-lint", "lint:fix": "lens-lint --fix" }, diff --git a/packages/technical-features/messaging/agnostic/.eslintrc.json b/packages/technical-features/messaging/agnostic/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/technical-features/messaging/agnostic/.prettierrc b/packages/technical-features/messaging/agnostic/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/messaging/agnostic/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/messaging/agnostic/index.ts b/packages/technical-features/messaging/agnostic/index.ts new file mode 100644 index 0000000000..75b20812f1 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/index.ts @@ -0,0 +1,2 @@ +export * from "./src/features/actual"; +export * as testUtils from "./src/features/unit-testing"; diff --git a/packages/technical-features/messaging/agnostic/jest.config.js b/packages/technical-features/messaging/agnostic/jest.config.js new file mode 100644 index 0000000000..38d54ab7b6 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/technical-features/messaging/agnostic/package.json b/packages/technical-features/messaging/agnostic/package.json new file mode 100644 index 0000000000..085304d4e0 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/package.json @@ -0,0 +1,49 @@ +{ + "name": "@k8slens/messaging", + "private": false, + "version": "1.0.0-alpha.1", + "description": "An abstraction for messaging between Lens environments", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "dist" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint:fix": "lens-lint --fix", + "lint": "lens-lint" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "lodash": "^4.17.21", + "mobx": "^6.7.0" + }, + + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + } +} diff --git a/packages/core/src/common/utils/channel/channel-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/channel.no-coverage.ts similarity index 52% rename from packages/core/src/common/utils/channel/channel-injection-token.ts rename to packages/technical-features/messaging/agnostic/src/features/actual/channel.no-coverage.ts index 6006290f89..62a2ea1490 100644 --- a/packages/core/src/common/utils/channel/channel-injection-token.ts +++ b/packages/technical-features/messaging/agnostic/src/features/actual/channel.no-coverage.ts @@ -1,12 +1,5 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - - export interface Channel { id: string; _messageTemplate?: MessageTemplate; _returnTemplate?: ReturnTemplate; } - diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/feature.ts b/packages/technical-features/messaging/agnostic/src/features/actual/feature.ts new file mode 100644 index 0000000000..5f302e1bcd --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/feature.ts @@ -0,0 +1,18 @@ +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { applicationFeature } from "@k8slens/application"; +import { getFeature } from "@k8slens/feature-core"; + +export const messagingFeature = getFeature({ + id: "messaging", + + dependencies: [applicationFeature], + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, +}); diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/index.ts b/packages/technical-features/messaging/agnostic/src/features/actual/index.ts new file mode 100644 index 0000000000..e8209f26f0 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/index.ts @@ -0,0 +1,53 @@ +/* c8 ignore next */ +export { messagingFeature } from "./feature"; + +export { getRequestChannel } from "./request/get-request-channel"; +export { getMessageChannel } from "./message/get-message-channel"; + +export { requestFromChannelInjectionToken } from "./request/request-from-channel-injection-token"; + +export type { Channel } from "./channel.no-coverage"; + +export { sendMessageToChannelInjectionToken } from "./message/message-to-channel-injection-token"; +export type { SendMessageToChannel } from "./message/message-to-channel-injection-token"; + +export type { + GetMessageChannelListenerInfo, + MessageChannel, + MessageChannelHandler, + MessageChannelListener, +} from "./message/message-channel-listener-injection-token"; + +export { + messageChannelListenerInjectionToken, + getMessageChannelListenerInjectable, +} from "./message/message-channel-listener-injection-token"; + +export type { + RequestChannel, + RequestChannelHandler, +} from "./request/request-channel-listener-injection-token"; + +export type { + RequestFromChannel, + ChannelRequester, +} from "./request/request-from-channel-injection-token"; + +export type { EnlistMessageChannelListener } from "./message/enlist-message-channel-listener-injection-token"; +export { enlistMessageChannelListenerInjectionToken } from "./message/enlist-message-channel-listener-injection-token"; + +export type { EnlistRequestChannelListener } from "./request/enlist-request-channel-listener-injection-token"; +export { enlistRequestChannelListenerInjectionToken } from "./request/enlist-request-channel-listener-injection-token"; + +export type { ListeningOfChannels } from "./listening-of-channels/listening-of-channels.injectable"; +export { listeningOfChannelsInjectionToken } from "./listening-of-channels/listening-of-channels.injectable"; + +export type { + GetRequestChannelListenerInjectableInfo, + RequestChannelListener, +} from "./request/request-channel-listener-injection-token"; + +export { + getRequestChannelListenerInjectable, + requestChannelListenerInjectionToken, +} from "./request/request-channel-listener-injection-token"; diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/listening-of-channels.injectable.ts b/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/listening-of-channels.injectable.ts new file mode 100644 index 0000000000..c28d6cbc5a --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/listening-of-channels.injectable.ts @@ -0,0 +1,106 @@ +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../message/enlist-message-channel-listener-injection-token"; + +import { getStartableStoppable, StartableStoppable } from "@k8slens/startable-stoppable"; + +import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; +import { IComputedValue, reaction } from "mobx"; + +import { messageChannelListenerInjectionToken } from "../message/message-channel-listener-injection-token"; +import { requestChannelListenerInjectionToken } from "../request/request-channel-listener-injection-token"; +import { enlistRequestChannelListenerInjectionToken } from "../request/enlist-request-channel-listener-injection-token"; +import type { Channel } from "../channel.no-coverage"; + +export type ListeningOfChannels = StartableStoppable; +export const listeningOfChannelsInjectionToken = getInjectionToken({ + id: "listening-of-channels-injection-token", +}); + +const listening = }>( + channelListeners: IComputedValue, + enlistChannelListener: (listener: T) => () => void, + getId: (listener: T) => string, +) => { + const listenerDisposers = new Map void>(); + + const reactionDisposer = reaction( + () => channelListeners.get(), + (newValues, oldValues = []) => { + const addedListeners = newValues.filter( + (newValue) => !oldValues.some((oldValue) => oldValue.id === newValue.id), + ); + + const removedListeners = oldValues.filter( + (oldValue) => !newValues.some((newValue) => newValue.id === oldValue.id), + ); + + addedListeners.forEach((listener) => { + const id = getId(listener); + + if (listenerDisposers.has(id)) { + throw new Error( + `Tried to add listener for channel "${listener.channel.id}" but listener already exists.`, + ); + } + + const disposer = enlistChannelListener(listener); + + listenerDisposers.set(id, disposer); + }); + + removedListeners.forEach((listener) => { + const dispose = listenerDisposers.get(getId(listener)); + + dispose?.(); + + listenerDisposers.delete(getId(listener)); + }); + }, + + { fireImmediately: true }, + ); + + return () => { + reactionDisposer(); + listenerDisposers.forEach((dispose) => dispose()); + }; +}; + +const listeningOfChannelsInjectable = getInjectable({ + id: "listening-of-channels", + + instantiate: (di) => { + const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); + + const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectionToken); + + const computedInjectMany = di.inject(computedInjectManyInjectable); + + const messageChannelListeners = computedInjectMany(messageChannelListenerInjectionToken); + + const requestChannelListeners = computedInjectMany(requestChannelListenerInjectionToken); + + return getStartableStoppable("listening-of-channels", () => { + const stopListeningOfMessageChannels = listening( + messageChannelListeners, + enlistMessageChannelListener, + (x) => x.id, + ); + + const stopListeningOfRequestChannels = listening( + requestChannelListeners, + enlistRequestChannelListener, + (x) => x.channel.id, + ); + + return () => { + stopListeningOfMessageChannels(); + stopListeningOfRequestChannels(); + }; + }); + }, + + injectionToken: listeningOfChannelsInjectionToken, +}); + +export default listeningOfChannelsInjectable; diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/start-listening-of-channels.injectable.ts b/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/start-listening-of-channels.injectable.ts new file mode 100644 index 0000000000..eb265b1ca2 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/listening-of-channels/start-listening-of-channels.injectable.ts @@ -0,0 +1,21 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; +import { listeningOfChannelsInjectionToken } from "./listening-of-channels.injectable"; + +const startListeningOfChannelsInjectable = getInjectable({ + id: "start-listening-of-channels", + + instantiate: (di) => { + const listeningOfChannels = di.inject(listeningOfChannelsInjectionToken); + + return { + run: async () => { + await listeningOfChannels.start(); + }, + }; + }, + + injectionToken: onLoadOfApplicationInjectionToken, +}); + +export default startListeningOfChannelsInjectable; diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/message/enlist-message-channel-listener-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/message/enlist-message-channel-listener-injection-token.ts new file mode 100644 index 0000000000..9ec6f8b93a --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/message/enlist-message-channel-listener-injection-token.ts @@ -0,0 +1,15 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; + +import type { + MessageChannel, + MessageChannelListener, +} from "./message-channel-listener-injection-token"; + +export type EnlistMessageChannelListener = ( + listener: MessageChannelListener>, +) => () => void; + +export const enlistMessageChannelListenerInjectionToken = + getInjectionToken({ + id: "listening-to-a-message-channel", + }); diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/message/get-message-channel.ts b/packages/technical-features/messaging/agnostic/src/features/actual/message/get-message-channel.ts new file mode 100644 index 0000000000..076a7af464 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/message/get-message-channel.ts @@ -0,0 +1,5 @@ +import type { MessageChannel } from "./message-channel-listener-injection-token"; + +export const getMessageChannel = (id: string): MessageChannel => ({ + id, +}); diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/message/message-channel-listener-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/message/message-channel-listener-injection-token.ts new file mode 100644 index 0000000000..386c9f9e5e --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/message/message-channel-listener-injection-token.ts @@ -0,0 +1,51 @@ +import type { DiContainerForInjection } from "@ogre-tools/injectable"; +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; + +export interface MessageChannel { + id: string; + _messageSignature?: Message; +} + +export type ExtraData = { processId: number; frameId: number }; + +export type MessageChannelHandler = Channel extends MessageChannel + ? (message: Message, data: ExtraData) => void + : never; + +export interface MessageChannelListener { + id: string; + channel: Channel; + handler: MessageChannelHandler; +} + +export const messageChannelListenerInjectionToken = getInjectionToken< + MessageChannelListener> +>({ + id: "message-channel-listener", +}); + +export interface GetMessageChannelListenerInfo, Message> { + id: string; + channel: Channel; + getHandler: (di: DiContainerForInjection) => MessageChannelHandler; + causesSideEffects?: boolean; +} + +export const getMessageChannelListenerInjectable = < + Channel extends MessageChannel, + Message, +>( + info: GetMessageChannelListenerInfo, +) => + getInjectable({ + id: `${info.channel.id}-message-listener-${info.id}`, + + instantiate: (di): MessageChannelListener => ({ + id: `${info.channel.id}-message-listener-${info.id}`, + channel: info.channel, + handler: info.getHandler(di), + }), + + injectionToken: messageChannelListenerInjectionToken, + causesSideEffects: info.causesSideEffects, + }); diff --git a/packages/core/src/common/utils/channel/message-to-channel-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/message/message-to-channel-injection-token.ts similarity index 55% rename from packages/core/src/common/utils/channel/message-to-channel-injection-token.ts rename to packages/technical-features/messaging/agnostic/src/features/actual/message/message-to-channel-injection-token.ts index 3ffd75f4f7..9cb5df4986 100644 --- a/packages/core/src/common/utils/channel/message-to-channel-injection-token.ts +++ b/packages/technical-features/messaging/agnostic/src/features/actual/message/message-to-channel-injection-token.ts @@ -1,7 +1,3 @@ -/** - * 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 { MessageChannel } from "./message-channel-listener-injection-token"; @@ -10,12 +6,6 @@ export interface SendMessageToChannel { (channel: MessageChannel, message: Message): void; } -export type MessageChannelSender = Channel extends MessageChannel - ? () => void - : Channel extends MessageChannel - ? (message: Message) => void - : never; - export const sendMessageToChannelInjectionToken = getInjectionToken({ id: "send-message-to-message-channel", }); diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/request/enlist-request-channel-listener-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/request/enlist-request-channel-listener-injection-token.ts new file mode 100644 index 0000000000..cdb3ac97d5 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/request/enlist-request-channel-listener-injection-token.ts @@ -0,0 +1,15 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; + +import type { + RequestChannel, + RequestChannelListener, +} from "./request-channel-listener-injection-token"; + +export type EnlistRequestChannelListener = ( + listener: RequestChannelListener>, +) => () => void; + +export const enlistRequestChannelListenerInjectionToken = + getInjectionToken({ + id: "listening-to-a-request-channel", + }); diff --git a/packages/technical-features/messaging/agnostic/src/features/actual/request/get-request-channel.ts b/packages/technical-features/messaging/agnostic/src/features/actual/request/get-request-channel.ts new file mode 100644 index 0000000000..c0ee40bcf4 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/actual/request/get-request-channel.ts @@ -0,0 +1,7 @@ +import type { RequestChannel } from "./request-channel-listener-injection-token"; + +export const getRequestChannel = ( + id: string, +): RequestChannel => ({ + id, +}); diff --git a/packages/core/src/main/utils/channel/channel-listeners/listener-tokens.ts b/packages/technical-features/messaging/agnostic/src/features/actual/request/request-channel-listener-injection-token.ts similarity index 56% rename from packages/core/src/main/utils/channel/channel-listeners/listener-tokens.ts rename to packages/technical-features/messaging/agnostic/src/features/actual/request/request-channel-listener-injection-token.ts index a3cd5af4f4..2ec76ff546 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/listener-tokens.ts +++ b/packages/technical-features/messaging/agnostic/src/features/actual/request/request-channel-listener-injection-token.ts @@ -1,23 +1,28 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - import type { DiContainerForInjection } from "@ogre-tools/injectable"; import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -export type RequestChannelHandler = Channel extends RequestChannel +export interface RequestChannel { + id: string; + _requestSignature?: Request; + _responseSignature?: Response; +} + +export type RequestChannelHandler = Channel extends RequestChannel< + infer Request, + infer Response +> ? (req: Request) => Promise | Response : never; export interface RequestChannelListener { + id: string; channel: Channel; handler: RequestChannelHandler; } - -export const requestChannelListenerInjectionToken = getInjectionToken>>( { +export const requestChannelListenerInjectionToken = getInjectionToken< + RequestChannelListener> +>({ id: "request-channel-listener", }); @@ -26,21 +31,26 @@ export interface GetRequestChannelListenerInjectableInfo< Request, Response, > { + id: string; channel: Channel; - handler: (di: DiContainerForInjection) => RequestChannelHandler; + getHandler: (di: DiContainerForInjection) => RequestChannelHandler; } -export function getRequestChannelListenerInjectable< +export const getRequestChannelListenerInjectable = < Channel extends RequestChannel, Request, Response, ->(info: GetRequestChannelListenerInjectableInfo) { - return getInjectable({ - id: `${info.channel.id}-listener`, +>( + info: GetRequestChannelListenerInjectableInfo, +) => + getInjectable({ + id: `${info.channel.id}-request-listener-${info.id}`, + instantiate: (di) => ({ + id: `${info.channel.id}-request-listener-${info.id}`, channel: info.channel, - handler: info.handler(di), + handler: info.getHandler(di), }), + injectionToken: requestChannelListenerInjectionToken, }); -} diff --git a/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts b/packages/technical-features/messaging/agnostic/src/features/actual/request/request-from-channel-injection-token.ts similarity index 53% rename from packages/core/src/common/utils/channel/request-from-channel-injection-token.ts rename to packages/technical-features/messaging/agnostic/src/features/actual/request/request-from-channel-injection-token.ts index 939cc23f9d..194091b588 100644 --- a/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts +++ b/packages/technical-features/messaging/agnostic/src/features/actual/request/request-from-channel-injection-token.ts @@ -1,16 +1,18 @@ -/** - * 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 { RequestChannel } from "./request-channel-listener-injection-token"; export interface RequestFromChannel { - (channel: RequestChannel, request: Request): Promise>; - (channel: RequestChannel): Promise>; + ( + channel: RequestChannel, + request: Request, + ): Promise; + (channel: RequestChannel): Promise; } -export type ChannelRequester = Channel extends RequestChannel +export type ChannelRequester = Channel extends RequestChannel< + infer Request, + infer Response +> ? (req: Request) => Promise> : never; diff --git a/packages/technical-features/messaging/agnostic/src/features/unit-testing/feature.ts b/packages/technical-features/messaging/agnostic/src/features/unit-testing/feature.ts new file mode 100644 index 0000000000..ca6ddd2b2e --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/unit-testing/feature.ts @@ -0,0 +1,18 @@ +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { getFeature } from "@k8slens/feature-core"; +import { messagingFeature } from "../actual/feature"; + +export const messagingFeatureForUnitTesting = getFeature({ + id: "messaging-for-unit-testing", + + dependencies: [messagingFeature], + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, +}); diff --git a/packages/technical-features/messaging/agnostic/src/features/unit-testing/index.ts b/packages/technical-features/messaging/agnostic/src/features/unit-testing/index.ts new file mode 100644 index 0000000000..e0ee8eb25b --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/unit-testing/index.ts @@ -0,0 +1 @@ +export { messagingFeatureForUnitTesting } from "./feature"; diff --git a/packages/technical-features/messaging/agnostic/src/features/unit-testing/test-doubles.injectable.ts b/packages/technical-features/messaging/agnostic/src/features/unit-testing/test-doubles.injectable.ts new file mode 100644 index 0000000000..621e088a4b --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/features/unit-testing/test-doubles.injectable.ts @@ -0,0 +1,31 @@ +import { sendMessageToChannelInjectionToken } from "../actual/message/message-to-channel-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "../actual/message/enlist-message-channel-listener-injection-token"; +import { requestFromChannelInjectionToken } from "../actual/request/request-from-channel-injection-token"; +import { enlistRequestChannelListenerInjectionToken } from "../actual/request/enlist-request-channel-listener-injection-token"; +import { getInjectable } from "@ogre-tools/injectable"; + +export const sendMessageToChannelStubInjectable = getInjectable({ + id: "send-message-to-channel-stub", + /* c8 ignore next */ + instantiate: () => () => {}, + injectionToken: sendMessageToChannelInjectionToken, +}); + +export const enlistMessageChannelListenerStubInjectable = getInjectable({ + id: "enlist-message-channel-listener-stub", + instantiate: () => () => () => {}, + injectionToken: enlistMessageChannelListenerInjectionToken, +}); + +export const requestFromChannelStubInjectable = getInjectable({ + id: "request-from-channel-stub", + /* c8 ignore next */ + instantiate: () => () => Promise.resolve(), + injectionToken: requestFromChannelInjectionToken, +}); + +export const enlistRequestChannelListenerStubInjectable = getInjectable({ + id: "enlist-request-channel-listener-stub", + instantiate: () => () => () => {}, + injectionToken: enlistRequestChannelListenerInjectionToken, +}); diff --git a/packages/technical-features/messaging/agnostic/src/listening-of-messages.test.ts b/packages/technical-features/messaging/agnostic/src/listening-of-messages.test.ts new file mode 100644 index 0000000000..8dc25fa41e --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/listening-of-messages.test.ts @@ -0,0 +1,169 @@ +import { createContainer, DiContainer, Injectable } from "@ogre-tools/injectable"; + +import { registerFeature } from "@k8slens/feature-core"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { runInAction } from "mobx"; + +import { + EnlistMessageChannelListener, + enlistMessageChannelListenerInjectionToken, +} from "./features/actual/message/enlist-message-channel-listener-injection-token"; + +import { messagingFeatureForUnitTesting } from "./features/unit-testing"; + +import { + getMessageChannelListenerInjectable, + MessageChannel, + MessageChannelListener, +} from "./features/actual/message/message-channel-listener-injection-token"; + +import { listeningOfChannelsInjectionToken } from "./features/actual/listening-of-channels/listening-of-channels.injectable"; + +import { getMessageChannel } from "./features/actual/message/get-message-channel"; +import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; + +describe("listening-of-messages", () => { + let di: DiContainer; + let enlistMessageChannelListenerMock: jest.MockedFunction; + let disposeSomeListenerMock: jest.Mock; + let disposeSomeUnrelatedListenerMock: jest.Mock; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerMobX(di); + + disposeSomeListenerMock = jest.fn(); + disposeSomeUnrelatedListenerMock = jest.fn(); + + enlistMessageChannelListenerMock = jest.fn((listener) => + listener.id === "some-channel-id-message-listener-some-listener" + ? disposeSomeListenerMock + : disposeSomeUnrelatedListenerMock, + ); + + runInAction(() => { + registerFeature(di, applicationFeature, messagingFeatureForUnitTesting); + }); + + di.override(enlistMessageChannelListenerInjectionToken, () => enlistMessageChannelListenerMock); + }); + + describe("given listening of channels has not started yet", () => { + describe("when a new listener gets registered", () => { + let someChannel: MessageChannel; + let someMessageHandler: () => void; + + let someListenerInjectable: Injectable< + MessageChannelListener>, + MessageChannelListener> + >; + + beforeEach(() => { + someChannel = getMessageChannel("some-channel-id"); + + someMessageHandler = () => {}; + + someListenerInjectable = getMessageChannelListenerInjectable({ + id: "some-listener", + channel: someChannel, + getHandler: () => someMessageHandler, + }); + + runInAction(() => { + di.register(someListenerInjectable); + }); + }); + + describe("when application is started", () => { + beforeEach(async () => { + const startApplication = di.inject(startApplicationInjectionToken); + + await startApplication(); + }); + + it("enlists a listener for the channel", () => { + expect(enlistMessageChannelListenerMock).toHaveBeenCalledWith({ + id: "some-channel-id-message-listener-some-listener", + channel: someChannel, + handler: someMessageHandler, + }); + }); + + describe("when another listener gets registered", () => { + let someOtherListenerInjectable: Injectable< + MessageChannelListener>, + MessageChannelListener>, + void + >; + + beforeEach(() => { + const handler = () => someMessageHandler; + + someOtherListenerInjectable = getMessageChannelListenerInjectable({ + id: "some-other-listener", + channel: someChannel, + getHandler: handler, + }); + + enlistMessageChannelListenerMock.mockClear(); + + runInAction(() => { + di.register(someOtherListenerInjectable); + }); + }); + + it("only enlists it as well", () => { + expect(enlistMessageChannelListenerMock.mock.calls).toEqual([ + [ + { + id: "some-channel-id-message-listener-some-other-listener", + channel: someChannel, + handler: someMessageHandler, + }, + ], + ]); + }); + + describe("when one of the listeners gets deregistered", () => { + beforeEach(() => { + runInAction(() => { + di.deregister(someListenerInjectable); + }); + }); + + it("the listener gets disposed", () => { + expect(disposeSomeListenerMock).toHaveBeenCalled(); + }); + + it("the unrelated listener does not get disposed", () => { + expect(disposeSomeUnrelatedListenerMock).not.toHaveBeenCalled(); + }); + + describe("when listening of channels stops", () => { + beforeEach(() => { + const listening = di.inject(listeningOfChannelsInjectionToken); + + listening.stop(); + }); + + it("remaining listeners get disposed", () => { + expect(disposeSomeUnrelatedListenerMock).toHaveBeenCalled(); + }); + + it("when yet another listener gets registered, does not enlist it", () => { + enlistMessageChannelListenerMock.mockClear(); + + runInAction(() => { + di.register(someListenerInjectable); + }); + + expect(enlistMessageChannelListenerMock).not.toHaveBeenCalled(); + }); + }); + }); + }); + }); + }); + }); +}); diff --git a/packages/technical-features/messaging/agnostic/src/listening-of-requests.test.ts b/packages/technical-features/messaging/agnostic/src/listening-of-requests.test.ts new file mode 100644 index 0000000000..e708c983c8 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/src/listening-of-requests.test.ts @@ -0,0 +1,204 @@ +import { createContainer, DiContainer, Injectable } from "@ogre-tools/injectable"; + +import { registerFeature } from "@k8slens/feature-core"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { _resetGlobalState, configure, runInAction } from "mobx"; + +import { + EnlistRequestChannelListener, + enlistRequestChannelListenerInjectionToken, +} from "./features/actual/request/enlist-request-channel-listener-injection-token"; + +import { messagingFeatureForUnitTesting } from "./features/unit-testing"; + +import { + getRequestChannelListenerInjectable, + RequestChannel, + RequestChannelListener, +} from "./features/actual/request/request-channel-listener-injection-token"; + +import { listeningOfChannelsInjectionToken } from "./features/actual/listening-of-channels/listening-of-channels.injectable"; +import { noop } from "lodash/fp"; +import { getRequestChannel } from "./features/actual/request/get-request-channel"; +import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; + +describe("listening-of-requests", () => { + let di: DiContainer; + let enlistRequestChannelListenerMock: jest.MockedFunction; + let disposeSomeListenerMock: jest.Mock; + let disposeSomeUnrelatedListenerMock: jest.Mock; + + beforeEach(() => { + configure({ + disableErrorBoundaries: false, + }); + + _resetGlobalState(); + + di = createContainer("irrelevant"); + + registerMobX(di); + + disposeSomeListenerMock = jest.fn(); + disposeSomeUnrelatedListenerMock = jest.fn(); + + enlistRequestChannelListenerMock = jest.fn((listener) => + listener.id === "some-channel-id-request-listener-some-listener" + ? disposeSomeListenerMock + : disposeSomeUnrelatedListenerMock, + ); + + runInAction(() => { + registerFeature(di, applicationFeature, messagingFeatureForUnitTesting); + }); + + di.override(enlistRequestChannelListenerInjectionToken, () => enlistRequestChannelListenerMock); + }); + + describe("given listening of channels has not started yet", () => { + describe("when a new listener gets registered", () => { + let someChannel: RequestChannel; + let someOtherChannel: RequestChannel; + let someRequestHandler: () => string; + + let someListenerInjectable: Injectable< + RequestChannelListener>, + RequestChannelListener> + >; + + beforeEach(() => { + someChannel = getRequestChannel("some-channel-id"); + someOtherChannel = getRequestChannel("some-other-channel-id"); + + someRequestHandler = () => "some-response"; + + someListenerInjectable = getRequestChannelListenerInjectable({ + id: "some-listener", + channel: someChannel, + getHandler: () => someRequestHandler, + }); + + runInAction(() => { + di.register(someListenerInjectable); + }); + }); + + describe("when application is started", () => { + beforeEach(async () => { + const startApplication = di.inject(startApplicationInjectionToken); + + await startApplication(); + }); + + it("enlists a listener for the channel", () => { + expect(enlistRequestChannelListenerMock).toHaveBeenCalledWith({ + id: "some-channel-id-request-listener-some-listener", + channel: someChannel, + handler: someRequestHandler, + }); + }); + + it("when another listener for same channel gets registered, throws", () => { + const originalConsoleWarn = console.warn; + + console.warn = noop; + + configure({ + disableErrorBoundaries: true, + }); + + console.warn = originalConsoleWarn; + + const handler = () => someRequestHandler; + + const someConflictingListenerInjectable = getRequestChannelListenerInjectable({ + id: "some-other-listener", + channel: someChannel, + getHandler: handler, + }); + + expect(() => { + runInAction(() => { + di.register(someConflictingListenerInjectable); + }); + }).toThrow( + 'Tried to add listener for channel "some-channel-id" but listener already exists.', + ); + }); + + describe("when another listener gets registered", () => { + let someOtherListenerInjectable: Injectable< + RequestChannelListener>, + RequestChannelListener> + >; + + beforeEach(() => { + const handler = () => someRequestHandler; + + someOtherListenerInjectable = getRequestChannelListenerInjectable({ + id: "some-other-listener", + channel: someOtherChannel, + getHandler: handler, + }); + + enlistRequestChannelListenerMock.mockClear(); + + runInAction(() => { + di.register(someOtherListenerInjectable); + }); + }); + + it("only enlists it as well", () => { + expect(enlistRequestChannelListenerMock.mock.calls).toEqual([ + [ + { + id: "some-other-channel-id-request-listener-some-other-listener", + channel: someOtherChannel, + handler: someRequestHandler, + }, + ], + ]); + }); + + describe("when one of the listeners gets deregistered", () => { + beforeEach(() => { + runInAction(() => { + di.deregister(someListenerInjectable); + }); + }); + + it("the listener gets disposed", () => { + expect(disposeSomeListenerMock).toHaveBeenCalled(); + }); + + it("the unrelated listener does not get disposed", () => { + expect(disposeSomeUnrelatedListenerMock).not.toHaveBeenCalled(); + }); + + describe("when listening of channels stops", () => { + beforeEach(() => { + const listening = di.inject(listeningOfChannelsInjectionToken); + + listening.stop(); + }); + + it("remaining listeners get disposed", () => { + expect(disposeSomeUnrelatedListenerMock).toHaveBeenCalled(); + }); + + it("when yet another listener gets registered, does not enlist it", () => { + enlistRequestChannelListenerMock.mockClear(); + + runInAction(() => { + di.register(someListenerInjectable); + }); + + expect(enlistRequestChannelListenerMock).not.toHaveBeenCalled(); + }); + }); + }); + }); + }); + }); + }); +}); diff --git a/packages/technical-features/messaging/agnostic/tsconfig.json b/packages/technical-features/messaging/agnostic/tsconfig.json new file mode 100644 index 0000000000..ec29a8f75f --- /dev/null +++ b/packages/technical-features/messaging/agnostic/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/packages/technical-features/messaging/agnostic/webpack.config.js b/packages/technical-features/messaging/agnostic/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/messaging/agnostic/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/technical-features/messaging/computed-channel/.eslintrc.json b/packages/technical-features/messaging/computed-channel/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/technical-features/messaging/computed-channel/.prettierrc b/packages/technical-features/messaging/computed-channel/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/messaging/computed-channel/index.ts b/packages/technical-features/messaging/computed-channel/index.ts new file mode 100644 index 0000000000..4516e0b9a6 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/index.ts @@ -0,0 +1,12 @@ +export { + computedChannelInjectionToken, + computedChannelObserverInjectionToken, +} from "./src/computed-channel/computed-channel.injectable"; + +export type { + ChannelObserver, + ComputedChannelFactory, + JsonifiableObject, + JsonifiableArray, + Jsonifiable, +} from "./src/computed-channel/computed-channel.injectable"; diff --git a/packages/technical-features/messaging/computed-channel/jest.config.js b/packages/technical-features/messaging/computed-channel/jest.config.js new file mode 100644 index 0000000000..38d54ab7b6 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/technical-features/messaging/computed-channel/package.json b/packages/technical-features/messaging/computed-channel/package.json new file mode 100644 index 0000000000..81c4f80013 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/package.json @@ -0,0 +1,51 @@ +{ + "name": "@k8slens/computed-channel", + "private": false, + "version": "1.0.0-alpha.1", + "description": "MobX-like computed between channels", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "dist" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "lodash": "^4.17.21", + "mobx": "^6.8.0" + }, + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1", + "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1", + "type-fest": "^2.14.0" + } +} diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts new file mode 100644 index 0000000000..b0fdb3c59f --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts @@ -0,0 +1,64 @@ +import { reaction } from "mobx"; + +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import type { JsonPrimitive } from "type-fest"; +import { computedChannelObserverInjectionToken } from "./computed-channel.injectable"; +import { getMessageChannel } from "@k8slens/messaging"; + +export type JsonifiableObject = { [Key in string]?: Jsonifiable } | { toJSON: () => Jsonifiable }; +export type JsonifiableArray = readonly Jsonifiable[]; +export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray; + +export type ComputedChannelAdminMessage = { + channelId: string; + status: "became-observed" | "became-unobserved"; +}; + +export const computedChannelAdministrationChannel = getMessageChannel( + "computed-channel-administration-channel", +); + +export const computedChannelAdministrationListenerInjectable = getMessageChannelListenerInjectable({ + id: "computed-channel-administration", + channel: computedChannelAdministrationChannel, + + getHandler: (di) => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + const disposersByChannelId = new Map void>(); + + return (message) => { + if (message.status === "became-observed") { + const result = di + .injectMany(computedChannelObserverInjectionToken) + .find((channelObserver) => channelObserver.channel.id === message.channelId); + + if (result === undefined) { + return; + } + + const disposer = reaction( + () => result.observer.get(), + (observed) => + sendMessageToChannel( + { + id: message.channelId, + }, + + observed, + ), + { + fireImmediately: true, + }, + ); + + disposersByChannelId.set(message.channelId, disposer); + } else { + const disposer = disposersByChannelId.get(message.channelId); + + disposer?.(); + } + }; + }, +}); diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts new file mode 100644 index 0000000000..03f5a16aab --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts @@ -0,0 +1,110 @@ +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; + +import { + _getGlobalState, + computed, + IComputedValue, + observable, + onBecomeObserved, + onBecomeUnobserved, + runInAction, +} from "mobx"; + +import type { MessageChannel } from "@k8slens/messaging"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import type { JsonPrimitive } from "type-fest"; +import { computedChannelAdministrationChannel } from "./computed-channel-administration-channel.injectable"; + +export type JsonifiableObject = { [Key in string]?: Jsonifiable } | { toJSON: () => Jsonifiable }; +export type JsonifiableArray = readonly Jsonifiable[]; +export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray; + +export type ComputedChannelFactory = ( + channel: MessageChannel, + pendingValue: T, +) => IComputedValue; + +export const computedChannelInjectionToken = getInjectionToken({ + id: "computed-channel-injection-token", +}); + +export type ChannelObserver = { + channel: MessageChannel; + observer: IComputedValue; +}; + +export const computedChannelObserverInjectionToken = getInjectionToken< + ChannelObserver +>({ + id: "computed-channel-observer", +}); + +const computedChannelInjectable = getInjectable({ + id: "computed-channel", + + instantiate: (di) => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + return ((channel, pendingValue) => { + const observableValue = observable.box(pendingValue); + + const computedValue = computed(() => { + const { trackingDerivation } = _getGlobalState(); + + const contextIsReactive = !!trackingDerivation; + + if (!contextIsReactive) { + throw new Error( + `Tried to access value of computed channel "${channel.id}" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.`, + ); + } + + return observableValue.get(); + }); + + const valueReceiverInjectable = getMessageChannelListenerInjectable({ + id: `computed-channel-value-receiver-for-${channel.id}`, + channel, + + getHandler: () => (message) => { + runInAction(() => { + observableValue.set(message); + }); + }, + }); + + runInAction(() => { + di.register(valueReceiverInjectable); + }); + + onBecomeObserved(computedValue, () => { + runInAction(() => { + observableValue.set(pendingValue); + }); + + sendMessageToChannel(computedChannelAdministrationChannel, { + channelId: channel.id, + status: "became-observed", + }); + }); + + onBecomeUnobserved(computedValue, () => { + runInAction(() => { + observableValue.set(pendingValue); + }); + + sendMessageToChannel(computedChannelAdministrationChannel, { + channelId: channel.id, + status: "became-unobserved", + }); + }); + + return computedValue; + }) as ComputedChannelFactory; + }, + + injectionToken: computedChannelInjectionToken, +}); + +export default computedChannelInjectable; diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx new file mode 100644 index 0000000000..4736fe22d4 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx @@ -0,0 +1,571 @@ +import React from "react"; +import { act } from "@testing-library/react"; +import { createContainer, DiContainer, getInjectable } from "@ogre-tools/injectable"; +import { getMessageBridgeFake, MessageBridgeFake } from "@k8slens/messaging-fake-bridge"; +import { startApplicationInjectionToken } from "@k8slens/application"; +import { + computed, + IComputedValue, + IObservableValue, + observable, + reaction, + runInAction, +} from "mobx"; +import type { MessageChannel } from "@k8slens/messaging"; +import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { registerFeature } from "@k8slens/feature-core"; +import { testUtils } from "@k8slens/messaging"; +import { + computedChannelInjectionToken, + computedChannelObserverInjectionToken, +} from "./computed-channel.injectable"; +import { runWithThrownMobxReactions, renderFor } from "@k8slens/test-utils"; +import { observer } from "mobx-react"; +import { + computedChannelAdministrationChannel, + ComputedChannelAdminMessage, +} from "./computed-channel-administration-channel.injectable"; +import { computedChannelFeature } from "../feature"; + +const testChannel: MessageChannel = { id: "some-channel-id" }; +const testChannel2: MessageChannel = { id: "some-other-channel-id" }; + +const TestComponent = observer(({ someComputed }: { someComputed: IComputedValue }) => ( +
{someComputed.get()}
+)); + +[{ scenarioIsAsync: true }, { scenarioIsAsync: false }].forEach(({ scenarioIsAsync }) => + describe(`computed-channel, given running message bridge fake as ${ + scenarioIsAsync ? "async" : "sync" + }`, () => { + describe("given multiple dis and a message channel and a channel observer and application has started", () => { + let di1: DiContainer; + let di2: DiContainer; + let latestAdminMessage: ComputedChannelAdminMessage | undefined; + let latestValueMessage: string | undefined; + let messageBridgeFake: MessageBridgeFake; + + beforeEach(async () => { + latestAdminMessage = undefined; + latestValueMessage = undefined; + + di1 = createContainer("some-container-1"); + di2 = createContainer("some-container-2"); + registerMobX(di1); + registerMobX(di2); + + const administrationChannelTestListenerInjectable = getMessageChannelListenerInjectable({ + id: "administration-channel-test-listener", + channel: computedChannelAdministrationChannel, + + getHandler: () => (adminMessage) => { + latestAdminMessage = adminMessage; + }, + }); + + const channelValueTestListenerInjectable = getMessageChannelListenerInjectable({ + id: "test-channel-value-listener", + channel: testChannel, + + getHandler: () => (message) => { + latestValueMessage = message; + }, + }); + + runInAction(() => { + const messagingFeature = testUtils.messagingFeatureForUnitTesting; + + registerFeature(di1, messagingFeature, computedChannelFeature); + registerFeature(di2, messagingFeature, computedChannelFeature); + + di1.register(channelValueTestListenerInjectable); + di2.register(administrationChannelTestListenerInjectable); + }); + + messageBridgeFake = getMessageBridgeFake(); + messageBridgeFake.setAsync(scenarioIsAsync); + messageBridgeFake.involve(di1, di2); + + await Promise.all([ + di1.inject(startApplicationInjectionToken)(), + di2.inject(startApplicationInjectionToken)(), + ]); + }); + + describe("given a channel observer and matching computed channel for the channel in di-2", () => { + let someObservable: IObservableValue; + let computedTestChannel: IComputedValue; + + beforeEach(() => { + someObservable = observable.box("some-initial-value"); + + const channelObserverInjectable = getInjectable({ + id: "some-channel-observer", + + instantiate: () => ({ + channel: testChannel, + observer: computed(() => someObservable.get()), + }), + + injectionToken: computedChannelObserverInjectionToken, + }); + + runInAction(() => { + di2.register(channelObserverInjectable); + }); + + const computedChannel = di1.inject(computedChannelInjectionToken); + + computedTestChannel = computedChannel(testChannel, "some-pending-value"); + }); + + it("there is no admin message yet", () => { + expect(latestAdminMessage).toBeUndefined(); + }); + + describe("when observing the computed value in a component in di-1", () => { + let rendered: any; + + beforeEach(() => { + const render = renderFor(di2); + + rendered = render(); + }); + + const scenarioName = scenarioIsAsync ? "when all messages are propagated" : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + messageBridgeFake.messagePropagationRecursive(act).then(done); + } else { + done(); + } + }); + + it("renders", () => { + expect(rendered.container).toHaveTextContent("some-initial-value"); + }); + }); + }); + + describe("when observing the computed channel in di-1", () => { + let observedValue: string | undefined; + let stopObserving: () => void; + + beforeEach(() => { + observedValue = undefined; + + stopObserving = reaction( + () => computedTestChannel.get(), + (value) => { + observedValue = value; + }, + + { + fireImmediately: true, + }, + ); + }); + + scenarioIsAsync && + it("computed test channel value is observed as the pending value", () => { + expect(observedValue).toBe("some-pending-value"); + }); + + const scenarioName = scenarioIsAsync + ? "when admin messages are propagated" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("administration-message to start observing gets listened", () => { + expect(latestAdminMessage).toEqual({ + channelId: "some-channel-id", + status: "became-observed", + }); + }); + + const scenarioName = scenarioIsAsync + ? "when returning value-messages propagate" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("the computed channel value in di-1 matches the value in di-2", () => { + expect(observedValue).toBe("some-initial-value"); + }); + + it("the value gets listened in di-1", () => { + expect(latestValueMessage).toBe("some-initial-value"); + }); + + describe("when the observed value changes", () => { + beforeEach(async () => { + latestValueMessage = undefined; + + runInAction(() => { + someObservable.set("some-new-value"); + }); + }); + + const scenarioName = scenarioIsAsync + ? "when value-messages propagate" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("the computed channel value in di-1 changes", () => { + expect(observedValue).toBe("some-new-value"); + }); + + it("the new value gets listened in di-1", () => { + expect(latestValueMessage).toBe("some-new-value"); + }); + }); + }); + + describe("when stopping observation for the channel in di-1", () => { + beforeEach(async () => { + latestValueMessage = undefined; + + stopObserving(); + }); + + const scenarioName = scenarioIsAsync + ? "when admin-messages propagate" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("messages administration channel to stop observing", () => { + expect(latestAdminMessage).toEqual({ + channelId: "some-channel-id", + status: "became-unobserved", + }); + }); + + it("no value gets listened in di-1 anymore", () => { + expect(latestValueMessage).toBeUndefined(); + }); + + describe("when the observed value changes", () => { + beforeEach(async () => { + latestValueMessage = undefined; + + runInAction(() => { + someObservable.set("some-new-value-2"); + }); + }); + + it("when accessing the computed value outside of reactive context, throws", () => { + expect(() => { + computedTestChannel.get(); + }).toThrow( + 'Tried to access value of computed channel "some-channel-id" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.', + ); + }); + + it("no value gets listened in di-1 anymore", () => { + expect(latestValueMessage).toBeUndefined(); + }); + + describe("when observing the computed channel again", () => { + beforeEach(() => { + observedValue = undefined; + + reaction( + () => computedTestChannel.get(), + (value) => { + observedValue = value; + }, + + { + fireImmediately: true, + }, + ); + }); + + scenarioIsAsync && + it("computed test channel value is observed as the pending value again", () => { + expect(observedValue).toBe("some-pending-value"); + }); + + const scenarioName = scenarioIsAsync + ? "when admin messages propagate" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + latestAdminMessage = undefined; + + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("administration-message to start observing gets listened again", () => { + expect(latestAdminMessage).toEqual({ + channelId: "some-channel-id", + status: "became-observed", + }); + }); + + scenarioIsAsync && + it("computed test channel value is still observed as the pending value", () => { + expect(observedValue).toBe("some-pending-value"); + }); + + const scenarioTitle = scenarioIsAsync + ? "when value-messages propagate back" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioTitle, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + latestValueMessage = undefined; + + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("the computed channel value changes", () => { + expect(observedValue).toBe("some-new-value-2"); + }); + + it("the current value gets listened", () => { + expect(latestValueMessage).toBe("some-new-value-2"); + }); + }); + }); + }); + }); + }); + + it("when accessing the computed value outside of reactive context, throws", () => { + expect(() => { + computedTestChannel.get(); + }).toThrow( + 'Tried to access value of computed channel "some-channel-id" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.', + ); + }); + }); + + it("given observation of unrelated computed channel is stopped, observation of other computed channel still works", async () => { + const someOtherObservable = observable.box(""); + + const channelObserver2Injectable = getInjectable({ + id: "some-channel-observer-2", + + instantiate: () => ({ + channel: testChannel2, + observer: computed(() => someOtherObservable.get()), + }), + + injectionToken: computedChannelObserverInjectionToken, + }); + + runInAction(() => { + di2.register(channelObserver2Injectable); + }); + + const computedChannel = di1.inject(computedChannelInjectionToken); + + computedTestChannel = computedChannel(testChannel2, "some-pending-value"); + + reaction( + () => computedTestChannel.get(), + (value) => { + observedValue = value; + }, + + { + fireImmediately: true, + }, + ); + + scenarioIsAsync && (await messageBridgeFake.messagePropagation()); + + stopObserving(); + + scenarioIsAsync && (await messageBridgeFake.messagePropagation()); + + runInAction(() => { + someOtherObservable.set("some-value"); + }); + + scenarioIsAsync && (await messageBridgeFake.messagePropagation()); + + expect(observedValue).toBe("some-value"); + }); + + describe("when observing the computed channel again", () => { + beforeEach(() => { + latestAdminMessage = undefined; + + reaction( + () => computedTestChannel.get(), + (value) => { + observedValue = value; + }, + + { + fireImmediately: true, + }, + ); + }); + + it("doesn't send second administration message", () => { + expect(latestAdminMessage).toBeUndefined(); + }); + + it("when one of the observations stops, doesn't send administration message to stop observing", async () => { + latestAdminMessage = undefined; + + stopObserving(); + + expect(latestAdminMessage).toBeUndefined(); + }); + }); + + describe("when accessing the computed value outside of reactive context", () => { + let nonReactiveValue: string; + + beforeEach(() => { + latestValueMessage = undefined; + latestAdminMessage = undefined; + + nonReactiveValue = computedTestChannel.get(); + }); + + it("the non reactive value is what ever happens to be the current value from di-2", () => { + expect(nonReactiveValue).toBe("some-initial-value"); + }); + + const scenarioName = scenarioIsAsync + ? "when messages would be propagated" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + void messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("does not send new value message", () => { + expect(latestValueMessage).toBeUndefined(); + }); + + it("does not send new admin message", () => { + expect(latestAdminMessage).toBeUndefined(); + }); + }); + }); + }); + }); + }); + + it("when accessing the computed value outside of reactive context, throws", () => { + expect(() => { + computedTestChannel.get(); + }).toThrow( + 'Tried to access value of computed channel "some-channel-id" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.', + ); + }); + + it("given duplicate channel observer for the channel is registered, when the computed channel is observer, throws", () => { + const duplicateChannelObserverInjectable = getInjectable({ + id: "some-duplicate-channel-observer", + + instantiate: () => ({ + channel: testChannel, + observer: computed(() => "irrelevant"), + }), + + injectionToken: computedChannelObserverInjectionToken, + }); + + expect(() => { + runWithThrownMobxReactions(() => { + runInAction(() => { + di2.register(duplicateChannelObserverInjectable); + }); + }); + }).toThrow('Tried to register duplicate channel observer for channels "some-channel-id"'); + }); + }); + + describe("given no channel observer but still a computed channel", () => { + let computedTestChannel: IComputedValue; + + beforeEach(() => { + const computedChannel = di1.inject(computedChannelInjectionToken); + + computedTestChannel = computedChannel(testChannel, "some-pending-value"); + }); + + it("when the computed channel is observed, observes as undefined", () => { + let observedValue = "some-value-to-never-be-seen-in-unit-test"; + + reaction( + () => computedTestChannel.get(), + + (value) => { + observedValue = value; + }, + + { + fireImmediately: true, + }, + ); + + expect(observedValue).toBe("some-pending-value"); + }); + }); + }); + }), +); diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/duplicate-channel-observer-guard.injectable.ts b/packages/technical-features/messaging/computed-channel/src/computed-channel/duplicate-channel-observer-guard.injectable.ts new file mode 100644 index 0000000000..42f313ec36 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/duplicate-channel-observer-guard.injectable.ts @@ -0,0 +1,42 @@ +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; +import { pipeline } from "@ogre-tools/fp"; +import { getInjectable } from "@ogre-tools/injectable"; +import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; +import { filter, groupBy, nth, map, toPairs } from "lodash/fp"; +import { reaction } from "mobx"; +import { computedChannelObserverInjectionToken } from "./computed-channel.injectable"; + +export const duplicateChannelObserverGuardInjectable = getInjectable({ + id: "duplicate-channel-observer-guard", + + instantiate: (di) => { + const computedInjectMany = di.inject(computedInjectManyInjectable); + + return { + run: () => { + reaction( + () => computedInjectMany(computedChannelObserverInjectionToken).get(), + (observers) => { + const duplicateObserverChannelIds = pipeline( + observers, + groupBy((observer) => observer.channel.id), + toPairs, + filter(([, channelObservers]) => channelObservers.length > 1), + map(nth(0)), + ); + + if (duplicateObserverChannelIds.length) { + throw new Error( + `Tried to register duplicate channel observer for channels "${duplicateObserverChannelIds.join( + '", "', + )}"`, + ); + } + }, + ); + }, + }; + }, + + injectionToken: onLoadOfApplicationInjectionToken, +}); diff --git a/packages/technical-features/messaging/computed-channel/src/feature.ts b/packages/technical-features/messaging/computed-channel/src/feature.ts new file mode 100644 index 0000000000..179700edcc --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/src/feature.ts @@ -0,0 +1,18 @@ +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { getFeature } from "@k8slens/feature-core"; +import { messagingFeature } from "@k8slens/messaging"; + +export const computedChannelFeature = getFeature({ + id: "computed-channel", + + dependencies: [messagingFeature], + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, +}); diff --git a/packages/technical-features/messaging/computed-channel/tsconfig.json b/packages/technical-features/messaging/computed-channel/tsconfig.json new file mode 100644 index 0000000000..ec29a8f75f --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/packages/technical-features/messaging/computed-channel/webpack.config.js b/packages/technical-features/messaging/computed-channel/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/messaging/computed-channel/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/technical-features/messaging/electron/main/.eslintrc.json b/packages/technical-features/messaging/electron/main/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/technical-features/messaging/electron/main/.prettierrc b/packages/technical-features/messaging/electron/main/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/messaging/electron/main/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/messaging/electron/main/index.ts b/packages/technical-features/messaging/electron/main/index.ts new file mode 100644 index 0000000000..1ff9afff0d --- /dev/null +++ b/packages/technical-features/messaging/electron/main/index.ts @@ -0,0 +1 @@ +export { messagingFeatureForMain } from "./src/feature"; diff --git a/packages/technical-features/messaging/electron/main/jest.config.js b/packages/technical-features/messaging/electron/main/jest.config.js new file mode 100644 index 0000000000..c6074967eb --- /dev/null +++ b/packages/technical-features/messaging/electron/main/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/messaging/electron/main/package.json b/packages/technical-features/messaging/electron/main/package.json new file mode 100644 index 0000000000..63d66ea6d0 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/package.json @@ -0,0 +1,47 @@ +{ + "name": "@k8slens/messaging-for-main", + "private": false, + "version": "1.0.0-alpha.1", + "description": "Implementations for 'messaging' in Electron main", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "dist" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "electron": "^19.1.8", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + } +} diff --git a/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.injectable.ts b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.injectable.ts new file mode 100644 index 0000000000..5a33ed39d9 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.injectable.ts @@ -0,0 +1,28 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import type { IpcMainEvent } from "electron"; +import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; + +const enlistMessageChannelListenerInjectable = getInjectable({ + id: "enlist-message-channel-listener", + + instantiate: (di) => { + const ipcMain = di.inject(ipcMainInjectable); + + return ({ channel, handler }) => { + const nativeOnCallback = (nativeEvent: IpcMainEvent, message: unknown) => { + handler(message, { frameId: nativeEvent.frameId, processId: nativeEvent.processId }); + }; + + ipcMain.on(channel.id, nativeOnCallback); + + return () => { + ipcMain.off(channel.id, nativeOnCallback); + }; + }; + }, + + injectionToken: enlistMessageChannelListenerInjectionToken, +}); + +export default enlistMessageChannelListenerInjectable; diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.test.ts similarity index 59% rename from packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts rename to packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.test.ts index 2bb5f7b10f..c4385246cd 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-message-channel-listener.test.ts @@ -1,12 +1,12 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; -import type { EnlistMessageChannelListener } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; import type { IpcMain, IpcMainEvent } from "electron"; +import { + EnlistMessageChannelListener, + enlistMessageChannelListenerInjectionToken, +} from "@k8slens/messaging"; +import { createContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForMain } from "../feature"; describe("enlist message channel listener in main", () => { let enlistMessageChannelListener: EnlistMessageChannelListener; @@ -15,7 +15,9 @@ describe("enlist message channel listener in main", () => { let offMock: jest.Mock; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForMain); onMock = jest.fn(); offMock = jest.fn(); @@ -27,9 +29,7 @@ describe("enlist message channel listener in main", () => { di.override(ipcMainInjectable, () => ipcMainStub); - enlistMessageChannelListener = di.inject( - enlistMessageChannelListenerInjectionToken, - ); + enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); }); describe("when called", () => { @@ -40,6 +40,7 @@ describe("enlist message channel listener in main", () => { handlerMock = jest.fn(); disposer = enlistMessageChannelListener({ + id: "some-listener", channel: { id: "some-channel-id" }, handler: handlerMock, }); @@ -50,10 +51,7 @@ describe("enlist message channel listener in main", () => { }); it("registers the listener", () => { - expect(onMock).toHaveBeenCalledWith( - "some-channel-id", - expect.any(Function), - ); + expect(onMock).toHaveBeenCalledWith("some-channel-id", expect.any(Function)); }); it("does not de-register the listener yet", () => { @@ -62,11 +60,11 @@ describe("enlist message channel listener in main", () => { describe("when message arrives", () => { beforeEach(() => { - onMock.mock.calls[0][1]({} as IpcMainEvent, "some-message"); + onMock.mock.calls[0][1]({ frameId: 42, processId: 84 } as IpcMainEvent, "some-message"); }); it("calls the handler with the message", () => { - expect(handlerMock).toHaveBeenCalledWith("some-message"); + expect(handlerMock).toHaveBeenCalledWith("some-message", { frameId: 42, processId: 84 }); }); it("when disposing the listener, de-registers the listener", () => { @@ -77,21 +75,21 @@ describe("enlist message channel listener in main", () => { }); it("given number as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcMainEvent, 42); + onMock.mock.calls[0][1]({ frameId: 42, processId: 84 } as IpcMainEvent, 42); - expect(handlerMock).toHaveBeenCalledWith(42); + expect(handlerMock).toHaveBeenCalledWith(42, { frameId: 42, processId: 84 }); }); it("given boolean as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcMainEvent, true); + onMock.mock.calls[0][1]({ frameId: 42, processId: 84 } as IpcMainEvent, true); - expect(handlerMock).toHaveBeenCalledWith(true); + expect(handlerMock).toHaveBeenCalledWith(true, { frameId: 42, processId: 84 }); }); it("given object as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcMainEvent, { some: "object" }); + onMock.mock.calls[0][1]({ frameId: 42, processId: 84 } as IpcMainEvent, { some: "object" }); - expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); + expect(handlerMock).toHaveBeenCalledWith({ some: "object" }, { frameId: 42, processId: 84 }); }); }); }); diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.injectable.ts similarity index 53% rename from packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts rename to packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.injectable.ts index 08a600297c..f46976a3f1 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.injectable.ts @@ -1,21 +1,18 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainInvokeEvent } from "electron"; -import type { Disposer } from "@k8slens/utilities"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import type { RequestChannelListener } from "./listener-tokens"; -import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token"; +import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; +import type { RequestChannel, RequestChannelListener } from "@k8slens/messaging"; +import { enlistRequestChannelListenerInjectionToken } from "@k8slens/messaging"; -export type EnlistRequestChannelListener = >(listener: RequestChannelListener) => Disposer; +export type EnlistRequestChannelListener = >( + listener: RequestChannelListener, +) => () => void; const enlistRequestChannelListenerInjectable = getInjectable({ id: "enlist-request-channel-listener-for-main", instantiate: (di): EnlistRequestChannelListener => { - const ipcMain = di.inject(ipcMainInjectionToken); + const ipcMain = di.inject(ipcMainInjectable); return ({ channel, handler }) => { const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request); @@ -27,6 +24,8 @@ const enlistRequestChannelListenerInjectable = getInjectable({ }; }; }, + + injectionToken: enlistRequestChannelListenerInjectionToken, }); export default enlistRequestChannelListenerInjectable; diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.test.ts similarity index 86% rename from packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts rename to packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.test.ts index 188a11866b..68672f4e95 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts +++ b/packages/technical-features/messaging/electron/main/src/channel-listeners/enlist-request-channel-listener.test.ts @@ -1,17 +1,14 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import type { IpcMain, IpcMainInvokeEvent } from "electron"; -import { getPromiseStatus } from "@k8slens/test-utils"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; import type { EnlistRequestChannelListener } from "./enlist-request-channel-listener.injectable"; import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; -import type { RequestChannelHandler } from "./listener-tokens"; +import type { RequestChannel, RequestChannelHandler } from "@k8slens/messaging"; +import { getPromiseStatus } from "@k8slens/test-utils"; +import { createContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForMain } from "../feature"; type TestRequestChannel = RequestChannel; @@ -26,7 +23,9 @@ describe("enlist request channel listener in main", () => { let offMock: jest.Mock; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForMain); handleMock = jest.fn(); offMock = jest.fn(); @@ -49,6 +48,7 @@ describe("enlist request channel listener in main", () => { handlerMock = asyncFn(); disposer = enlistRequestChannelListener({ + id: "some-listener", channel: testRequestChannel, handler: handlerMock, }); @@ -59,10 +59,7 @@ describe("enlist request channel listener in main", () => { }); it("registers the listener", () => { - expect(handleMock).toHaveBeenCalledWith( - "some-channel-id", - expect.any(Function), - ); + expect(handleMock).toHaveBeenCalledWith("some-channel-id", expect.any(Function)); }); it("does not de-register the listener yet", () => { @@ -73,10 +70,7 @@ describe("enlist request channel listener in main", () => { let actualPromise: Promise; beforeEach(() => { - actualPromise = handleMock.mock.calls[0][1]( - {} as IpcMainInvokeEvent, - "some-request", - ); + actualPromise = handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, "some-request"); }); it("calls the handler with the request", () => { diff --git a/packages/technical-features/messaging/electron/main/src/feature.ts b/packages/technical-features/messaging/electron/main/src/feature.ts new file mode 100644 index 0000000000..250f5ed104 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/feature.ts @@ -0,0 +1,18 @@ +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { getFeature } from "@k8slens/feature-core"; +import { messagingFeature } from "@k8slens/messaging"; + +export const messagingFeatureForMain = getFeature({ + id: "messaging-for-main", + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, + + dependencies: [messagingFeature], +}); diff --git a/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.injectable.ts b/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.injectable.ts new file mode 100644 index 0000000000..fc55a6b414 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.injectable.ts @@ -0,0 +1,10 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { ipcMain } from "electron"; + +const ipcMainInjectable = getInjectable({ + id: "ipc-main", + instantiate: () => ipcMain, + causesSideEffects: true, +}); + +export default ipcMainInjectable; diff --git a/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.test.ts b/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.test.ts new file mode 100644 index 0000000000..9a3e92c02e --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/ipc-main/ipc-main.test.ts @@ -0,0 +1,21 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import ipcMainInjectable from "./ipc-main.injectable"; +import { ipcMain } from "electron"; +import { messagingFeatureForMain } from "../feature"; + +describe("ipc-main", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForMain); + }); + + it("is the actual IPC-main of Electron", () => { + const actual = di.inject(ipcMainInjectable); + + expect(actual).toBe(ipcMain); + }); +}); diff --git a/packages/technical-features/messaging/electron/main/src/request-from-channel/request-from-channel.injectable.ts b/packages/technical-features/messaging/electron/main/src/request-from-channel/request-from-channel.injectable.ts new file mode 100644 index 0000000000..220daf9fc7 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/request-from-channel/request-from-channel.injectable.ts @@ -0,0 +1,23 @@ +/* c8 ignore start */ +import { getInjectable } from "@ogre-tools/injectable"; +import { + RequestChannel, + RequestFromChannel, + requestFromChannelInjectionToken, +} from "@k8slens/messaging"; + +const requestFromChannelInjectable = getInjectable({ + id: "request-from-channel", + + instantiate: () => + ((channel: RequestChannel) => { + throw new Error( + `Tried to request from channel "${channel.id}" but requesting in "main" it's not supported yet`, + ); + }) as unknown as RequestFromChannel, + + injectionToken: requestFromChannelInjectionToken, +}); + +export default requestFromChannelInjectable; +/* c8 ignore stop */ diff --git a/packages/technical-features/messaging/electron/main/src/send-message-to-channel/allow-communication-listener.injectable.ts b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/allow-communication-listener.injectable.ts new file mode 100644 index 0000000000..af74d7a810 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/allow-communication-listener.injectable.ts @@ -0,0 +1,21 @@ +import { getMessageChannel, getMessageChannelListenerInjectable } from "@k8slens/messaging"; +import frameIdsInjectable from "./frameIds.injectable"; + +const frameCommunicationAdminChannel = getMessageChannel( + "frame-communication-admin-channel", +); + +const allowCommunicationListenerInjectable = getMessageChannelListenerInjectable({ + id: "allow-communication", + channel: frameCommunicationAdminChannel, + + getHandler: (di) => { + const frameIds = di.inject(frameIdsInjectable); + + return (_, { frameId, processId }) => { + frameIds.add({ frameId, processId }); + }; + }, +}); + +export default allowCommunicationListenerInjectable; diff --git a/packages/technical-features/messaging/electron/main/src/send-message-to-channel/frameIds.injectable.ts b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/frameIds.injectable.ts new file mode 100644 index 0000000000..6dff45afc2 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/frameIds.injectable.ts @@ -0,0 +1,8 @@ +import { getInjectable } from "@ogre-tools/injectable"; + +const frameIdsInjectable = getInjectable({ + id: "frame-ids", + instantiate: () => new Set<{ frameId: number; processId: number }>(), +}); + +export default frameIdsInjectable; diff --git a/packages/technical-features/messaging/electron/main/src/send-message-to-channel/get-web-contents.injectable.ts b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/get-web-contents.injectable.ts new file mode 100644 index 0000000000..701c976621 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/get-web-contents.injectable.ts @@ -0,0 +1,12 @@ +/* c8 ignore start */ +import { getInjectable } from "@ogre-tools/injectable"; +import { webContents } from "electron"; + +const getWebContentsInjectable = getInjectable({ + id: "web-contents", + instantiate: () => () => webContents.getAllWebContents(), + causesSideEffects: true, +}); + +export default getWebContentsInjectable; +/* c8 ignore stop */ diff --git a/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts new file mode 100644 index 0000000000..5c5a486658 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts @@ -0,0 +1,121 @@ +import { registerFeature } from "@k8slens/feature-core"; +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { messagingFeatureForMain } from "../feature"; +import { getMessageChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import getWebContentsInjectable from "./get-web-contents.injectable"; +import type { WebContents } from "electron"; +import allowCommunicationListenerInjectable from "./allow-communication-listener.injectable"; + +const someChannel = getMessageChannel("some-channel"); + +describe("send-message-to-channel", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForMain); + }); + + it("given no web contents, when sending a message, does not do anything", () => { + di.override(getWebContentsInjectable, () => () => []); + + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + expect(() => sendMessageToChannel(someChannel, "some-message")).not.toThrow(); + }); + + describe("given web content that is alive", () => { + let sendToFrameMock: jest.Mock; + let sendMessageMock: jest.Mock; + + beforeEach(() => { + sendToFrameMock = jest.fn(); + sendMessageMock = jest.fn(); + + di.override(getWebContentsInjectable, () => () => [ + { + send: (...args: any[]) => sendMessageMock("first", ...args), + sendToFrame: (...args: any[]) => sendToFrameMock("first", ...args), + isDestroyed: () => false, + isCrashed: () => false, + } as unknown as WebContents, + { + send: (...args: any[]) => sendMessageMock("second", ...args), + sendToFrame: (...args: any[]) => sendToFrameMock("second", ...args), + isDestroyed: () => false, + isCrashed: () => false, + } as unknown as WebContents, + ]); + }); + + it("when sending message, sends the message to webcontents", () => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel(someChannel, "some-message"); + + expect(sendMessageMock.mock.calls).toEqual([ + ["first", "some-channel", "some-message"], + ["second", "some-channel", "some-message"], + ]); + }); + + describe("when multiple renderers inform that they are ready to listen messages", () => { + beforeEach(() => { + const allowCommunicationListener = di.inject(allowCommunicationListenerInjectable); + + allowCommunicationListener.handler(undefined, { frameId: 42, processId: 126 }); + allowCommunicationListener.handler(undefined, { frameId: 84, processId: 168 }); + }); + + describe("when sending a message", () => { + beforeEach(() => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel(someChannel, "some-message"); + }); + + it("sends the message to webcontents", () => { + expect(sendMessageMock.mock.calls).toEqual([ + ["first", "some-channel", "some-message"], + ["second", "some-channel", "some-message"], + ]); + }); + + it("sends the message to individual frames in webcontents", () => { + expect(sendToFrameMock.mock.calls).toEqual([ + ["first", [42, 126], "some-channel", "some-message"], + ["first", [84, 168], "some-channel", "some-message"], + + ["second", [42, 126], "some-channel", "some-message"], + ["second", [84, 168], "some-channel", "some-message"], + ]); + }); + }); + }); + }); + + it("given non alive web contents, when sending a message, does not send messages", () => { + const sendToWebContentsMock = jest.fn(); + + di.override(getWebContentsInjectable, () => () => [ + { + send: sendToWebContentsMock, + isDestroyed: () => true, + isCrashed: () => false, + } as unknown as WebContents, + + { + send: sendToWebContentsMock, + isDestroyed: () => false, + isCrashed: () => true, + } as unknown as WebContents, + ]); + + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel(someChannel, "irrelevant"); + + expect(sendToWebContentsMock).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.ts b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.ts new file mode 100644 index 0000000000..e68d8e1577 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/src/send-message-to-channel/send-message-to-channel.injectable.ts @@ -0,0 +1,48 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { pipeline } from "@ogre-tools/fp"; +import { SendMessageToChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import getWebContentsInjectable from "./get-web-contents.injectable"; +import { flatMap, reject } from "lodash/fp"; +import type { WebContents } from "electron"; +import frameIdsInjectable from "./frameIds.injectable"; + +const isDestroyed = (webContent: WebContents) => webContent.isDestroyed(); +const isCrashed = (webContent: WebContents) => webContent.isCrashed(); + +const forEach = + (predicate: (item: T) => void) => + (items: T[]) => + items.forEach(predicate); + +const sendMessageToChannelInjectable = getInjectable({ + id: "send-message-to-channel", + + instantiate: (di) => { + const getWebContents = di.inject(getWebContentsInjectable); + const frameIds = di.inject(frameIdsInjectable); + + return ((channel, message) => { + pipeline( + getWebContents(), + reject(isDestroyed), + reject(isCrashed), + + flatMap((webContent) => [ + (channelId: string, ...args: any[]) => webContent.send(channelId, ...args), + + ...[...frameIds].map(({ frameId, processId }) => (channelId: string, ...args: any[]) => { + webContent.sendToFrame([frameId, processId], channelId, ...args); + }), + ]), + + forEach((send) => { + send(channel.id, message); + }), + ); + }) as SendMessageToChannel; + }, + + injectionToken: sendMessageToChannelInjectionToken, +}); + +export default sendMessageToChannelInjectable; diff --git a/packages/technical-features/messaging/electron/main/tsconfig.json b/packages/technical-features/messaging/electron/main/tsconfig.json new file mode 100644 index 0000000000..1819203dc1 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] +} diff --git a/packages/technical-features/messaging/electron/main/webpack.config.js b/packages/technical-features/messaging/electron/main/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/messaging/electron/main/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/technical-features/messaging/electron/renderer/.eslintrc.json b/packages/technical-features/messaging/electron/renderer/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/technical-features/messaging/electron/renderer/.prettierrc b/packages/technical-features/messaging/electron/renderer/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/messaging/electron/renderer/index.ts b/packages/technical-features/messaging/electron/renderer/index.ts new file mode 100644 index 0000000000..337d473d1f --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/index.ts @@ -0,0 +1 @@ +export { messagingFeatureForRenderer } from "./src/feature"; diff --git a/packages/technical-features/messaging/electron/renderer/jest.config.js b/packages/technical-features/messaging/electron/renderer/jest.config.js new file mode 100644 index 0000000000..c6074967eb --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/messaging/electron/renderer/package.json b/packages/technical-features/messaging/electron/renderer/package.json new file mode 100644 index 0000000000..dcb9a7a185 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/package.json @@ -0,0 +1,48 @@ +{ + "name": "@k8slens/messaging-for-renderer", + "private": false, + "version": "1.0.0-alpha.1", + "description": "Implementations for 'messaging' in Electron renderer", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "dist" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/messaging": "^1.0.0-alpha.1", + "@k8slens/run-many": "^1.0.0-alpha.1", + "@k8slens/startable-stoppable": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "electron": "^19.1.8", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + } +} diff --git a/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.injectable.ts new file mode 100644 index 0000000000..59abe7f931 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.injectable.ts @@ -0,0 +1,25 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; +import { getMessageChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; + +export const frameCommunicationAdminChannel = getMessageChannel( + "frame-communication-admin-channel", +); + +const allowCommunicationToIframeInjectable = getInjectable({ + id: "allow-communication-to-iframe-injectable", + + instantiate: (di) => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + return { + run: () => { + sendMessageToChannel(frameCommunicationAdminChannel); + }, + }; + }, + + injectionToken: onLoadOfApplicationInjectionToken, +}); + +export default allowCommunicationToIframeInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.test.ts b/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.test.ts new file mode 100644 index 0000000000..990c6601d9 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/allow-communication-to-iframe.test.ts @@ -0,0 +1,35 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { startApplicationInjectionToken } from "@k8slens/application"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForRenderer } from "./feature"; +import { runInAction } from "mobx"; +import ipcRendererInjectable from "./ipc/ipc-renderer.injectable"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import { frameCommunicationAdminChannel } from "./allow-communication-to-iframe.injectable"; + +describe("allow communication to iframe", () => { + let di: DiContainer; + let sendMessageToChannelMock: jest.Mock; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerMobX(di); + + runInAction(() => { + registerFeature(di, messagingFeatureForRenderer); + }); + + di.override(ipcRendererInjectable, () => ({ on: () => {} } as unknown)); + + sendMessageToChannelMock = jest.fn(); + di.override(sendMessageToChannelInjectionToken, () => sendMessageToChannelMock); + }); + + it("when application starts, sends message to communication channel to register the frame ID and process ID for further usage", async () => { + await di.inject(startApplicationInjectionToken)(); + + expect(sendMessageToChannelMock).toHaveBeenCalledWith(frameCommunicationAdminChannel); + }); +}); diff --git a/packages/technical-features/messaging/electron/renderer/src/feature.ts b/packages/technical-features/messaging/electron/renderer/src/feature.ts new file mode 100644 index 0000000000..c63092f2e5 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/feature.ts @@ -0,0 +1,18 @@ +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { getFeature } from "@k8slens/feature-core"; +import { messagingFeature } from "@k8slens/messaging"; + +export const messagingFeatureForRenderer = getFeature({ + id: "messaging-for-renderer", + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], + }); + }, + + dependencies: [messagingFeature], +}); diff --git a/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.injectable.ts new file mode 100644 index 0000000000..a2ecffac15 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.injectable.ts @@ -0,0 +1,10 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { ipcRenderer } from "electron"; + +const ipcRendererInjectable = getInjectable({ + id: "ipc-renderer", + instantiate: () => ipcRenderer, + causesSideEffects: true, +}); + +export default ipcRendererInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.test.ts b/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.test.ts new file mode 100644 index 0000000000..e882b5f5aa --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/ipc/ipc-renderer.test.ts @@ -0,0 +1,27 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import ipcRendererInjectable from "./ipc-renderer.injectable"; +import { messagingFeatureForRenderer } from "../feature"; +import { ipcRenderer } from "electron"; + +describe("ipc-renderer", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); + }); + + it("is not undefined", () => { + const actual = di.inject(ipcRendererInjectable); + + expect(actual).not.toBeUndefined(); + }); + + it("is IPC-renderer of Electron", () => { + const actual = di.inject(ipcRendererInjectable); + + expect(actual).toBe(ipcRenderer); + }); +}); diff --git a/packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.injectable.ts similarity index 67% rename from packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts rename to packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.injectable.ts index 1e5b14bb40..64e9b1f873 100644 --- a/packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ b/packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.injectable.ts @@ -1,11 +1,7 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import ipcRendererInjectable from "../ipc-renderer.injectable"; +import ipcRendererInjectable from "../ipc/ipc-renderer.injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { IpcRendererEvent } from "electron"; -import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging"; const enlistMessageChannelListenerInjectable = getInjectable({ id: "enlist-message-channel-listener-for-renderer", diff --git a/packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.test.ts similarity index 73% rename from packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts rename to packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.test.ts index ac416a568e..dc89c7b3e7 100644 --- a/packages/core/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/packages/technical-features/messaging/electron/renderer/src/listening-of-messages/enlist-message-channel-listener.test.ts @@ -1,12 +1,12 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; -import type { EnlistMessageChannelListener } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; import type { IpcRendererEvent, IpcRenderer } from "electron"; -import ipcRendererInjectable from "../ipc-renderer.injectable"; +import ipcRendererInjectable from "../ipc/ipc-renderer.injectable"; +import { + EnlistMessageChannelListener, + enlistMessageChannelListenerInjectionToken, +} from "@k8slens/messaging"; +import { createContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForRenderer } from "../feature"; describe("enlist message channel listener in renderer", () => { let enlistMessageChannelListener: EnlistMessageChannelListener; @@ -15,7 +15,9 @@ describe("enlist message channel listener in renderer", () => { let offMock: jest.Mock; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); onMock = jest.fn(); offMock = jest.fn(); @@ -27,9 +29,7 @@ describe("enlist message channel listener in renderer", () => { di.override(ipcRendererInjectable, () => ipcRendererStub); - enlistMessageChannelListener = di.inject( - enlistMessageChannelListenerInjectionToken, - ); + enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); }); describe("when called", () => { @@ -40,6 +40,7 @@ describe("enlist message channel listener in renderer", () => { handlerMock = jest.fn(); disposer = enlistMessageChannelListener({ + id: "some-listener", channel: { id: "some-channel-id" }, handler: handlerMock, }); @@ -50,10 +51,7 @@ describe("enlist message channel listener in renderer", () => { }); it("registers the listener", () => { - expect(onMock).toHaveBeenCalledWith( - "some-channel-id", - expect.any(Function), - ); + expect(onMock).toHaveBeenCalledWith("some-channel-id", expect.any(Function)); }); it("does not de-register the listener yet", () => { diff --git a/packages/technical-features/messaging/electron/renderer/src/listening-of-requests/enlist-request-channel-listener.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/listening-of-requests/enlist-request-channel-listener.injectable.ts new file mode 100644 index 0000000000..92d6c978fe --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/listening-of-requests/enlist-request-channel-listener.injectable.ts @@ -0,0 +1,18 @@ +/* c8 ignore start */ +import { getInjectable } from "@ogre-tools/injectable"; +import { enlistRequestChannelListenerInjectionToken } from "@k8slens/messaging"; + +const enlistRequestChannelListenerInjectable = getInjectable({ + id: "enlist-request-channel-listener-for-renderer", + + instantiate: () => (listener) => { + throw new Error( + `Tried to enlist request channel "${listener.channel.id}" in "renderer", but requesting it's not supported yet.`, + ); + }, + + injectionToken: enlistRequestChannelListenerInjectionToken, +}); + +export default enlistRequestChannelListenerInjectable; +/* c8 ignore end */ diff --git a/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.injectable.ts new file mode 100644 index 0000000000..03329d0c92 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.injectable.ts @@ -0,0 +1,10 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import ipcRendererInjectable from "../ipc/ipc-renderer.injectable"; + +const invokeIpcInjectable = getInjectable({ + id: "invoke-ipc", + + instantiate: (di) => di.inject(ipcRendererInjectable).invoke, +}); + +export default invokeIpcInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.test.ts b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.test.ts new file mode 100644 index 0000000000..e54c98616b --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/invoke-ipc.test.ts @@ -0,0 +1,21 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForRenderer } from "../feature"; +import { ipcRenderer } from "electron"; +import invokeIpcInjectable from "./invoke-ipc.injectable"; + +describe("ipc-renderer", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); + }); + + it("is IPC-renderer invoke of Electron", () => { + const actual = di.inject(invokeIpcInjectable); + + expect(actual).toBe(ipcRenderer.invoke); + }); +}); diff --git a/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.injectable.ts new file mode 100644 index 0000000000..032042198a --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.injectable.ts @@ -0,0 +1,18 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import type { RequestFromChannel } from "@k8slens/messaging"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; +import invokeIpcInjectable from "./invoke-ipc.injectable"; + +const requestFromChannelInjectable = getInjectable({ + id: "request-from-channel", + + instantiate: (di) => { + const invokeIpc = di.inject(invokeIpcInjectable); + + return ((channel, request) => invokeIpc(channel.id, request)) as RequestFromChannel; + }, + + injectionToken: requestFromChannelInjectionToken, +}); + +export default requestFromChannelInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.test.ts b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.test.ts new file mode 100644 index 0000000000..930040f117 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/requesting-of-requests/request-from-channel.test.ts @@ -0,0 +1,46 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { requestFromChannelInjectionToken } from "@k8slens/messaging"; +import { messagingFeatureForRenderer } from "../feature"; +import type { RequestChannel } from "@k8slens/messaging"; +import invokeIpcInjectable from "./invoke-ipc.injectable"; +import type { AsyncFnMock } from "@async-fn/jest"; +import asyncFn from "@async-fn/jest"; + +describe("request-from-channel", () => { + let di: DiContainer; + let invokeIpcMock: AsyncFnMock<() => Promise>; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); + + invokeIpcMock = asyncFn(); + di.override(invokeIpcInjectable, () => invokeIpcMock); + }); + + describe("when called", () => { + let actualPromise: Promise; + + beforeEach(() => { + const requestFromChannel = di.inject(requestFromChannelInjectionToken); + + const someChannel: RequestChannel = { + id: "some-channel-id", + }; + + actualPromise = requestFromChannel(someChannel, "some-request-payload"); + }); + + it("invokes ipcRenderer of Electron", () => { + expect(invokeIpcMock).toHaveBeenCalledWith("some-channel-id", "some-request-payload"); + }); + + it("when invoke resolves with response, resolves with said response", async () => { + await invokeIpcMock.resolve(42); + + expect(await actualPromise).toBe(42); + }); + }); +}); diff --git a/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.injectable.ts new file mode 100644 index 0000000000..469a1548ab --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.injectable.ts @@ -0,0 +1,19 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import sendToIpcInjectable from "./send-to-ipc.injectable"; +import { SendMessageToChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; + +const messageToChannelInjectable = getInjectable({ + id: "message-to-channel", + + instantiate: (di) => { + const sendToIpc = di.inject(sendToIpcInjectable); + + return ((channel, message) => { + sendToIpc(channel.id, message); + }) as SendMessageToChannel; + }, + + injectionToken: sendMessageToChannelInjectionToken, +}); + +export default messageToChannelInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.test.ts b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.test.ts new file mode 100644 index 0000000000..07989cf16e --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/message-to-channel.test.ts @@ -0,0 +1,38 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import { messagingFeatureForRenderer } from "../feature"; +import type { MessageChannel } from "@k8slens/messaging"; +import sendToIpcInjectable from "./send-to-ipc.injectable"; +import type { AsyncFnMock } from "@async-fn/jest"; +import asyncFn from "@async-fn/jest"; + +describe("message-from-channel", () => { + let di: DiContainer; + let sendToIpcMock: AsyncFnMock<() => Promise>; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); + + sendToIpcMock = asyncFn(); + di.override(sendToIpcInjectable, () => sendToIpcMock); + }); + + describe("when called", () => { + beforeEach(() => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + const someChannel: MessageChannel = { + id: "some-channel-id", + }; + + sendMessageToChannel(someChannel, 42); + }); + + it("sends to ipcRenderer of Electron", () => { + expect(sendToIpcMock).toHaveBeenCalledWith("some-channel-id", 42); + }); + }); +}); diff --git a/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.injectable.ts b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.injectable.ts new file mode 100644 index 0000000000..059dcbe8c2 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.injectable.ts @@ -0,0 +1,10 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import ipcRendererInjectable from "../ipc/ipc-renderer.injectable"; + +const sendToIpcInjectable = getInjectable({ + id: "send-to-ipc", + + instantiate: (di) => di.inject(ipcRendererInjectable).send, +}); + +export default sendToIpcInjectable; diff --git a/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.test.ts b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.test.ts new file mode 100644 index 0000000000..9d1b2303f5 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/src/sending-of-messages/send-to-ipc.test.ts @@ -0,0 +1,21 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { messagingFeatureForRenderer } from "../feature"; +import { ipcRenderer } from "electron"; +import sendToIpcInjectable from "./send-to-ipc.injectable"; + +describe("ipc-renderer", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForRenderer); + }); + + it("is IPC-renderer send of Electron", () => { + const actual = di.inject(sendToIpcInjectable); + + expect(actual).toBe(ipcRenderer.send); + }); +}); diff --git a/packages/technical-features/messaging/electron/renderer/tsconfig.json b/packages/technical-features/messaging/electron/renderer/tsconfig.json new file mode 100644 index 0000000000..1819203dc1 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] +} diff --git a/packages/technical-features/messaging/electron/renderer/webpack.config.js b/packages/technical-features/messaging/electron/renderer/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/messaging/electron/renderer/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/technical-features/messaging/message-bridge-fake/.eslintrc.json b/packages/technical-features/messaging/message-bridge-fake/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/technical-features/messaging/message-bridge-fake/.prettierrc b/packages/technical-features/messaging/message-bridge-fake/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/messaging/message-bridge-fake/index.ts b/packages/technical-features/messaging/message-bridge-fake/index.ts new file mode 100644 index 0000000000..6b85a40628 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/index.ts @@ -0,0 +1,3 @@ +export type { MessageBridgeFake } from "./src/get-message-bridge-fake/get-message-bridge-fake"; + +export { getMessageBridgeFake } from "./src/get-message-bridge-fake/get-message-bridge-fake"; diff --git a/packages/technical-features/messaging/message-bridge-fake/jest.config.js b/packages/technical-features/messaging/message-bridge-fake/jest.config.js new file mode 100644 index 0000000000..38d54ab7b6 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/technical-features/messaging/message-bridge-fake/package.json b/packages/technical-features/messaging/message-bridge-fake/package.json new file mode 100644 index 0000000000..6837504a0e --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/package.json @@ -0,0 +1,49 @@ +{ + "name": "@k8slens/messaging-fake-bridge", + "private": false, + "version": "1.0.0-alpha.1", + "description": "Fake implementation to bridge multiple dependency injection containers.", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "dist" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint:fix": "lens-lint --fix", + "lint": "lens-lint" + }, + "peerDependencies": { + "@k8slens/messaging": "^1.0.0-alpha.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "lodash": "^4.17.21" + }, + + "devDependencies": { + "@async-fn/jest": "^1.6.4", + "@k8slens/feature-core": "6.5.0-alpha.1", + "@k8slens/eslint-config": "^6.5.0-alpha.1", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "mobx": "^6.7.0" + } +} diff --git a/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.test.ts b/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.test.ts new file mode 100644 index 0000000000..e91109df10 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.test.ts @@ -0,0 +1,397 @@ +import { createContainer, DiContainer, Injectable } from "@ogre-tools/injectable"; +import asyncFn, { AsyncFnMock } from "@async-fn/jest"; +import { registerFeature } from "@k8slens/feature-core"; +import { + getMessageChannel, + getMessageChannelListenerInjectable, + getRequestChannel, + getRequestChannelListenerInjectable, + MessageChannel, + testUtils, + RequestChannel, + requestFromChannelInjectionToken, + sendMessageToChannelInjectionToken, +} from "@k8slens/messaging"; + +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { runInAction } from "mobx"; +import { getPromiseStatus } from "@k8slens/test-utils"; +import { getMessageBridgeFake } from "./get-message-bridge-fake"; +import { startApplicationInjectionToken } from "@k8slens/application"; + +type SomeMessageChannel = MessageChannel; +type SomeRequestChannel = RequestChannel; + +const someMessageChannel: SomeMessageChannel = getMessageChannel("some-message-channel"); +const someRequestChannel: SomeRequestChannel = getRequestChannel("some-request-channel"); +const someOtherRequestChannel: SomeRequestChannel = { + id: "some-other-request-channel", +}; +const someRequestChannelWithoutListeners: SomeRequestChannel = { + id: "some-request-channel-without-listeners", +}; + +[{ scenarioIsAsync: true }, { scenarioIsAsync: false }].forEach(({ scenarioIsAsync }) => + describe(`get-message-bridge-fake, given running as ${ + scenarioIsAsync ? "async" : "sync" + }`, () => { + let messageBridgeFake: any; + + beforeEach(() => { + messageBridgeFake = getMessageBridgeFake(); + }); + + describe("given multiple DIs are involved", () => { + let someDi1: DiContainer; + let someDi2: DiContainer; + let someDiWithoutListeners: DiContainer; + + beforeEach(async () => { + someDi1 = createContainer("some-di-1"); + someDi2 = createContainer("some-di-2"); + + someDiWithoutListeners = createContainer("some-di-3"); + + registerMobX(someDi1); + registerMobX(someDi2); + registerMobX(someDiWithoutListeners); + + runInAction(() => { + const feature = testUtils.messagingFeatureForUnitTesting; + + registerFeature(someDi1, feature); + registerFeature(someDi2, feature); + registerFeature(someDiWithoutListeners, feature); + }); + + messageBridgeFake.involve(someDi1, someDi2, someDiWithoutListeners); + + if (scenarioIsAsync) { + messageBridgeFake.setAsync(scenarioIsAsync); + } + + await Promise.all([ + someDi1.inject(startApplicationInjectionToken)(), + someDi2.inject(startApplicationInjectionToken)(), + someDiWithoutListeners.inject(startApplicationInjectionToken)(), + ]); + }); + + describe("given there are message listeners", () => { + let someHandler1MockInDi1: jest.Mock; + let someHandler1MockInDi2: jest.Mock; + let someHandler2MockInDi2: jest.Mock; + let someListener1InDi2: Injectable; + + beforeEach(() => { + someHandler1MockInDi1 = jest.fn(); + someHandler1MockInDi2 = jest.fn(); + someHandler2MockInDi2 = jest.fn(); + + const someListener1InDi1 = getMessageChannelListenerInjectable({ + id: "some-listener-in-di-1", + channel: someMessageChannel, + getHandler: () => someHandler1MockInDi1, + }); + + someListener1InDi2 = getMessageChannelListenerInjectable({ + id: "some-listener-in-di-2", + channel: someMessageChannel, + getHandler: () => someHandler1MockInDi2, + }); + + const someListener2InDi2 = getMessageChannelListenerInjectable({ + id: "some-listener-2-in-di-2", + channel: someMessageChannel, + getHandler: () => someHandler2MockInDi2, + }); + + runInAction(() => { + someDi1.register(someListener1InDi1); + someDi2.register(someListener1InDi2); + someDi2.register(someListener2InDi2); + }); + }); + + describe("given there is a listener in di-2 that responds to a message with a message", () => { + beforeEach(() => { + const someResponder = getMessageChannelListenerInjectable({ + id: "some-responder-di-2", + channel: someMessageChannel, + + getHandler: (di) => { + const sendMessage = di.inject(sendMessageToChannelInjectionToken); + + return (message) => { + sendMessage(someMessageChannel, `some-response-to: ${message}`); + }; + }, + }); + + runInAction(() => { + someDi2.register(someResponder); + }); + }); + + describe("given a message is sent in di-1", () => { + beforeEach(() => { + const sendMessageToChannelFromDi1 = someDi1.inject( + sendMessageToChannelInjectionToken, + ); + + sendMessageToChannelFromDi1(someMessageChannel, "some-message"); + }); + + const scenarioTitle = scenarioIsAsync + ? "when all message steps are propagated using a wrapper" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioTitle, () => { + let someWrapper: jest.Mock; + + beforeEach((done) => { + someWrapper = jest.fn((propagation) => propagation()); + + if (scenarioIsAsync) { + messageBridgeFake.messagePropagationRecursive(someWrapper).then(done); + } else { + done(); + } + }); + + it("the response gets handled in di-1", () => { + expect(someHandler1MockInDi1).toHaveBeenCalledWith( + "some-response-to: some-message", + { + frameId: 42, + processId: 42, + }, + ); + }); + + scenarioIsAsync && + it("the wrapper gets called with the both propagations", () => { + expect(someWrapper).toHaveBeenCalledTimes(2); + }); + }); + + const scenarioName: string = scenarioIsAsync + ? "when all message steps are propagated not using a wrapper" + : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + messageBridgeFake.messagePropagationRecursive().then(done); + } else { + done(); + } + }); + + it("the response gets handled in di-1", () => { + expect(someHandler1MockInDi1).toHaveBeenCalledWith( + "some-response-to: some-message", + { + frameId: 42, + processId: 42, + }, + ); + }); + }); + }); + }); + + describe("when sending message in a DI", () => { + beforeEach(() => { + const sendMessageToChannelFromDi1 = someDi1.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannelFromDi1(someMessageChannel, "some-message"); + }); + + it("listener in sending DI does not handle the message", () => { + expect(someHandler1MockInDi1).not.toHaveBeenCalled(); + }); + + scenarioIsAsync && + it("listeners in other than sending DIs do not handle the message yet", () => { + expect(someHandler1MockInDi2).not.toHaveBeenCalled(); + expect(someHandler2MockInDi2).not.toHaveBeenCalled(); + }); + + const scenarioName = scenarioIsAsync ? "when messages are propagated" : "immediately"; + + // eslint-disable-next-line jest/valid-title + describe(scenarioName, () => { + beforeEach((done) => { + if (scenarioIsAsync) { + messageBridgeFake.messagePropagation().then(done); + } else { + done(); + } + }); + + it("listeners in other than sending DIs handle the message", () => { + expect(someHandler1MockInDi2).toHaveBeenCalledWith("some-message", { + frameId: 42, + processId: 42, + }); + + expect(someHandler2MockInDi2).toHaveBeenCalledWith("some-message", { + frameId: 42, + processId: 42, + }); + }); + }); + + scenarioIsAsync && + describe("when messages are propagated using a wrapper, such as act() in react testing lib", () => { + let someWrapper: jest.Mock; + + beforeEach(async () => { + someWrapper = jest.fn((observation) => observation()); + + await messageBridgeFake.messagePropagation(someWrapper); + }); + + it("the wrapper gets called with the related propagation", async () => { + expect(someWrapper).toHaveBeenCalledTimes(1); + }); + + it("listeners still handle the message", () => { + expect(someHandler1MockInDi2).toHaveBeenCalledWith("some-message", { + frameId: 42, + processId: 42, + }); + + expect(someHandler2MockInDi2).toHaveBeenCalledWith("some-message", { + frameId: 42, + processId: 42, + }); + }); + }); + }); + + it("given a listener is deregistered, when sending message, deregistered listener does not handle the message", () => { + runInAction(() => { + someDi2.deregister(someListener1InDi2); + }); + + const sendMessageToChannelFromDi1 = someDi1.inject(sendMessageToChannelInjectionToken); + + someHandler1MockInDi2.mockClear(); + + sendMessageToChannelFromDi1(someMessageChannel, "irrelevant"); + + expect(someHandler1MockInDi2).not.toHaveBeenCalled(); + }); + }); + + describe("given there are request listeners", () => { + let someHandler1MockInDi1: AsyncFnMock<(message: string) => Promise>; + + let someHandler1MockInDi2: AsyncFnMock<(message: string) => Promise>; + + let someListener1InDi2: Injectable; + let actualPromise: Promise; + + beforeEach(() => { + someHandler1MockInDi1 = asyncFn(); + someHandler1MockInDi2 = asyncFn(); + + const someListener1InDi1 = getRequestChannelListenerInjectable({ + id: "some-request-listener-in-di-1", + channel: someOtherRequestChannel, + getHandler: () => someHandler1MockInDi1, + }); + + someListener1InDi2 = getRequestChannelListenerInjectable({ + id: "some-request-listener-in-di-2", + channel: someRequestChannel, + getHandler: () => someHandler1MockInDi2, + }); + + runInAction(() => { + someDi1.register(someListener1InDi1); + someDi2.register(someListener1InDi2); + }); + }); + + describe("when requesting from a channel in a DI", () => { + beforeEach(() => { + const requestFromChannelFromDi1 = someDi1.inject(requestFromChannelInjectionToken); + + actualPromise = requestFromChannelFromDi1(someRequestChannel, "some-request"); + }); + + it("listener in requesting DI does not handle the request", () => { + expect(someHandler1MockInDi1).not.toHaveBeenCalled(); + }); + + it("the listener in other than requesting DIs handle the request", () => { + expect(someHandler1MockInDi2).toHaveBeenCalledWith("some-request"); + }); + + it("does not resolve yet", async () => { + const promiseStatus = await getPromiseStatus(actualPromise); + + expect(promiseStatus.fulfilled).toBe(false); + }); + + it("when handle resolves, resolves with response", async () => { + await someHandler1MockInDi2.resolve(42); + + const actual = await actualPromise; + + expect(actual).toBe(42); + }); + }); + + it("given a listener is deregistered, when requesting, deregistered listener does not handle the request", () => { + runInAction(() => { + someDi2.deregister(someListener1InDi2); + }); + + const sendMessageToChannelFromDi1 = someDi1.inject(sendMessageToChannelInjectionToken); + + someHandler1MockInDi2.mockClear(); + + sendMessageToChannelFromDi1(someMessageChannel, "irrelevant"); + + expect(someHandler1MockInDi2).not.toHaveBeenCalled(); + }); + + it("given there are multiple listeners between different DIs for same channel, when requesting, throws", () => { + const someConflictingListenerInjectable = getRequestChannelListenerInjectable({ + id: "conflicting-listener", + channel: someRequestChannel, + getHandler: () => () => 84, + }); + + runInAction(() => { + someDi1.register(someConflictingListenerInjectable); + }); + + const requestFromChannelFromDi2 = someDi2.inject(requestFromChannelInjectionToken); + + return expect(() => + requestFromChannelFromDi2(someRequestChannel, "irrelevant"), + ).rejects.toThrow( + 'Tried to make a request but multiple listeners were discovered for channel "some-request-channel" in multiple DIs.', + ); + }); + + it("when requesting from channel without listener, throws", () => { + const requestFromChannel = someDi1.inject(requestFromChannelInjectionToken); + + return expect(() => + requestFromChannel(someRequestChannelWithoutListeners, "irrelevant"), + ).rejects.toThrow( + 'Tried to make a request but no listeners for channel "some-request-channel-without-listeners" was discovered in any DIs', + ); + }); + }); + }); + }), +); diff --git a/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.ts b/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.ts new file mode 100644 index 0000000000..ef8eed6461 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/src/get-message-bridge-fake/get-message-bridge-fake.ts @@ -0,0 +1,196 @@ +import type { DiContainer } from "@ogre-tools/injectable"; +import type { Channel, MessageChannelHandler, RequestChannelHandler } from "@k8slens/messaging"; + +import { + enlistMessageChannelListenerInjectionToken, + enlistRequestChannelListenerInjectionToken, + RequestFromChannel, + requestFromChannelInjectionToken, + sendMessageToChannelInjectionToken, +} from "@k8slens/messaging"; + +import { pipeline } from "@ogre-tools/fp"; +import { filter, map } from "lodash/fp"; +import asyncFn, { AsyncFnMock } from "@async-fn/jest"; + +export type MessageBridgeFake = { + involve: (...dis: DiContainer[]) => void; + messagePropagation: () => Promise; + messagePropagationRecursive: (callback: any) => any; + setAsync: (value: boolean) => void; +}; + +const overrideMessaging = ({ + di, + messageListenersByDi, + messagePropagationBuffer, + getAsyncModeStatus, +}: { + di: DiContainer; + + messageListenersByDi: Map>>>; + + messagePropagationBuffer: Set<{ resolve: () => Promise }>; + + getAsyncModeStatus: () => boolean; +}) => { + const messageHandlersByChannel = new Map>>(); + + messageListenersByDi.set(di, messageHandlersByChannel); + + di.override(sendMessageToChannelInjectionToken, () => (channel, message) => { + const allOtherDis = [...messageListenersByDi.keys()].filter((x) => x !== di); + + allOtherDis.forEach((otherDi) => { + const listeners = messageListenersByDi.get(otherDi); + + const handlersForChannel = listeners?.get(channel.id); + + if (!handlersForChannel) { + return; + } + + if (getAsyncModeStatus()) { + const resolvableHandlePromise = asyncFn(); + + resolvableHandlePromise().then(() => { + handlersForChannel.forEach((handler) => handler(message, { frameId: 42, processId: 42 })); + }); + + messagePropagationBuffer.add(resolvableHandlePromise); + } else { + handlersForChannel.forEach((handler) => handler(message, { frameId: 42, processId: 42 })); + } + }); + }); + + di.override(enlistMessageChannelListenerInjectionToken, () => (listener) => { + if (!messageHandlersByChannel.has(listener.channel.id)) { + messageHandlersByChannel.set(listener.channel.id, new Set()); + } + + const handlerSet = messageHandlersByChannel.get(listener.channel.id); + + handlerSet?.add(listener.handler); + + return () => { + handlerSet?.delete(listener.handler); + }; + }); +}; + +const overrideRequesting = ({ + di, + requestListenersByDi, +}: { + di: DiContainer; + + requestListenersByDi: Map>>>; +}) => { + const requestHandlersByChannel = new Map>>(); + + requestListenersByDi.set(di, requestHandlersByChannel); + + di.override( + requestFromChannelInjectionToken, + () => + (async (channel, request) => + pipeline( + [...requestListenersByDi.values()], + map((listenersByChannel) => listenersByChannel?.get(channel.id)), + filter((x) => !!x), + + (channelSpecificListeners) => { + if (channelSpecificListeners.length === 0) { + throw new Error( + `Tried to make a request but no listeners for channel "${channel.id}" was discovered in any DIs`, + ); + } + + if (channelSpecificListeners.length > 1) { + throw new Error( + `Tried to make a request but multiple listeners were discovered for channel "${channel.id}" in multiple DIs.`, + ); + } + + const listeners = channelSpecificListeners[0]; + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const [handler] = listeners!; + + return handler; + }, + + async (handler) => handler(request), + )) as RequestFromChannel, + ); + + di.override(enlistRequestChannelListenerInjectionToken, () => (listener) => { + if (!requestHandlersByChannel.has(listener.channel.id)) { + requestHandlersByChannel.set(listener.channel.id, new Set()); + } + + const handlerSet = requestHandlersByChannel.get(listener.channel.id); + + handlerSet?.add(listener.handler); + + return () => { + handlerSet?.delete(listener.handler); + }; + }); +}; + +export const getMessageBridgeFake = (): MessageBridgeFake => { + const messageListenersByDi = new Map< + DiContainer, + Map>> + >(); + + const requestListenersByDi = new Map< + DiContainer, + Map>> + >(); + + const messagePropagationBuffer = new Set void>>(); + + const messagePropagation = async (wrapper: (callback: any) => any = (callback) => callback()) => { + const oldMessages = [...messagePropagationBuffer.values()]; + + messagePropagationBuffer.clear(); + await Promise.all(oldMessages.map((x) => wrapper(x.resolve))); + }; + + const messagePropagationRecursive = async ( + wrapper: (callback: any) => any = (callback) => callback(), + ) => { + while (messagePropagationBuffer.size) { + await messagePropagation(wrapper); + } + }; + + let asyncModeStatus = false; + const getAsyncModeStatus = () => asyncModeStatus; + + return { + involve: (...dis: DiContainer[]) => { + dis.forEach((di) => { + overrideRequesting({ di, requestListenersByDi }); + + overrideMessaging({ + di, + messageListenersByDi, + messagePropagationBuffer, + getAsyncModeStatus, + }); + }); + }, + + messagePropagation, + + messagePropagationRecursive, + + setAsync: (value) => { + asyncModeStatus = value; + }, + }; +}; diff --git a/packages/technical-features/messaging/message-bridge-fake/tsconfig.json b/packages/technical-features/messaging/message-bridge-fake/tsconfig.json new file mode 100644 index 0000000000..ec29a8f75f --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/packages/technical-features/messaging/message-bridge-fake/webpack.config.js b/packages/technical-features/messaging/message-bridge-fake/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/messaging/message-bridge-fake/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/utility-features/run-many/jest.config.js b/packages/utility-features/run-many/jest.config.js index 23be80353b..05dbeacf60 100644 --- a/packages/utility-features/run-many/jest.config.js +++ b/packages/utility-features/run-many/jest.config.js @@ -1,2 +1,3 @@ -module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; +const config = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; + +module.exports = { ...config, coverageThreshold: undefined }; diff --git a/packages/utility-features/run-many/package.json b/packages/utility-features/run-many/package.json index 1dd0229afd..1fa8af2ba1 100644 --- a/packages/utility-features/run-many/package.json +++ b/packages/utility-features/run-many/package.json @@ -22,12 +22,12 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "test:unit": "jest --coverage --runInBand" }, "peerDependencies": { "@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1", - "@ogre-tools/fp": "^15.1.1", + "@ogre-tools/fp": "^15.1.2", "@ogre-tools/injectable": "^15.1.2", "type-fest": "^2.19.0", "typed-emitter": "^1.4.0", diff --git a/packages/utility-features/startable-stoppable/.eslintrc.json b/packages/utility-features/startable-stoppable/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/utility-features/startable-stoppable/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/utility-features/startable-stoppable/.prettierrc b/packages/utility-features/startable-stoppable/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/utility-features/startable-stoppable/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/utility-features/startable-stoppable/index.ts b/packages/utility-features/startable-stoppable/index.ts new file mode 100644 index 0000000000..7f5c07cf47 --- /dev/null +++ b/packages/utility-features/startable-stoppable/index.ts @@ -0,0 +1,3 @@ +export type { StartableStoppable, Starter, Stopper } from "./src/get-startable-stoppable"; + +export { getStartableStoppable } from "./src/get-startable-stoppable"; diff --git a/packages/utility-features/startable-stoppable/jest.config.js b/packages/utility-features/startable-stoppable/jest.config.js new file mode 100644 index 0000000000..38d54ab7b6 --- /dev/null +++ b/packages/utility-features/startable-stoppable/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/utility-features/startable-stoppable/package.json b/packages/utility-features/startable-stoppable/package.json new file mode 100644 index 0000000000..940e1e91b2 --- /dev/null +++ b/packages/utility-features/startable-stoppable/package.json @@ -0,0 +1,38 @@ +{ + "name": "@k8slens/startable-stoppable", + "private": false, + "version": "1.0.0-alpha.1", + "description": "TBD", + "type": "commonjs", + + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + + "files": [ + "build" + ], + "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": "webpack", + "dev": "webpack --mode=development --watch", + "test:unit": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "devDependencies": { + "@k8slens/eslint-config": "^6.5.0-alpha.1" + } +} diff --git a/packages/core/src/common/utils/get-startable-stoppable.test.ts b/packages/utility-features/startable-stoppable/src/get-startable-stoppable.test.ts similarity index 84% rename from packages/core/src/common/utils/get-startable-stoppable.test.ts rename to packages/utility-features/startable-stoppable/src/get-startable-stoppable.test.ts index dc8b24dd43..2ec64eeb95 100644 --- a/packages/core/src/common/utils/get-startable-stoppable.test.ts +++ b/packages/utility-features/startable-stoppable/src/get-startable-stoppable.test.ts @@ -1,7 +1,3 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ import type { StartableStoppable } from "./get-startable-stoppable"; import { getStartableStoppable } from "./get-startable-stoppable"; @@ -25,7 +21,7 @@ describe("getStartableStoppable", () => { }); it("when stopping before ever starting, throws", () => { - expect(() => actual.stop()).toThrow("Tried to stop \"some-id\", but it is already stopped."); + expect(() => actual.stop()).toThrow('Tried to stop "some-id", but it is already stopped.'); }); it("is not started", () => { @@ -45,6 +41,10 @@ describe("getStartableStoppable", () => { expect(actual.started).toBe(true); }); + it("when started again, throws", () => { + expect(() => actual.start()).toThrow('Tried to start "some-id", but it is already started.'); + }); + describe("when stopped", () => { beforeEach(() => { actual.stop(); diff --git a/packages/core/src/common/utils/get-startable-stoppable.ts b/packages/utility-features/startable-stoppable/src/get-startable-stoppable.ts similarity index 86% rename from packages/core/src/common/utils/get-startable-stoppable.ts rename to packages/utility-features/startable-stoppable/src/get-startable-stoppable.ts index 05d8b4d9af..85f0a6336d 100644 --- a/packages/core/src/common/utils/get-startable-stoppable.ts +++ b/packages/utility-features/startable-stoppable/src/get-startable-stoppable.ts @@ -1,8 +1,3 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - export type Stopper = () => void; export type Starter = () => Stopper; diff --git a/packages/utility-features/startable-stoppable/tsconfig.json b/packages/utility-features/startable-stoppable/tsconfig.json new file mode 100644 index 0000000000..1819203dc1 --- /dev/null +++ b/packages/utility-features/startable-stoppable/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] +} diff --git a/packages/utility-features/startable-stoppable/webpack.config.js b/packages/utility-features/startable-stoppable/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/utility-features/startable-stoppable/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/utility-features/test-utils/index.ts b/packages/utility-features/test-utils/index.ts index ed5afc6535..aca8fd5f9a 100644 --- a/packages/utility-features/test-utils/index.ts +++ b/packages/utility-features/test-utils/index.ts @@ -2,3 +2,5 @@ export * from "./src/flush-promises"; export * from "./src/get-global-override-for-function"; export * from "./src/get-global-override"; export * from "./src/get-promise-status"; +export * from "./src/render-for"; +export * from "./src/run-with-thrown-mobx-reactions"; diff --git a/packages/utility-features/test-utils/package.json b/packages/utility-features/test-utils/package.json index 0dc5170a07..4336c0682b 100644 --- a/packages/utility-features/test-utils/package.json +++ b/packages/utility-features/test-utils/package.json @@ -21,12 +21,14 @@ "homepage": "https://github.com/lensapp/lens", "scripts": { "build": "webpack", - "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "dev": "webpack --mode=development --watch" }, "peerDependencies": { "@ogre-tools/injectable": "^15.1.2", - "lodash": "^4.17.21" + "@ogre-tools/injectable-react": "^15.1.2", + "@testing-library/react": "^12.1.5", + "lodash": "^4.17.21", + "react": "^17.0.2" }, "devDependencies": { "@types/lodash": "^4.14.191" diff --git a/packages/utility-features/test-utils/src/render-for.tsx b/packages/utility-features/test-utils/src/render-for.tsx new file mode 100644 index 0000000000..2508d70d69 --- /dev/null +++ b/packages/utility-features/test-utils/src/render-for.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import type { RenderResult } from "@testing-library/react"; +import { render as testingLibraryRender } from "@testing-library/react"; +import type { DiContainer } from "@ogre-tools/injectable"; +import { DiContextProvider } from "@ogre-tools/injectable-react"; + +export type DiRender = (ui: React.ReactElement) => RenderResult; + +type DiRenderFor = (di: DiContainer) => DiRender; + +export const renderFor: DiRenderFor = (di) => (ui) => { + const result = testingLibraryRender( + {ui} + ); + + return { + ...result, + + rerender: (ui: React.ReactElement) => + result.rerender( + {ui} + ), + }; +}; diff --git a/packages/utility-features/test-utils/src/run-with-thrown-mobx-reactions.ts b/packages/utility-features/test-utils/src/run-with-thrown-mobx-reactions.ts new file mode 100644 index 0000000000..cc3f7ada23 --- /dev/null +++ b/packages/utility-features/test-utils/src/run-with-thrown-mobx-reactions.ts @@ -0,0 +1,38 @@ +import { noop } from "lodash/fp"; +import { _resetGlobalState, configure } from "mobx"; + +export const runWithThrownMobxReactions = (callback: () => void) => { + const originalConsoleWarn = console.warn; + + console.warn = noop; + + configure({ + disableErrorBoundaries: true, + }); + + console.warn = originalConsoleWarn; + + let error: any; + + try { + callback(); + } catch (e) { + error = e; + } finally { + configure({ + disableErrorBoundaries: false, + }); + + // This is because when disableErrorBoundaries is true, MobX doesn't recover from the thrown + // errors, and its global state starts bleeding between tests making. + _resetGlobalState(); + + if (!error) { + throw new Error( + "Tried to run with thrown MobX reactions but nothing was thrown" + ); + } else { + throw error; + } + } +}; diff --git a/packages/utility-features/utilities/jest.config.js b/packages/utility-features/utilities/jest.config.js index 23be80353b..05dbeacf60 100644 --- a/packages/utility-features/utilities/jest.config.js +++ b/packages/utility-features/utilities/jest.config.js @@ -1,2 +1,3 @@ -module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; +const config = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; + +module.exports = { ...config, coverageThreshold: undefined }; diff --git a/packages/utility-features/utilities/package.json b/packages/utility-features/utilities/package.json index 01c75c4d7c..777907d851 100644 --- a/packages/utility-features/utilities/package.json +++ b/packages/utility-features/utilities/package.json @@ -22,7 +22,7 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "test:unit": "jest --coverage --runInBand" }, "peerDependencies": { "@astronautlabs/jsonpath": "^1.1.0", @@ -47,6 +47,7 @@ "@types/react-router": "^5.1.20", "@types/readable-stream": "^2.3.15", "@types/semver": "^7.3.13", - "@types/tar": "^6.1.4" + "@types/tar": "^6.1.4", + "type-fest": "^2.14.0" } } diff --git a/packages/utility-features/utilities/src/splitArray.test.ts b/packages/utility-features/utilities/src/splitArray.test.ts index 038d4731d8..9a1a2aac59 100644 --- a/packages/utility-features/utilities/src/splitArray.test.ts +++ b/packages/utility-features/utilities/src/splitArray.test.ts @@ -3,62 +3,62 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { bifurcateArray, splitArray } from "../splitArray"; +import { array } from "./array"; describe("split array on element tests", () => { it("empty array", () => { - expect(splitArray([], 10)).toStrictEqual([[], [], false]); + expect(array.split([], 10)).toStrictEqual([[], [], false]); }); it("one element, not in array", () => { - expect(splitArray([1], 10)).toStrictEqual([[1], [], false]); + expect(array.split([1], 10)).toStrictEqual([[1], [], false]); }); it("ten elements, not in array", () => { - expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [], false]); + expect(array.split([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [], false]); }); it("one elements, in array", () => { - expect(splitArray([1], 1)).toStrictEqual([[], [], true]); + expect(array.split([1], 1)).toStrictEqual([[], [], true]); }); it("ten elements, in front array", () => { - expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0)).toStrictEqual([[], [1, 2, 3, 4, 5, 6, 7, 8, 9], true]); + expect(array.split([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0)).toStrictEqual([[], [1, 2, 3, 4, 5, 6, 7, 8, 9], true]); }); it("ten elements, in middle array", () => { - expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 4)).toStrictEqual([[0, 1, 2, 3], [5, 6, 7, 8, 9], true]); + expect(array.split([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 4)).toStrictEqual([[0, 1, 2, 3], [5, 6, 7, 8, 9], true]); }); it("ten elements, in end array", () => { - expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8], [], true]); + expect(array.split([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8], [], true]); }); }); describe("bifurcateArray", () => { it("should return tuple of empty arrays from empty array", () => { - const [left, right] = bifurcateArray([], () => true); + const [left, right] = array.bifurcate([], () => true); expect(left).toStrictEqual([]); expect(right).toStrictEqual([]); }); it("should return all true condition returning items in the right array", () => { - const [left, right] = bifurcateArray([1, 2, 3], () => true); + const [left, right] = array.bifurcate([1, 2, 3], () => true); expect(left).toStrictEqual([]); expect(right).toStrictEqual([1, 2, 3]); }); it("should return all false condition returning items in the right array", () => { - const [left, right] = bifurcateArray([1, 2, 3], () => false); + const [left, right] = array.bifurcate([1, 2, 3], () => false); expect(left).toStrictEqual([1, 2, 3]); expect(right).toStrictEqual([]); }); it("should split array as specified", () => { - const [left, right] = bifurcateArray([1, 2, 3], (i) => Boolean(i % 2)); + const [left, right] = array.bifurcate([1, 2, 3], (i) => Boolean(i % 2)); expect(left).toStrictEqual([2]); expect(right).toStrictEqual([1, 3]); diff --git a/packages/utility-features/utilities/src/union-env-path.test.ts b/packages/utility-features/utilities/src/union-env-path.test.ts index ff8ca916d2..10afb9d1d6 100644 --- a/packages/utility-features/utilities/src/union-env-path.test.ts +++ b/packages/utility-features/utilities/src/union-env-path.test.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { unionPATHs } from "../union-env-path"; +import { unionPATHs } from "./union-env-path"; describe("unionPATHs", () => { it("return the same path if given only one with no double delimiters", () => {