mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into dependabot/npm_and_yarn/swc/core-1.3.37
This commit is contained in:
commit
405b1c16a5
54
.github/workflows/cron-test.yaml
vendored
Normal file
54
.github/workflows/cron-test.yaml
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
name: Cron Test
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * 1" # Run on the first day over every week
|
||||
jobs:
|
||||
test:
|
||||
name: cron unit tests on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-11, windows-2019]
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Add the current IP address, long hostname and short hostname record to /etc/hosts file
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Using Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Get npm cache directory path
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
id: npm-cache-dir-path
|
||||
shell: bash
|
||||
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- uses: nick-fields/retry@v2
|
||||
name: Install dependencies
|
||||
with:
|
||||
timeout_minutes: 20
|
||||
max_attempts: 3
|
||||
retry_on: error
|
||||
command: npm ci
|
||||
|
||||
- run: npm run test:unit
|
||||
name: Run tests
|
||||
93
.github/workflows/test.yml
vendored
93
.github/workflows/test.yml
vendored
@ -7,14 +7,80 @@ on:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
test:
|
||||
name: ${{ matrix.type }} tests on ${{ matrix.os }}
|
||||
integration-test:
|
||||
name: integration tests on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-11, windows-2019]
|
||||
type: [unit, smoke]
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- name: Checkout Release from lens
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Add the current IP address, long hostname and short hostname record to /etc/hosts file
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Using Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Get npm cache directory path
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
id: npm-cache-dir-path
|
||||
shell: bash
|
||||
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- uses: nick-fields/retry@v2
|
||||
name: Install dependencies
|
||||
with:
|
||||
timeout_minutes: 20
|
||||
max_attempts: 3
|
||||
retry_on: error
|
||||
command: npm ci
|
||||
|
||||
- name: Install integration test dependencies
|
||||
id: minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
with:
|
||||
minikube-version: latest
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
|
||||
- run: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' npm run test:integration
|
||||
name: Run Linux integration tests
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
|
||||
- run: npm run test:integration
|
||||
name: Run macOS integration tests
|
||||
shell: bash
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
|
||||
- run: npm run test:integration
|
||||
name: Run Windows integration tests
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
|
||||
unit-test:
|
||||
name: unit tests on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- name: Checkout Release from lens
|
||||
@ -57,24 +123,3 @@ jobs:
|
||||
|
||||
- run: npm run test:unit
|
||||
name: Run tests
|
||||
if: ${{ matrix.type == 'unit' }}
|
||||
|
||||
- name: Install integration test dependencies
|
||||
id: minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
with:
|
||||
minikube-version: latest
|
||||
if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }}
|
||||
|
||||
- run: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' npm run test:integration
|
||||
name: Run Linux integration tests
|
||||
if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }}
|
||||
|
||||
- run: npm run test:integration
|
||||
name: Run macOS integration tests
|
||||
shell: bash
|
||||
if: ${{ runner.os == 'macOS' && matrix.type == 'smoke' }}
|
||||
|
||||
- run: npm run test:integration
|
||||
name: Run Windows integration tests
|
||||
if: ${{ runner.os == 'Windows' && matrix.type == 'smoke' }}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"useWorkspaces": true,
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"npmClient": "npm",
|
||||
"npmClientArgs": [
|
||||
"--network-timeout=100000"
|
||||
|
||||
17483
package-lock.json
generated
17483
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,6 @@
|
||||
"adr": "^1.4.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"lerna": "^6.5.1",
|
||||
"rimraf": "^4.1.2"
|
||||
"rimraf": "^4.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/bump-version-for-cron",
|
||||
"version": "6.4.0-cron.4db172da60",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "CLI to bump the version to during a cron daily alpha release",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"productName": "",
|
||||
"description": "Lens Desktop Core",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
@ -127,7 +127,7 @@
|
||||
"@astronautlabs/jsonpath": "^1.1.0",
|
||||
"@hapi/call": "^9.0.1",
|
||||
"@hapi/subtext": "^7.1.0",
|
||||
"@k8slens/node-fetch": "^6.4.0-beta.13",
|
||||
"@k8slens/node-fetch": "^6.5.0-alpha.0",
|
||||
"@kubernetes/client-node": "^0.18.1",
|
||||
"@material-ui/styles": "^4.11.5",
|
||||
"@ogre-tools/fp": "^15.1.1",
|
||||
@ -329,7 +329,7 @@
|
||||
"xterm-addon-fit": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@k8slens/application": "^6.4.0-beta.13",
|
||||
"@k8slens/application": "^6.5.0-alpha.0",
|
||||
"@types/byline": "^4.2.33",
|
||||
"@types/chart.js": "^2.9.36",
|
||||
"@types/color": "^3.0.3",
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import type { CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
|
||||
import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog/catalog-entity";
|
||||
import productNameInjectable from "../vars/product-name.injectable";
|
||||
@ -32,7 +32,7 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
|
||||
|
||||
onContextMenuOpen(context: CatalogEntityContextMenuContext) {
|
||||
// NOTE: this is safe because `onContextMenuOpen` is only supposed to be called in the renderer
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.renderer);
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("renderer");
|
||||
const productName = di.inject(productNameInjectable);
|
||||
const weblinkStore = di.inject(weblinkStoreInjectable);
|
||||
|
||||
|
||||
17
packages/core/src/common/create-app.ts
Normal file
17
packages/core/src/common/create-app.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
export interface ApplicationConfig {
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export interface Application {
|
||||
start: () => Promise<void>;
|
||||
readonly di: DiContainerForInjection;
|
||||
}
|
||||
|
||||
export type CreateApplication = (config: ApplicationConfig) => Application;
|
||||
@ -7,7 +7,7 @@ import type { ReadOptions } from "fs-extra";
|
||||
import fse from "fs-extra";
|
||||
|
||||
/**
|
||||
* NOTE: Add corrisponding a corrisponding override of this injecable in `src/test-utils/override-fs-with-fakes.ts`
|
||||
* NOTE: Add corresponding override of this injectable in `src/test-utils/override-fs-with-fakes.ts`
|
||||
*/
|
||||
const fsInjectable = getInjectable({
|
||||
id: "fs",
|
||||
|
||||
@ -24,6 +24,7 @@ export const applicationInformationFakeInjectable = getInjectable({
|
||||
welcomeRoute: "/welcome",
|
||||
copyright: "some-copyright-information",
|
||||
description: "some-descriptive-text",
|
||||
dependencies: {},
|
||||
}),
|
||||
|
||||
injectionToken: applicationInformationToken,
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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 nodeEnvInjectionToken from "./node-env-injection-token";
|
||||
|
||||
const nodeEnvFakeInjectable = getInjectable({
|
||||
id: "node-env-fake",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
});
|
||||
|
||||
export default nodeEnvFakeInjectable;
|
||||
@ -9,7 +9,7 @@ import {
|
||||
createContainer,
|
||||
getInjectable,
|
||||
} from "@ogre-tools/injectable";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api";
|
||||
import { setLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api";
|
||||
import { asLegacyGlobalObjectForExtensionApiWithModifications } from "./as-legacy-global-object-for-extension-api-with-modifications";
|
||||
|
||||
describe("asLegacyGlobalObjectForExtensionApiWithModifications", () => {
|
||||
@ -25,7 +25,7 @@ describe("asLegacyGlobalObjectForExtensionApiWithModifications", () => {
|
||||
|
||||
jest.spyOn(di, "inject");
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||
setLegacyGlobalDiForExtensionApi(di, "renderer");
|
||||
|
||||
someInjectable = getInjectable({
|
||||
id: "some-injectable",
|
||||
|
||||
@ -4,17 +4,11 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
export type Environments = "main" | "renderer";
|
||||
|
||||
const legacyGlobalDis = new Map<Environments, DiContainer>();
|
||||
|
||||
export enum Environments {
|
||||
renderer,
|
||||
main,
|
||||
}
|
||||
|
||||
export const setLegacyGlobalDiForExtensionApi = (
|
||||
di: DiContainer,
|
||||
environment: Environments,
|
||||
) => {
|
||||
export const setLegacyGlobalDiForExtensionApi = (di: DiContainer, environment: Environments) => {
|
||||
legacyGlobalDis.set(environment, di);
|
||||
};
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@ import extensionLoaderInjectable from "../extension-loader/extension-loader.inje
|
||||
import isCompatibleExtensionInjectable from "./is-compatible-extension/is-compatible-extension.injectable";
|
||||
import extensionsStoreInjectable from "../extensions-store/extensions-store.injectable";
|
||||
import extensionInstallationStateStoreInjectable from "../extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable";
|
||||
import installExtensionInjectable from "../install-extension/install-extension.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "../install-extension/extension-package-root-directory.injectable";
|
||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||
|
||||
@ -7,7 +7,7 @@ import type { FSWatcher } from "chokidar";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import extensionDiscoveryInjectable from "../extension-discovery/extension-discovery.injectable";
|
||||
import type { ExtensionDiscovery } from "../extension-discovery/extension-discovery";
|
||||
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
|
||||
import installExtensionInjectable from "../install-extension/install-extension.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import { delay } from "../../renderer/utils";
|
||||
import { observable, runInAction, when } from "mobx";
|
||||
|
||||
@ -1,21 +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 pathToNpmCliInjectable from "../../common/app-paths/path-to-npm-cli.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import { ExtensionInstaller } from "./extension-installer";
|
||||
import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory/extension-package-root-directory.injectable";
|
||||
|
||||
const extensionInstallerInjectable = getInjectable({
|
||||
id: "extension-installer",
|
||||
|
||||
instantiate: (di) => new ExtensionInstaller({
|
||||
extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
pathToNpmCli: di.inject(pathToNpmCliInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export default extensionInstallerInjectable;
|
||||
@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import AwaitLock from "await-lock";
|
||||
import child_process from "child_process";
|
||||
import type { Logger } from "../../common/logger";
|
||||
|
||||
const logModule = "[EXTENSION-INSTALLER]";
|
||||
|
||||
interface Dependencies {
|
||||
readonly extensionPackageRootDirectory: string;
|
||||
readonly logger: Logger;
|
||||
readonly pathToNpmCli: string;
|
||||
}
|
||||
|
||||
const baseNpmInstallArgs = [
|
||||
"install",
|
||||
"--audit=false",
|
||||
"--fund=false",
|
||||
// NOTE: we do not omit the `optional` dependencies because that is how we specify the non-bundled extensions
|
||||
"--omit=dev",
|
||||
"--omit=peer",
|
||||
"--prefer-offline",
|
||||
];
|
||||
|
||||
/**
|
||||
* Installs dependencies for extensions
|
||||
*/
|
||||
export class ExtensionInstaller {
|
||||
private readonly installLock = new AwaitLock();
|
||||
|
||||
constructor(private readonly dependencies: Dependencies) {}
|
||||
|
||||
/**
|
||||
* Install single package using npm
|
||||
*/
|
||||
installPackage = async (name: string): Promise<void> => {
|
||||
// Mutual exclusion to install packages in sequence
|
||||
await this.installLock.acquireAsync();
|
||||
|
||||
try {
|
||||
this.dependencies.logger.info(`${logModule} installing package from ${name} to ${this.dependencies.extensionPackageRootDirectory}`);
|
||||
await this.npm(...baseNpmInstallArgs, name);
|
||||
this.dependencies.logger.info(`${logModule} package ${name} installed to ${this.dependencies.extensionPackageRootDirectory}`);
|
||||
} finally {
|
||||
this.installLock.release();
|
||||
}
|
||||
};
|
||||
|
||||
private npm(...args: string[]): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = child_process.fork(this.dependencies.pathToNpmCli, args, {
|
||||
cwd: this.dependencies.extensionPackageRootDirectory,
|
||||
silent: true,
|
||||
env: {},
|
||||
});
|
||||
let stderr = "";
|
||||
|
||||
child.stderr?.on("data", data => {
|
||||
stderr += String(data);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(stderr));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
child.on("error", error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,13 +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 extensionInstallerInjectable from "../extension-installer.injectable";
|
||||
|
||||
const installExtensionInjectable = getInjectable({
|
||||
id: "install-extension",
|
||||
instantiate: (di) => di.inject(extensionInstallerInjectable).installPackage,
|
||||
});
|
||||
|
||||
export default installExtensionInjectable;
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
const extensionPackageRootDirectoryInjectable = getInjectable({
|
||||
id: "extension-package-root-directory",
|
||||
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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 { fork } from "child_process";
|
||||
import AwaitLock from "await-lock";
|
||||
import pathToNpmCliInjectable from "../../common/app-paths/path-to-npm-cli.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory.injectable";
|
||||
import prefixedLoggerInjectable from "../../common/logger/prefixed-logger.injectable";
|
||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||
import joinPathsInjectable from "../../common/path/join-paths.injectable";
|
||||
import type { PackageJson } from "../common-api";
|
||||
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
|
||||
import { once } from "lodash";
|
||||
import { isErrnoException } from "../../common/utils";
|
||||
|
||||
const baseNpmInstallArgs = [
|
||||
"install",
|
||||
"--save-optional",
|
||||
"--audit=false",
|
||||
"--fund=false",
|
||||
// NOTE: we do not omit the `optional` dependencies because that is how we specify the non-bundled extensions
|
||||
"--omit=dev",
|
||||
"--omit=peer",
|
||||
"--prefer-offline",
|
||||
];
|
||||
|
||||
export type InstallExtension = (name: string) => Promise<void>;
|
||||
|
||||
const installExtensionInjectable = getInjectable({
|
||||
id: "install-extension",
|
||||
instantiate: (di): InstallExtension => {
|
||||
const pathToNpmCli = di.inject(pathToNpmCliInjectable);
|
||||
const extensionPackageRootDirectory = di.inject(extensionPackageRootDirectoryInjectable);
|
||||
const readJsonFile = di.inject(readJsonFileInjectable);
|
||||
const writeJsonFile = di.inject(writeJsonFileInjectable);
|
||||
const joinPaths = di.inject(joinPathsInjectable);
|
||||
const logger = di.inject(prefixedLoggerInjectable, "EXTENSION-INSTALLER");
|
||||
|
||||
const forkNpm = (...args: string[]) => new Promise<void>((resolve, reject) => {
|
||||
const child = fork(pathToNpmCli, args, {
|
||||
cwd: extensionPackageRootDirectory,
|
||||
silent: true,
|
||||
env: {},
|
||||
});
|
||||
let stderr = "";
|
||||
|
||||
child.stderr?.on("data", data => {
|
||||
stderr += String(data);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(stderr));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
child.on("error", error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
const packageJsonPath = joinPaths(extensionPackageRootDirectory, "package.json");
|
||||
|
||||
/**
|
||||
* NOTES:
|
||||
* - We have to keep the `package.json` because `npm install` removes files from `node_modules`
|
||||
* if they are no longer in the `package.json`
|
||||
* - In v6.2.X we saved bundled extensions as `"dependencies"` and external extensions as
|
||||
* `"optionalDependencies"` at startup. This was done because `"optionalDependencies"` can
|
||||
* fail to install and that is OK.
|
||||
* - We continue to maintain this behavior here by only installing new dependencies as
|
||||
* `"optionalDependencies"`
|
||||
*/
|
||||
const fixupPackageJson = once(async () => {
|
||||
try {
|
||||
const packageJson = await readJsonFile(packageJsonPath) as PackageJson;
|
||||
|
||||
delete packageJson.dependencies;
|
||||
|
||||
await writeJsonFile(packageJsonPath, packageJson);
|
||||
} catch (error) {
|
||||
if (isErrnoException(error) && error.code === "ENOENT") {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
const installLock = new AwaitLock();
|
||||
|
||||
return async (name) => {
|
||||
await installLock.acquireAsync();
|
||||
await fixupPackageJson();
|
||||
|
||||
try {
|
||||
logger.info(`installing package for extension "${name}"`);
|
||||
await forkNpm(...baseNpmInstallArgs, name);
|
||||
logger.info(`installed package for extension "${name}"`);
|
||||
} finally {
|
||||
installLock.release();
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default installExtensionInjectable;
|
||||
@ -3,16 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import {
|
||||
Environments,
|
||||
getEnvironmentSpecificLegacyGlobalDiForExtensionApi,
|
||||
} from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import navigateInjectable from "../../main/start-main-application/lens-window/navigate.injectable";
|
||||
|
||||
export function navigate(url: string) {
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.main);
|
||||
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("main");
|
||||
const navigate = di.inject(navigateInjectable);
|
||||
|
||||
return navigate(url);
|
||||
|
||||
@ -2,22 +2,34 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { bundledExtensionInjectionToken } from "../../../../../../common/library";
|
||||
import { object } from "../../../../../../common/utils";
|
||||
import buildSemanticVersionInjectable from "../../../../../../common/vars/build-semantic-version.injectable";
|
||||
|
||||
const aboutBundledExtensionsInjectable = getInjectable({
|
||||
id: "about-bundled-extensions",
|
||||
const specificVersionsInjectable = getInjectable({
|
||||
id: "specific-versions",
|
||||
instantiate: (di) => {
|
||||
const buildSemanticVersion = di.inject(buildSemanticVersionInjectable);
|
||||
const bundledExtensions = di.injectMany(bundledExtensionInjectionToken);
|
||||
const applicationInformation = di.inject(applicationInformationToken);
|
||||
|
||||
if (buildSemanticVersion.get().prerelease[0] === "latest") {
|
||||
return [];
|
||||
}
|
||||
|
||||
return bundledExtensions.map(ext => `${ext.manifest.name}: ${ext.manifest.version}`);
|
||||
const corePackageVersions = object.entries(applicationInformation.dependencies)
|
||||
.filter(([name]) => name.startsWith("@k8slens/"))
|
||||
.map(([name, version]) => `${name}: ${version}`);
|
||||
const bundledExtensionVersions = bundledExtensions
|
||||
.map(ext => `${ext.manifest.name}: ${ext.manifest.version}`);
|
||||
|
||||
return [
|
||||
...corePackageVersions,
|
||||
...bundledExtensionVersions,
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
export default aboutBundledExtensionsInjectable;
|
||||
export default specificVersionsInjectable;
|
||||
|
||||
@ -10,7 +10,7 @@ import productNameInjectable from "../../../../../../common/vars/product-name.in
|
||||
import buildVersionInjectable from "../../../../../../main/vars/build-version/build-version.injectable";
|
||||
import extensionApiVersionInjectable from "../../../../../../common/vars/extension-api-version.injectable";
|
||||
import applicationCopyrightInjectable from "../../../../../../common/vars/application-copyright.injectable";
|
||||
import aboutBundledExtensionsInjectable from "./about-bundled-extensions.injectable";
|
||||
import specificVersionsInjectable from "./about-bundled-extensions.injectable";
|
||||
|
||||
const showAboutInjectable = getInjectable({
|
||||
id: "show-about",
|
||||
@ -23,7 +23,7 @@ const showAboutInjectable = getInjectable({
|
||||
const appName = di.inject(appNameInjectable);
|
||||
const productName = di.inject(productNameInjectable);
|
||||
const applicationCopyright = di.inject(applicationCopyrightInjectable);
|
||||
const aboutBundledExtensions = di.inject(aboutBundledExtensionsInjectable);
|
||||
const specificVersions = di.inject(specificVersionsInjectable);
|
||||
|
||||
return () => {
|
||||
const appInfo = [
|
||||
@ -32,14 +32,26 @@ const showAboutInjectable = getInjectable({
|
||||
`Electron: ${process.versions.electron}`,
|
||||
`Chrome: ${process.versions.chrome}`,
|
||||
`Node: ${process.versions.node}`,
|
||||
...aboutBundledExtensions,
|
||||
applicationCopyright,
|
||||
];
|
||||
|
||||
if (specificVersions.length > 0) {
|
||||
appInfo.push(
|
||||
"",
|
||||
"",
|
||||
...specificVersions,
|
||||
);
|
||||
}
|
||||
|
||||
showMessagePopup(
|
||||
`${isWindows ? " ".repeat(2) : ""}${appName}`,
|
||||
productName,
|
||||
appInfo.join("\r\n"),
|
||||
{
|
||||
textWidth: specificVersions.length > 0
|
||||
? 300
|
||||
: undefined,
|
||||
},
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
@ -22,7 +22,10 @@ const pickHighestAccuracy = (prev: ClusterDetectionResult, curr: ClusterDetectio
|
||||
|
||||
const detectMetadataWithFor = (cluster: Cluster) => async (clusterMetadataDetector: ClusterMetadataDetector) => {
|
||||
try {
|
||||
return await clusterMetadataDetector.detect(cluster);
|
||||
return {
|
||||
key: clusterMetadataDetector.key,
|
||||
result: await clusterMetadataDetector.detect(cluster),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@ -39,7 +42,12 @@ const detectClusterMetadataInjectable = getInjectable({
|
||||
filter(isDefined),
|
||||
(arg) => groupBy(arg, "key"),
|
||||
(arg) => object.entries(arg),
|
||||
map(([ key, results ]) => [key, reduce(results, pickHighestAccuracy)] as const),
|
||||
map(([ key, detectionResults ]) => {
|
||||
const results = detectionResults.map(({ result }) => result as ClusterDetectionResult);
|
||||
const highestAccuracyResult = reduce(results, pickHighestAccuracy)?.value;
|
||||
|
||||
return [key, highestAccuracyResult] as const;
|
||||
}),
|
||||
filter(hasDefinedTupleValue),
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AppPaths } from "../../common/app-paths/app-path-injection-token";
|
||||
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||
import type { Cluster } from "../../common/cluster/cluster";
|
||||
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
|
||||
import { getDiForUnitTesting } from "../getDiForUnitTesting";
|
||||
import clusterDistributionDetectorInjectable from "./cluster-distribution-detector.injectable";
|
||||
import clusterIdDetectorFactoryInjectable from "./cluster-id-detector.injectable";
|
||||
import clusterLastSeenDetectorInjectable from "./cluster-last-seen-detector.injectable";
|
||||
import clusterNodeCountDetectorInjectable from "./cluster-nodes-count-detector.injectable";
|
||||
import type { DetectClusterMetadata } from "./detect-cluster-metadata.injectable";
|
||||
import detectClusterMetadataInjectable from "./detect-cluster-metadata.injectable";
|
||||
import requestClusterVersionInjectable from "./request-cluster-version.injectable";
|
||||
|
||||
describe("detect-cluster-metadata", () => {
|
||||
let detectClusterMetadata: DetectClusterMetadata;
|
||||
|
||||
let cluster: Cluster;
|
||||
|
||||
beforeEach(async () => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
const lastSeenDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-time-stamp", accuracy: 100 }));
|
||||
const nodeCountDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: 42, accuracy: 100 }));
|
||||
const clusterIdDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-cluster-id", accuracy: 100 }));
|
||||
const distributionDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-distribution", accuracy: 100 }));
|
||||
|
||||
di.override(clusterLastSeenDetectorInjectable, () => {
|
||||
return {
|
||||
key: ClusterMetadataKey.LAST_SEEN,
|
||||
detect: lastSeenDetectMock,
|
||||
};
|
||||
});
|
||||
|
||||
di.override(requestClusterVersionInjectable, () => () => Promise.resolve("some-cluster-version"));
|
||||
|
||||
di.override(clusterNodeCountDetectorInjectable, () => ({
|
||||
key: ClusterMetadataKey.NODES_COUNT,
|
||||
detect: nodeCountDetectMock,
|
||||
}));
|
||||
|
||||
di.override(clusterIdDetectorFactoryInjectable, () => ({
|
||||
key: ClusterMetadataKey.CLUSTER_ID,
|
||||
detect: clusterIdDetectMock,
|
||||
}));
|
||||
|
||||
di.override(clusterDistributionDetectorInjectable, () => ({
|
||||
key: ClusterMetadataKey.DISTRIBUTION,
|
||||
detect: distributionDetectMock,
|
||||
}));
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(appPathsStateInjectable, () => ({
|
||||
get: () => ({} as AppPaths),
|
||||
set: () => {},
|
||||
}));
|
||||
|
||||
detectClusterMetadata = di.inject(detectClusterMetadataInjectable);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
cluster = createCluster({
|
||||
id: "some-id",
|
||||
contextName: "some-context",
|
||||
kubeConfigPath: "minikube-config.yml",
|
||||
}, {
|
||||
clusterServerUrl: "foo",
|
||||
});
|
||||
});
|
||||
|
||||
it("given some cluster, last seen time stamp is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.lastSeen).toEqual("some-time-stamp");
|
||||
});
|
||||
|
||||
it("given some cluster, cluster version is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.version).toEqual("some-cluster-version");
|
||||
});
|
||||
|
||||
it("given some cluster, id is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.id).toEqual("some-cluster-id");
|
||||
});
|
||||
|
||||
it("given some cluster, node count is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.nodes).toEqual(42);
|
||||
});
|
||||
|
||||
it("given some cluster, distribution is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.distribution).toEqual("some-distribution");
|
||||
});
|
||||
});
|
||||
@ -3,20 +3,17 @@
|
||||
* 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 { runInAction } from "mobx";
|
||||
import type { CreateApplication } from "../common/create-app";
|
||||
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
|
||||
import { getDi } from "./getDi";
|
||||
import { registerInjectables } from "./register-injectables";
|
||||
import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable";
|
||||
|
||||
interface AppConfig {
|
||||
di: DiContainer;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export function createApp(conf: AppConfig) {
|
||||
const { di, mode } = conf;
|
||||
export const createApplication: CreateApplication = (config) => {
|
||||
const { mode } = config;
|
||||
const di = getDi();
|
||||
|
||||
runInAction(() => {
|
||||
di.register(getInjectable({
|
||||
@ -28,9 +25,8 @@ export function createApp(conf: AppConfig) {
|
||||
registerInjectables(di);
|
||||
});
|
||||
|
||||
const startMainApplication = di.inject(startMainApplicationInjectable);
|
||||
|
||||
return {
|
||||
start: () => startMainApplication(),
|
||||
start: di.inject(startMainApplicationInjectable),
|
||||
di,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,7 +5,11 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronDialogInjectable from "./electron-dialog.injectable";
|
||||
|
||||
export type ShowMessagePopup = (title: string, message: string, detail: string) => void;
|
||||
export interface ShowMessagePopupOptions {
|
||||
textWidth?: number;
|
||||
}
|
||||
|
||||
export type ShowMessagePopup = (title: string, message: string, detail: string, options?: ShowMessagePopupOptions) => void;
|
||||
|
||||
const showMessagePopupInjectable = getInjectable({
|
||||
id: "show-message-popup",
|
||||
@ -13,13 +17,14 @@ const showMessagePopupInjectable = getInjectable({
|
||||
instantiate: (di): ShowMessagePopup => {
|
||||
const dialog = di.inject(electronDialogInjectable);
|
||||
|
||||
return async (title, message, detail) => {
|
||||
return async (title, message, detail, options = {}) => {
|
||||
await dialog.showMessageBox({
|
||||
title,
|
||||
message,
|
||||
detail,
|
||||
type: "info",
|
||||
buttons: ["Close"],
|
||||
...options,
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
@ -3,5 +3,15 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
export const getDi = () => createContainer("main");
|
||||
export const getDi = () => {
|
||||
const environment = "main";
|
||||
const di = createContainer(environment);
|
||||
|
||||
registerMobX(di);
|
||||
setLegacyGlobalDiForExtensionApi(di, environment);
|
||||
|
||||
return di;
|
||||
};
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
*/
|
||||
|
||||
import { chunk } from "lodash/fp";
|
||||
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
||||
import { createContainer, isInjectable, getInjectable } from "@ogre-tools/injectable";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { isInjectable } from "@ogre-tools/injectable";
|
||||
import spawnInjectable from "./child-process/spawn.injectable";
|
||||
import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable";
|
||||
import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable";
|
||||
@ -25,46 +24,30 @@ import electronQuitAndInstallUpdateInjectable from "./electron-app/features/elec
|
||||
import electronUpdaterIsActiveInjectable from "./electron-app/features/electron-updater-is-active.injectable";
|
||||
import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-quit.injectable";
|
||||
import waitUntilBundledExtensionsAreLoadedInjectable from "./start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
|
||||
import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable";
|
||||
import type { GlobalOverride } from "../common/test-utils/get-global-override";
|
||||
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
|
||||
import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes";
|
||||
import { applicationInformationFakeInjectable } from "../common/vars/application-information-fake-injectable";
|
||||
import { getDi } from "./getDi";
|
||||
|
||||
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
||||
const {
|
||||
doGeneralOverrides = false,
|
||||
} = opts;
|
||||
|
||||
const di = createContainer("main");
|
||||
|
||||
di.register(getInjectable({
|
||||
id: "node-env",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.main);
|
||||
const di = getDi();
|
||||
|
||||
di.preventSideEffects();
|
||||
|
||||
const injectables = (
|
||||
global.injectablePaths.main.paths
|
||||
runInAction(() => {
|
||||
const injectables = global.injectablePaths.main.paths
|
||||
.map(path => require(path))
|
||||
.flatMap(Object.values)
|
||||
.filter(isInjectable)
|
||||
) as Injectable<any, any, any>[];
|
||||
.filter(isInjectable);
|
||||
|
||||
registerMobX(di);
|
||||
|
||||
runInAction(() => {
|
||||
di.register(applicationInformationFakeInjectable);
|
||||
|
||||
chunk(100)(injectables).forEach(chunkInjectables => {
|
||||
di.register(...chunkInjectables);
|
||||
});
|
||||
for (const block of chunk(100)(injectables)) {
|
||||
di.register(...block);
|
||||
}
|
||||
});
|
||||
|
||||
if (doGeneralOverrides) {
|
||||
|
||||
@ -8,7 +8,8 @@ export { afterApplicationIsLoadedInjectionToken } from "./start-main-application
|
||||
export { beforeApplicationIsLoadingInjectionToken } from "./start-main-application/runnable-tokens/before-application-is-loading-injection-token";
|
||||
export { beforeElectronIsReadyInjectionToken } from "./start-main-application/runnable-tokens/before-electron-is-ready-injection-token";
|
||||
export { onLoadOfApplicationInjectionToken } from "./start-main-application/runnable-tokens/on-load-of-application-injection-token";
|
||||
export { createApp } from "./create-app";
|
||||
export { createApplication } from "./create-app";
|
||||
export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app";
|
||||
export * as Mobx from "mobx";
|
||||
export * as mainExtensionApi from "../extensions/main-api";
|
||||
export * as commonExtensionApi from "../extensions/common-api";
|
||||
|
||||
@ -4,16 +4,10 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { runInAction } from "mobx";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
export function registerInjectables(di: DiContainer) {
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.main);
|
||||
|
||||
runInAction(() => {
|
||||
registerMobX(di);
|
||||
|
||||
autoRegister({
|
||||
di,
|
||||
targetModule: module,
|
||||
@ -25,6 +19,4 @@ export function registerInjectables(di: DiContainer) {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
return di;
|
||||
}
|
||||
|
||||
@ -5,19 +5,16 @@
|
||||
import "./components/app.scss";
|
||||
|
||||
import { bootstrap } from "./bootstrap";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
|
||||
import { runInAction } from "mobx";
|
||||
import { registerInjectables } from "./register-injectables";
|
||||
import type { CreateApplication } from "../common/create-app";
|
||||
import { getDi } from "./getDi";
|
||||
|
||||
interface AppConfig {
|
||||
di: DiContainer;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export function createApp(conf: AppConfig) {
|
||||
const { di, mode } = conf;
|
||||
export const createApplication: CreateApplication = (config) => {
|
||||
const { mode } = config;
|
||||
const di = getDi();
|
||||
|
||||
runInAction(() => {
|
||||
di.register(getInjectable({
|
||||
@ -25,10 +22,12 @@ export function createApp(conf: AppConfig) {
|
||||
instantiate: () => mode,
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
|
||||
registerInjectables(di);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
start: () => bootstrap(di),
|
||||
di,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -4,5 +4,17 @@
|
||||
*/
|
||||
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { registerInjectableReact } from "@ogre-tools/injectable-react";
|
||||
import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
export const getDi = () => createContainer("renderer");
|
||||
export const getDi = () => {
|
||||
const environment = "renderer";
|
||||
const di = createContainer(environment);
|
||||
|
||||
registerMobX(di);
|
||||
registerInjectableReact(di);
|
||||
setLegacyGlobalDiForExtensionApi(di, environment);
|
||||
|
||||
return di;
|
||||
};
|
||||
|
||||
@ -4,9 +4,7 @@
|
||||
*/
|
||||
|
||||
import { noop, chunk } from "lodash/fp";
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { createContainer, isInjectable, getInjectable } from "@ogre-tools/injectable";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import { 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";
|
||||
@ -14,47 +12,29 @@ import hostedClusterIdInjectable from "./cluster-frame-context/hosted-cluster-id
|
||||
import { runInAction } from "mobx";
|
||||
import requestAnimationFrameInjectable from "./components/animate/request-animation-frame.injectable";
|
||||
import startTopbarStateSyncInjectable from "./components/layout/top-bar/start-state-sync.injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import watchHistoryStateInjectable from "./remote-helpers/watch-history-state.injectable";
|
||||
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
|
||||
import type { GlobalOverride } from "../common/test-utils/get-global-override";
|
||||
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
|
||||
import { applicationInformationFakeInjectable } from "../common/vars/application-information-fake-injectable";
|
||||
import { registerInjectableReact } from "@ogre-tools/injectable-react";
|
||||
import { getDi } from "./getDi";
|
||||
|
||||
export const getDiForUnitTesting = (
|
||||
opts: { doGeneralOverrides?: boolean } = {},
|
||||
) => {
|
||||
const { doGeneralOverrides = false } = opts;
|
||||
|
||||
const di = createContainer("renderer");
|
||||
|
||||
di.register(getInjectable({
|
||||
id: "node-env",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
const di = getDi();
|
||||
|
||||
di.preventSideEffects();
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||
|
||||
const injectables = (
|
||||
global.injectablePaths.renderer.paths
|
||||
runInAction(() => {
|
||||
const injectables = global.injectablePaths.renderer.paths
|
||||
.map(path => require(path))
|
||||
.flatMap(Object.values)
|
||||
.filter(isInjectable)
|
||||
) as Injectable<any, any, any>[];
|
||||
.filter(isInjectable);
|
||||
|
||||
registerMobX(di);
|
||||
registerInjectableReact(di);
|
||||
|
||||
runInAction(() => {
|
||||
di.register(applicationInformationFakeInjectable);
|
||||
|
||||
chunk(100)(injectables).forEach((chunkInjectables) => {
|
||||
di.register(...chunkInjectables);
|
||||
});
|
||||
for (const block of chunk(100)(injectables)) {
|
||||
di.register(...block);
|
||||
}
|
||||
});
|
||||
|
||||
if (doGeneralOverrides) {
|
||||
|
||||
@ -14,4 +14,5 @@ export * as ReactRouter from "react-router";
|
||||
export * as ReactRouterDom from "react-router-dom";
|
||||
export * as rendererExtensionApi from "../extensions/renderer-api";
|
||||
export * as commonExtensionApi from "../extensions/common-api";
|
||||
export { createApp } from "./create-app";
|
||||
export { createApplication } from "./create-app";
|
||||
export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app";
|
||||
|
||||
@ -5,19 +5,10 @@
|
||||
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { registerInjectableReact } from "@ogre-tools/injectable-react";
|
||||
import { runInAction } from "mobx";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
export function registerInjectables(di: DiContainer) {
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||
|
||||
registerMobX(di);
|
||||
registerInjectableReact(di);
|
||||
|
||||
runInAction(() => {
|
||||
|
||||
autoRegister({
|
||||
di,
|
||||
targetModule: module,
|
||||
@ -29,6 +20,4 @@ export function registerInjectables(di: DiContainer) {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
return di;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/ensure-binaries",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "CLI for downloading configured versions of the bundled versions of CLIs",
|
||||
"main": "dist/index.js",
|
||||
"license": "MIT",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "@k8slens/extensions",
|
||||
"productName": "OpenLens extensions",
|
||||
"description": "OpenLens - Open Source Kubernetes IDE: extensions",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"copyright": "© 2022 OpenLens Authors",
|
||||
"license": "MIT",
|
||||
"main": "dist/extension-api.js",
|
||||
@ -26,7 +26,7 @@
|
||||
"prepare:dev": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@k8slens/core": "^6.4.0-beta.13"
|
||||
"@k8slens/core": "^6.5.0-alpha.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.6",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/generate-tray-icons",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "CLI generating tray icons for building a lens-like application",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@k8slens/jest",
|
||||
"private": false,
|
||||
"version": "0.0.1",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Jest configuration and scripts for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@k8slens/typescript",
|
||||
"private": false,
|
||||
"version": "0.0.1",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Typescript configuration for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@k8slens/webpack",
|
||||
"private": false,
|
||||
"version": "0.0.1",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Webpack configurations and scripts for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
@ -25,6 +25,7 @@
|
||||
"dependencies": {
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"css-loader": "^6.7.2",
|
||||
"fork-ts-checker-webpack-plugin": "^7.3.0",
|
||||
"mini-css-extract-plugin": "^2.7.0",
|
||||
"sass-loader": "^13.2.0",
|
||||
"style-loader": "^3.3.1",
|
||||
|
||||
@ -0,0 +1,226 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`get-multi-export-config given maximal package.json, when creating configuration works 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist",
|
||||
},
|
||||
"include": Array [
|
||||
"./index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./some-entrypoint/index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./some-entrypoint/index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist/some-entrypoint",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist/some-entrypoint",
|
||||
},
|
||||
"include": Array [
|
||||
"./some-entrypoint/index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./some-other-entrypoint/index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
Object {
|
||||
"test": /\\\\\\.s\\?css\\$/,
|
||||
"use": Array [
|
||||
Object {
|
||||
"some": "miniCssExtractPluginLoader",
|
||||
},
|
||||
Object {
|
||||
"loader": "css-loader",
|
||||
"options": Object {
|
||||
"modules": Object {
|
||||
"auto": /\\\\\\.module\\\\\\./i,
|
||||
"localIdentName": "[name]__[local]--[hash:base64:5]",
|
||||
"mode": "local",
|
||||
},
|
||||
"sourceMap": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"loader": "sass-loader",
|
||||
"options": Object {
|
||||
"sourceMap": false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./some-other-entrypoint/index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist/some-other-entrypoint",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist/some-other-entrypoint",
|
||||
},
|
||||
"include": Array [
|
||||
"./some-other-entrypoint/index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
MiniCssExtractPlugin {
|
||||
"_sortedModulesCache": WeakMap {},
|
||||
"options": Object {
|
||||
"chunkFilename": "[name].css",
|
||||
"experimentalUseImportModule": undefined,
|
||||
"filename": "[name].css",
|
||||
"ignoreOrder": false,
|
||||
"runtime": true,
|
||||
},
|
||||
"runtimeOptions": Object {
|
||||
"attributes": undefined,
|
||||
"insert": undefined,
|
||||
"linkType": "text/css",
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@ -1,5 +1,5 @@
|
||||
const nodeConfig = require("./node-config");
|
||||
const reactConfig = require("./react-config");
|
||||
const getNodeConfig = require("./get-node-config");
|
||||
const getReactConfigFor = require("./get-react-config");
|
||||
const path = require("path");
|
||||
const {
|
||||
map,
|
||||
@ -14,7 +14,15 @@ const {
|
||||
} = require("lodash/fp");
|
||||
const { pipeline } = require("@ogre-tools/fp");
|
||||
|
||||
module.exports = (packageJson, dependencies = { nodeConfig, reactConfig, joinPath: path.join }) => {
|
||||
module.exports = (
|
||||
packageJson,
|
||||
|
||||
dependencies = {
|
||||
resolvePath: path.resolve,
|
||||
workingDirectory: process.cwd(),
|
||||
getReactConfig: getReactConfigFor()
|
||||
}
|
||||
) => {
|
||||
if (!packageJson.lensMultiExportConfig) {
|
||||
throw new Error(
|
||||
`Tried to get multi export config for package "${packageJson.name}" but configuration is missing.`
|
||||
@ -72,10 +80,13 @@ module.exports = (packageJson, dependencies = { nodeConfig, reactConfig, joinPat
|
||||
);
|
||||
}
|
||||
|
||||
const toExportSpecificWebpackConfig =
|
||||
toExportSpecificWebpackConfigFor(dependencies);
|
||||
|
||||
return pipeline(
|
||||
packageJson.lensMultiExportConfig,
|
||||
toPairs,
|
||||
map(toExportSpecificWebpackConfigFor(dependencies))
|
||||
map(toExportSpecificWebpackConfig)
|
||||
);
|
||||
};
|
||||
|
||||
@ -91,7 +102,11 @@ const toExpectedExport = (externalImportPath) => {
|
||||
return [
|
||||
externalImportPath,
|
||||
{
|
||||
types: `./${posixJoinForPackageJson("./dist", externalImportPath, "index.d.ts")}`,
|
||||
types: `./${posixJoinForPackageJson(
|
||||
"./dist",
|
||||
externalImportPath,
|
||||
"index.d.ts"
|
||||
)}`,
|
||||
|
||||
default: entrypointPath,
|
||||
import: entrypointPath,
|
||||
@ -103,20 +118,19 @@ const toExpectedExport = (externalImportPath) => {
|
||||
const toExportSpecificWebpackConfigFor =
|
||||
(dependencies) =>
|
||||
([externalImportPath, { buildType, entrypoint }]) => {
|
||||
const baseConfig =
|
||||
buildType === "node" ? dependencies.nodeConfig : dependencies.reactConfig;
|
||||
const outputDirectory = dependencies.resolvePath(
|
||||
dependencies.workingDirectory,
|
||||
"dist",
|
||||
externalImportPath
|
||||
);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
name: entrypoint,
|
||||
|
||||
entry: {
|
||||
index: entrypoint,
|
||||
},
|
||||
|
||||
output: {
|
||||
...baseConfig.output,
|
||||
path: dependencies.joinPath(baseConfig.output.path, externalImportPath),
|
||||
},
|
||||
};
|
||||
return buildType === "node"
|
||||
? getNodeConfig({
|
||||
entrypointFilePath: entrypoint,
|
||||
outputDirectory,
|
||||
})
|
||||
: dependencies.getReactConfig({
|
||||
entrypointFilePath: entrypoint,
|
||||
outputDirectory,
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin";
|
||||
import getMultiExportConfig from "./get-multi-export-config";
|
||||
import path from 'path';
|
||||
import path from "path";
|
||||
const getReactConfigFor = require("./get-react-config");
|
||||
|
||||
const joinPathFake = path.posix.join;
|
||||
const resolvePathFake = path.posix.resolve;
|
||||
|
||||
describe("get-multi-export-config", () => {
|
||||
let actual;
|
||||
let configs;
|
||||
let maximalPackageJson;
|
||||
|
||||
beforeEach(() => {
|
||||
@ -51,43 +53,69 @@ describe("get-multi-export-config", () => {
|
||||
};
|
||||
});
|
||||
|
||||
it("given maximal package.json, when creating configuration, works", () => {
|
||||
actual = getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
describe("given maximal package.json, when creating configuration", () => {
|
||||
beforeEach(() => {
|
||||
configs = getMultiExportConfig(maximalPackageJson, {
|
||||
resolvePath: resolvePathFake,
|
||||
workingDirectory: "/some-working-directory",
|
||||
|
||||
getReactConfig: getReactConfigFor({
|
||||
miniCssExtractPluginLoader: { some: "miniCssExtractPluginLoader" },
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
expect(actual).toEqual([
|
||||
it("works", () => {
|
||||
expect(configs).toMatchSnapshot();
|
||||
});
|
||||
|
||||
[
|
||||
{
|
||||
name: "./index.ts",
|
||||
stub: "node",
|
||||
entry: { index: "./index.ts" },
|
||||
output: { some: "value", path: "/some-build-directory" },
|
||||
name: "config for node export in default entrypoint",
|
||||
entrypoint: "./index.ts",
|
||||
outputDirectory: "/some-working-directory/dist",
|
||||
},
|
||||
|
||||
{
|
||||
name: "./some-entrypoint/index.ts",
|
||||
stub: "node",
|
||||
entry: { index: "./some-entrypoint/index.ts" },
|
||||
|
||||
output: {
|
||||
some: "value",
|
||||
path: "/some-build-directory/some-entrypoint",
|
||||
},
|
||||
name: "config for node export in a non-default entrypoint",
|
||||
entrypoint: "./some-entrypoint/index.ts",
|
||||
outputDirectory: "/some-working-directory/dist/some-entrypoint",
|
||||
},
|
||||
|
||||
{
|
||||
name: "./some-other-entrypoint/index.ts",
|
||||
stub: "react",
|
||||
entry: { index: "./some-other-entrypoint/index.ts" },
|
||||
|
||||
output: {
|
||||
some: "other-value",
|
||||
path: "/some-build-directory/some-other-entrypoint",
|
||||
},
|
||||
name: "config for react export in a non-default entrypoint",
|
||||
entrypoint: "./some-other-entrypoint/index.ts",
|
||||
outputDirectory: "/some-working-directory/dist/some-other-entrypoint",
|
||||
},
|
||||
]);
|
||||
].forEach((scenario) => {
|
||||
describe(scenario.name, () => {
|
||||
let config;
|
||||
|
||||
beforeEach(() => {
|
||||
config = configs.find(({ name }) => name === scenario.entrypoint);
|
||||
});
|
||||
|
||||
it("has correct entrypoint", () => {
|
||||
expect(config).toHaveProperty("entry.index", scenario.entrypoint);
|
||||
});
|
||||
|
||||
it("has correct output directory", () => {
|
||||
expect(config).toHaveProperty(
|
||||
"output.path",
|
||||
scenario.outputDirectory
|
||||
);
|
||||
});
|
||||
|
||||
it("has correct declaration directory", () => {
|
||||
expect(
|
||||
config.plugins.find(
|
||||
({ constructor }) => constructor === ForkTsCheckerPlugin
|
||||
)
|
||||
).toHaveProperty(
|
||||
"options.typescript.configOverwrite.compilerOptions.declarationDir",
|
||||
scenario.outputDirectory
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("given maximal package.json but path for entrypoint in exports do not match output, when creating configuration, throws", () => {
|
||||
@ -95,9 +123,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config but exports of package.json for "some-name" did not match exactly:'
|
||||
@ -109,9 +137,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config but exports of package.json for "some-name" did not match exactly:'
|
||||
@ -123,9 +151,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config but exports of package.json for "some-name" did not match exactly:'
|
||||
@ -137,9 +165,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config for package "some-name" but configuration is missing.'
|
||||
@ -151,9 +179,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config for package "some-name" but build types "some-invalid" were not any of "node", "react".'
|
||||
@ -166,9 +194,9 @@ describe("get-multi-export-config", () => {
|
||||
|
||||
expect(() => {
|
||||
getMultiExportConfig(maximalPackageJson, {
|
||||
nodeConfig: nodeConfigStub,
|
||||
reactConfig: reactConfigStub,
|
||||
joinPath: joinPathFake,
|
||||
getNodeConfig: () => nodeConfigStub,
|
||||
getReactConfig: () => reactConfigStub,
|
||||
joinPath: resolvePathFake,
|
||||
});
|
||||
}).toThrow(
|
||||
'Tried to get multi export config for package "some-name" but entrypoint was missing for "./some-entrypoint".'
|
||||
|
||||
78
packages/infrastructure/webpack/src/get-node-config.js
Normal file
78
packages/infrastructure/webpack/src/get-node-config.js
Normal file
@ -0,0 +1,78 @@
|
||||
const ForkTsCheckerPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const nodeExternals = require("webpack-node-externals");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = ({ entrypointFilePath, outputDirectory }) => ({
|
||||
name: entrypointFilePath,
|
||||
entry: { index: entrypointFilePath },
|
||||
target: "node",
|
||||
mode: "production",
|
||||
|
||||
performance: {
|
||||
maxEntrypointSize: 100000,
|
||||
hints: "error",
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx"],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new ForkTsCheckerPlugin({
|
||||
typescript: {
|
||||
mode: "write-dts",
|
||||
|
||||
configOverwrite: {
|
||||
include: [entrypointFilePath],
|
||||
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
declarationDir: outputDirectory,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
output: {
|
||||
path: outputDirectory,
|
||||
|
||||
filename: (pathData) =>
|
||||
pathData.chunk.name === "index"
|
||||
? "index.js"
|
||||
: `${pathData.chunk.name}/index.js`,
|
||||
|
||||
libraryTarget: "commonjs2",
|
||||
},
|
||||
|
||||
externals: [
|
||||
nodeExternals({ modulesFromFile: true }),
|
||||
|
||||
nodeExternals({
|
||||
modulesDir: path.resolve(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"node_modules"
|
||||
),
|
||||
}),
|
||||
],
|
||||
|
||||
externalsPresets: { node: true },
|
||||
|
||||
node: {
|
||||
__dirname: true,
|
||||
__filename: true,
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts(x)?$/,
|
||||
loader: "ts-loader",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
60
packages/infrastructure/webpack/src/get-react-config.js
Normal file
60
packages/infrastructure/webpack/src/get-react-config.js
Normal file
@ -0,0 +1,60 @@
|
||||
const getNodeConfig = require("./get-node-config");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
|
||||
module.exports =
|
||||
({ miniCssExtractPluginLoader = MiniCssExtractPlugin.loader } = {}) =>
|
||||
({ entrypointFilePath, outputDirectory }) => {
|
||||
const nodeConfig = getNodeConfig({
|
||||
entrypointFilePath,
|
||||
outputDirectory,
|
||||
});
|
||||
|
||||
return {
|
||||
...nodeConfig,
|
||||
|
||||
plugins: [
|
||||
...nodeConfig.plugins,
|
||||
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].css",
|
||||
}),
|
||||
],
|
||||
|
||||
module: {
|
||||
...nodeConfig.module,
|
||||
|
||||
rules: [
|
||||
...nodeConfig.module.rules,
|
||||
|
||||
{
|
||||
test: /\.s?css$/,
|
||||
|
||||
use: [
|
||||
miniCssExtractPluginLoader,
|
||||
|
||||
{
|
||||
loader: "css-loader",
|
||||
|
||||
options: {
|
||||
sourceMap: false,
|
||||
|
||||
modules: {
|
||||
auto: /\.module\./i, // https://github.com/webpack-contrib/css-loader#auto
|
||||
mode: "local", // :local(.selector) by default
|
||||
localIdentName: "[name]__[local]--[hash:base64:5]",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
@ -1,68 +1,7 @@
|
||||
const nodeExternals = require("webpack-node-externals");
|
||||
const path = require("path");
|
||||
const getNodeConfig = require("./get-node-config");
|
||||
|
||||
const buildDirectory = path.resolve(process.cwd(), "dist");
|
||||
|
||||
module.exports = {
|
||||
entry: { index: "./index.ts" },
|
||||
target: "node",
|
||||
mode: "production",
|
||||
|
||||
performance: {
|
||||
maxEntrypointSize: 100000,
|
||||
hints: "error",
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx"],
|
||||
},
|
||||
|
||||
output: {
|
||||
path: buildDirectory,
|
||||
|
||||
filename: (pathData) =>
|
||||
pathData.chunk.name === "index"
|
||||
? "index.js"
|
||||
: `${pathData.chunk.name}/index.js`,
|
||||
|
||||
libraryTarget: "commonjs2",
|
||||
},
|
||||
|
||||
externals: [
|
||||
nodeExternals({ modulesFromFile: true }),
|
||||
|
||||
nodeExternals({
|
||||
modulesDir: path.resolve(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"node_modules"
|
||||
),
|
||||
}),
|
||||
],
|
||||
|
||||
externalsPresets: { node: true },
|
||||
|
||||
node: {
|
||||
__dirname: true,
|
||||
__filename: true,
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts(x)?$/,
|
||||
loader: "ts-loader",
|
||||
|
||||
options: {
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
declarationDir: "./dist",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
module.exports = getNodeConfig({
|
||||
entrypointFilePath: "./index.ts",
|
||||
outputDirectory: path.resolve(process.cwd(), "dist"),
|
||||
});
|
||||
|
||||
@ -1,44 +1,7 @@
|
||||
const nodeConfig = require("./node-config");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const path = require("path");
|
||||
const getReactConfig = require("./get-react-config");
|
||||
|
||||
module.exports = {
|
||||
...nodeConfig,
|
||||
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].css",
|
||||
}),
|
||||
],
|
||||
|
||||
module: {
|
||||
...nodeConfig.module,
|
||||
rules: [
|
||||
...nodeConfig.module.rules,
|
||||
|
||||
{
|
||||
test: /\.s?css$/,
|
||||
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
sourceMap: false,
|
||||
modules: {
|
||||
auto: /\.module\./i, // https://github.com/webpack-contrib/css-loader#auto
|
||||
mode: "local", // :local(.selector) by default
|
||||
localIdentName: "[name]__[local]--[hash:base64:5]",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
module.exports = getReactConfig({
|
||||
entrypointFilePath: "./index.ts",
|
||||
outputDirectory: path.resolve(process.cwd(), "dist"),
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/node-fetch",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Node fetch for Lens",
|
||||
"license": "MIT",
|
||||
"private": false,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"productName": "OpenLens",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
@ -195,10 +195,10 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@k8slens/application": "^6.4.0-beta.13",
|
||||
"@k8slens/core": "^6.4.0-beta.13",
|
||||
"@k8slens/ensure-binaries": "^6.4.0-beta.13",
|
||||
"@k8slens/generate-tray-icons": "^6.4.0-beta.13",
|
||||
"@k8slens/application": "^6.5.0-alpha.0",
|
||||
"@k8slens/core": "^6.5.0-alpha.0",
|
||||
"@k8slens/ensure-binaries": "^6.5.0-alpha.0",
|
||||
"@k8slens/generate-tray-icons": "^6.5.0-alpha.0",
|
||||
"@ogre-tools/fp": "^15.1.1",
|
||||
"@ogre-tools/injectable": "^15.1.1",
|
||||
"@ogre-tools/injectable-extension-for-auto-registration": "^15.1.1",
|
||||
@ -208,7 +208,8 @@
|
||||
"rimraf": "^4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@k8slens/node-fetch": "^6.4.0-beta.13",
|
||||
"@electron/rebuild": "^3.2.10",
|
||||
"@k8slens/node-fetch": "^6.5.0-alpha.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||
"@swc/cli": "^0.1.61",
|
||||
"@swc/core": "^1.3.35",
|
||||
@ -272,7 +273,6 @@
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.11.1",
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"@electron/rebuild": "^3.2.10"
|
||||
"xterm-addon-fit": "^0.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,12 +8,9 @@ import { applicationInformationToken } from "@k8slens/application";
|
||||
|
||||
const applicationInformationInjectable = getInjectable({
|
||||
id: "application-information",
|
||||
injectionToken: applicationInformationToken,
|
||||
|
||||
instantiate: () => {
|
||||
const {
|
||||
version,
|
||||
|
||||
config: {
|
||||
bundledHelmVersion,
|
||||
bundledKubectlVersion,
|
||||
@ -22,12 +19,12 @@ const applicationInformationInjectable = getInjectable({
|
||||
sentryDsn,
|
||||
welcomeRoute,
|
||||
},
|
||||
|
||||
productName,
|
||||
build,
|
||||
copyright,
|
||||
description,
|
||||
name,
|
||||
dependencies,
|
||||
} = packageJson;
|
||||
|
||||
return {
|
||||
@ -43,9 +40,11 @@ const applicationInformationInjectable = getInjectable({
|
||||
contentSecurityPolicy,
|
||||
welcomeRoute,
|
||||
updatingIsEnabled: (build as any)?.publish?.length > 0,
|
||||
dependencies,
|
||||
};
|
||||
},
|
||||
causesSideEffects: true,
|
||||
injectionToken: applicationInformationToken,
|
||||
});
|
||||
|
||||
export default applicationInformationInjectable;
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||
import { runInAction } from "mobx";
|
||||
import { createApp, mainExtensionApi as Main, commonExtensionApi as Common } from "@k8slens/core/main";
|
||||
import { createApplication, mainExtensionApi as Main, commonExtensionApi as Common } from "@k8slens/core/main";
|
||||
|
||||
const di = createContainer("main");
|
||||
const app = createApp({
|
||||
di,
|
||||
const app = createApplication({
|
||||
mode: process.env.NODE_ENV || "development"
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
try {
|
||||
autoRegister({
|
||||
di,
|
||||
di: app.di,
|
||||
targetModule: module,
|
||||
getRequireContexts: () => [
|
||||
require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES),
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
import "@k8slens/core/styles";
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import { createApp, rendererExtensionApi as Renderer, commonExtensionApi as Common } from "@k8slens/core/renderer";
|
||||
import { createApplication, rendererExtensionApi as Renderer, commonExtensionApi as Common } from "@k8slens/core/renderer";
|
||||
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
|
||||
|
||||
const di = createContainer("renderer");
|
||||
const app = createApp({
|
||||
di,
|
||||
const app = createApplication({
|
||||
mode: process.env.NODE_ENV || "development"
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
autoRegister({
|
||||
di,
|
||||
di: app.di,
|
||||
targetModule: module,
|
||||
getRequireContexts: () => [
|
||||
require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/release-tool",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Release tool for lens monorepo",
|
||||
"main": "dist/index.mjs",
|
||||
"license": "MIT",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@k8slens/semver",
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "CLI over semver package for picking parts of a version",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@k8slens/application",
|
||||
"private": false,
|
||||
"version": "6.4.0-beta.13",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Package for creating Lens applications",
|
||||
"type": "commonjs",
|
||||
"files": [
|
||||
|
||||
@ -17,6 +17,7 @@ export type ApplicationInformation = {
|
||||
contentSecurityPolicy: string,
|
||||
welcomeRoute: string,
|
||||
updatingIsEnabled: boolean;
|
||||
dependencies: Partial<Record<string, string>>;
|
||||
}
|
||||
|
||||
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
{
|
||||
"name": "@k8slens/feature-core",
|
||||
"private": false,
|
||||
"version": "0.0.1",
|
||||
"version": "6.5.0-alpha.0",
|
||||
"description": "Code that is common to all Features and those registering them.",
|
||||
"type": "commonjs",
|
||||
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user