Merge remote-tracking branch 'origin/master' into issue-3498

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton committed 2023-02-24 11:12:34 -05:00
commit cee32b1838
158 files changed
+39517 -37226

No files matched your search

+3 -3
View File
@@ -24,9 +24,9 @@ jobs:
- name: Generate Extensions API Reference using typedocs - name: Generate Extensions API Reference using typedocs
run: | run: |
yarn install npm install
yarn run build:docs npm run build:docs
- name: Verify that the markdown is valid - name: Verify that the markdown is valid
run: | run: |
yarn run mkdocs:verify npm run mkdocs:verify
+5 -5
View File
@@ -21,9 +21,9 @@ jobs:
- name: Install deps - name: Install deps
run: | run: |
yarn install npm install
sudo apt-get install -y ripgrep sudo apt-get install -y ripgrep
cd packages/bump-version-for-cron && yarn build cd packages/bump-version-for-cron && npm run build
env: env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Bump version - name: Bump version
@@ -85,14 +85,14 @@ jobs:
- name: Build package - name: Build package
shell: bash shell: bash
run: | run: |
yarn install --frozen-lockfile npm ci
yarn run build npm run build
env: env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release to GitHub NPM registry - name: Release to GitHub NPM registry
run: | run: |
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
yarn lerna \ npx lerna \
publish from-package \ publish from-package \
--no-push \ --no-push \
--no-git-tag-version \ --no-git-tag-version \
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Install deps - name: Install deps
run: yarn install run: npm install
- name: Lint - name: Lint
run: yarn run lint run: npm run lint
+5 -5
View File
@@ -34,12 +34,12 @@ jobs:
- name: Generate Extensions API Reference using typedocs - name: Generate Extensions API Reference using typedocs
run: | run: |
yarn install npm install
yarn run build:docs npm run build:docs
- name: Verify that the markdown is valid - name: Verify that the markdown is valid
run: | run: |
yarn run mkdocs:verify npm run mkdocs:verify
build: build:
name: Deploy docs name: Deploy docs
@@ -77,8 +77,8 @@ jobs:
- name: Generate Extensions API Reference using typedocs - name: Generate Extensions API Reference using typedocs
run: | run: |
yarn install --frozen-lockfile npm ci
yarn build:docs npm run build:docs
- name: mkdocs deploy master - name: mkdocs deploy master
if: contains(github.ref, 'refs/heads/master') if: contains(github.ref, 'refs/heads/master')
+2 -2
View File
@@ -37,8 +37,8 @@ jobs:
- name: Generate Extensions API Reference using typedocs - name: Generate Extensions API Reference using typedocs
run: | run: |
yarn install npm install
yarn typedocs-extensions-api npm run typedocs-extensions-api
- name: Checkout master branch from lens - name: Checkout master branch from lens
uses: actions/checkout@v3 uses: actions/checkout@v3
+3 -3
View File
@@ -32,8 +32,8 @@ jobs:
- name: Generate NPM packages - name: Generate NPM packages
run: | run: |
yarn install --frozen-lockfile npm ci
yarn run build npm run build
- name: Publish NPM packages - name: Publish NPM packages
run: | run: |
@@ -41,7 +41,7 @@ jobs:
VERSION=$(cat lerna.json | jq '.version' --raw-output) VERSION=$(cat lerna.json | jq '.version' --raw-output)
echo ${VERSION} echo ${VERSION}
DIST_TAG=$(node packages/semver/dist/index.js --prerelease 0 ${VERSION}) DIST_TAG=$(node packages/semver/dist/index.js --prerelease 0 ${VERSION})
yarn lerna \ npx lerna \
publish from-package \ publish from-package \
--no-push \ --no-push \
--no-git-tag-version \ --no-git-tag-version \
+14 -12
View File
@@ -32,18 +32,20 @@ jobs:
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Get yarn cache directory path - name: Get npm cache directory path
id: yarn-cache-dir-path if: ${{ runner.os != 'Windows' }}
id: npm-cache-dir-path
shell: bash shell: bash
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3 - uses: actions/cache@v3
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) if: ${{ runner.os != 'Windows' }}
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
with: with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }} path: ${{ steps.npm-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-yarn- ${{ runner.os }}-npm-
- uses: nick-fields/retry@v2 - uses: nick-fields/retry@v2
name: Install dependencies name: Install dependencies
@@ -51,9 +53,9 @@ jobs:
timeout_minutes: 20 timeout_minutes: 20
max_attempts: 3 max_attempts: 3
retry_on: error retry_on: error
command: yarn install --frozen-lockfile command: npm ci
- run: yarn run test:unit - run: npm run test:unit
name: Run tests name: Run tests
if: ${{ matrix.type == 'unit' }} if: ${{ matrix.type == 'unit' }}
@@ -64,15 +66,15 @@ jobs:
minikube-version: latest minikube-version: latest
if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }} if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }}
- run: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' yarn run test:integration - run: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' npm run test:integration
name: Run Linux integration tests name: Run Linux integration tests
if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }} if: ${{ runner.os == 'Linux' && matrix.type == 'smoke' }}
- run: yarn run test:integration - run: npm run test:integration
name: Run macOS integration tests name: Run macOS integration tests
shell: bash shell: bash
if: ${{ runner.os == 'macOS' && matrix.type == 'smoke' }} if: ${{ runner.os == 'macOS' && matrix.type == 'smoke' }}
- run: yarn run test:integration - run: npm run test:integration
name: Run Windows integration tests name: Run Windows integration tests
if: ${{ runner.os == 'Windows' && matrix.type == 'smoke' }} if: ${{ runner.os == 'Windows' && matrix.type == 'smoke' }}
+3
View File
@@ -6,3 +6,6 @@ lens.log
docs/extensions/api docs/extensions/api
site/ site/
lerna-debug.log lerna-debug.log
coverage
dist
node_modules
+3 -1
View File
@@ -1 +1,3 @@
engine-strict=true disturl "https://electronjs.org/headers"
target "19.0.4"
runtime "electron"
-3
View File
@@ -1,3 +0,0 @@
--install.check-files true
--install.network-timeout 100000
--publish.access public
+3 -3
View File
@@ -5,15 +5,15 @@ All releases will be made by creating a PR which bumps the version field in the
## Prerequisites ## Prerequisites
- `yarn` - `npm`
- Running `yarn` (to install all dependencies) - Running `npm install`
- `gh` (Github's CLI) with a version at least 2.15.0 - `gh` (Github's CLI) with a version at least 2.15.0
## Steps ## Steps
1. If you are making a minor or major release (or prereleases for one) make sure you are on the `master` branch. 1. If you are making a minor or major release (or prereleases for one) make sure you are on the `master` branch.
1. If you are making a patch release (or a prerelease for one) make sure you are on the `release/v<MAJOR>.<MINOR>` branch. 1. If you are making a patch release (or a prerelease for one) make sure you are on the `release/v<MAJOR>.<MINOR>` branch.
1. Run `yarn create-release-pr <release-type>`. If you are making a subsequent prerelease release, provide the `--check-commits` flag. 1. Run `npm run create-release-pr <release-type>`. If you are making a subsequent prerelease release, provide the `--check-commits` flag.
1. If you are checking the commits, type `y<ENTER>` to pick a commit, and `n<ENTER>` to skip it. You will want to skip the commits that were part of previous prerelease releases. 1. If you are checking the commits, type `y<ENTER>` to pick a commit, and `n<ENTER>` to skip it. You will want to skip the commits that were part of previous prerelease releases.
1. Once the PR is created, approved, and then merged the `Release Open Lens` workflow will create a tag and release for you. 1. Once the PR is created, approved, and then merged the `Release Open Lens` workflow will create a tag and release for you.
1. If you are making a major or minor release, create a `release/v<MAJOR>.<MINOR>` branch and push it to `origin` so that future patch releases can be made from it. 1. If you are making a major or minor release, create a `release/v<MAJOR>.<MINOR>` branch and push it to `origin` so that future patch releases can be made from it.
+4
View File
@@ -0,0 +1,4 @@
const { monorepoRootConfig } = require("@k8slens/jest");
module.exports = monorepoRootConfig(__dirname);
+2 -5
View File
@@ -1,11 +1,8 @@
{ {
"$schema": "node_modules/lerna/schemas/lerna-schema.json", "$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useWorkspaces": false, "useWorkspaces": true,
"packages": [
"packages/*"
],
"version": "6.4.0-beta.13", "version": "6.4.0-beta.13",
"npmClient": "yarn", "npmClient": "npm",
"npmClientArgs": [ "npmClientArgs": [
"--network-timeout=100000" "--network-timeout=100000"
] ]
+34548
View File
File diff suppressed because it is too large. Load diff
+10 -4
View File
@@ -1,7 +1,13 @@
{ {
"name": "lens-monorepo", "name": "lens-monorepo",
"private": true, "private": true,
"workspaces": [
"packages/**/*"
],
"scripts": { "scripts": {
"all:install": "npm install",
"adr:create": "echo \"What is the title?\"; read title; adr new \"$title\"", "adr:create": "echo \"What is the title?\"; read title; adr new \"$title\"",
"adr:change-status": "echo \"Decision number?:\"; read decision; adr status $decision", "adr:change-status": "echo \"Decision number?:\"; read decision; adr status $decision",
"adr:update-readme": "adr update", "adr:update-readme": "adr update",
@@ -16,16 +22,16 @@
"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: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", "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", "test:unit": "lerna run --stream test:unit",
"test:unit:watch": "jest --watch",
"test:integration": "lerna run --stream test:integration", "test:integration": "lerna run --stream test:integration",
"bump-version": "lerna version --no-git-tag-version --no-push", "bump-version": "lerna version --no-git-tag-version --no-push",
"precreate-release-pr": "cd packages/release-tool && yarn run build", "precreate-release-pr": "cd packages/release-tool && npm run build",
"create-release-pr": "node packages/release-tool/dist/index.js", "create-release-pr": "node packages/release-tool/dist/index.js"
"postinstall": "lerna bootstrap --ignore open-lens && lerna bootstrap --scope open-lens --include-dependencies"
}, },
"devDependencies": { "devDependencies": {
"adr": "^1.4.3", "adr": "^1.4.3",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"lerna": "^6.5.0", "lerna": "^6.5.1",
"rimraf": "^4.1.2" "rimraf": "^4.1.2"
} }
} }
@@ -1,2 +0,0 @@
dist/
node_modules/
+1 -1
View File
@@ -48,7 +48,7 @@ try {
}); });
} }
await exec(`yarn run bump-version --yes ${newVersion}`); await exec(`npm run bump-version ${newVersion} -- --yes`);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
process.exit(1); process.exit(1);
-890
View File
@@ -1,890 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@mole-inc/bin-wrapper@^8.0.1":
version "8.0.1"
resolved "https://registry.yarnpkg.com/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz#d7fd0ceb1cfa8a855293a3ed9d7d135f4d442f0e"
integrity sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==
dependencies:
bin-check "^4.1.0"
bin-version-check "^5.0.0"
content-disposition "^0.5.4"
ext-name "^5.0.0"
file-type "^17.1.6"
filenamify "^5.0.2"
got "^11.8.5"
os-filter-obj "^2.0.0"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
dependencies:
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
"@nodelib/fs.walk@^1.2.3":
version "1.2.8"
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
dependencies:
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@sindresorhus/is@^4.0.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
"@swc/cli@^0.1.61":
version "0.1.61"
resolved "https://registry.yarnpkg.com/@swc/cli/-/cli-0.1.61.tgz#202c70644b30e7b5f9c2590045f7fda72920b998"
integrity sha512-HeYMJ+8gKfJzM9xgcZqTpAHJYAJVGSljBSmWRUx2B6UiGraLsLjEcqxITwi6/t6Af+QboBMiQX5Wwll89oPK7g==
dependencies:
"@mole-inc/bin-wrapper" "^8.0.1"
commander "^7.1.0"
fast-glob "^3.2.5"
semver "^7.3.8"
slash "3.0.0"
source-map "^0.7.3"
"@swc/core-darwin-arm64@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.35.tgz#55ff0cc069769ce8bf6562ca0e724fe9c43deb8c"
integrity sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A==
"@swc/core-darwin-x64@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.35.tgz#270543a2aad6ddbc2d8e8d9a0b025bc08cef9a48"
integrity sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw==
"@swc/core-linux-arm-gnueabihf@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.35.tgz#d2c81406202202962c09451ec58e37efacb15c38"
integrity sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A==
"@swc/core-linux-arm64-gnu@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.35.tgz#f4670584fbe71525d919fa06db3ad778cee242e6"
integrity sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA==
"@swc/core-linux-arm64-musl@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.35.tgz#fd116255cca2d8e098637e95f38ae08f95a47db6"
integrity sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg==
"@swc/core-linux-x64-gnu@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.35.tgz#7a0fb187f1e9baa38d05273a7576c4eaf80a96b8"
integrity sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA==
"@swc/core-linux-x64-musl@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.35.tgz#ad2632b9ae0ea2bfd1461f121b324063c3d6755e"
integrity sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg==
"@swc/core-win32-arm64-msvc@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.35.tgz#5761d0f6efd9affa5571104f1a1951b8b530ec45"
integrity sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA==
"@swc/core-win32-ia32-msvc@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.35.tgz#53ebcf1a6abb0e5152c17da3871d695dfdc07338"
integrity sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q==
"@swc/core-win32-x64-msvc@1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.35.tgz#186170a7f33d1a08ce00800baf293e6d114659a9"
integrity sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg==
"@swc/core@^1.3.35":
version "1.3.35"
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.35.tgz#a96fa52651e56dc00af7b0b83750be33e151bfa8"
integrity sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w==
optionalDependencies:
"@swc/core-darwin-arm64" "1.3.35"
"@swc/core-darwin-x64" "1.3.35"
"@swc/core-linux-arm-gnueabihf" "1.3.35"
"@swc/core-linux-arm64-gnu" "1.3.35"
"@swc/core-linux-arm64-musl" "1.3.35"
"@swc/core-linux-x64-gnu" "1.3.35"
"@swc/core-linux-x64-musl" "1.3.35"
"@swc/core-win32-arm64-msvc" "1.3.35"
"@swc/core-win32-ia32-msvc" "1.3.35"
"@swc/core-win32-x64-msvc" "1.3.35"
"@szmarczak/http-timer@^4.0.5":
version "4.0.6"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
dependencies:
defer-to-connect "^2.0.0"
"@tokenizer/token@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
"@types/cacheable-request@^6.0.1":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==
dependencies:
"@types/http-cache-semantics" "*"
"@types/keyv" "^3.1.4"
"@types/node" "*"
"@types/responselike" "^1.0.0"
"@types/http-cache-semantics@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
"@types/keyv@^3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==
dependencies:
"@types/node" "*"
"@types/node@*":
version "18.13.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850"
integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==
"@types/node@^16.18.11":
version "16.18.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.12.tgz#e3bfea80e31523fde4292a6118f19ffa24fd6f65"
integrity sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==
"@types/responselike@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
dependencies:
"@types/node" "*"
"@types/semver@^7.3.13":
version "7.3.13"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91"
integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
arch@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
arg@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
bin-check@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49"
integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==
dependencies:
execa "^0.7.0"
executable "^4.1.0"
bin-version-check@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-5.0.0.tgz#958de30174d3fcedadbfc52f89f37bca62594877"
integrity sha512-Q3FMQnS5eZmrBGqmDXLs4dbAn/f+52voP6ykJYmweSA60t6DyH4UTSwZhtbK5UH+LBoWvDljILUQMLRUtsynsA==
dependencies:
bin-version "^6.0.0"
semver "^7.3.5"
semver-truncate "^2.0.0"
bin-version@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-6.0.0.tgz#08ecbe5fc87898b441425e145f9e105064d00315"
integrity sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==
dependencies:
execa "^5.0.0"
find-versions "^5.0.0"
braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
cacheable-request@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27"
integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==
dependencies:
clone-response "^1.0.2"
get-stream "^5.1.0"
http-cache-semantics "^4.0.0"
keyv "^4.0.0"
lowercase-keys "^2.0.0"
normalize-url "^6.0.1"
responselike "^2.0.0"
clone-response@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3"
integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==
dependencies:
mimic-response "^1.0.0"
commander@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
content-disposition@^0.5.4:
version "0.5.4"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
dependencies:
safe-buffer "5.2.1"
cross-spawn@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==
dependencies:
lru-cache "^4.0.1"
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"
defer-to-connect@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
escape-string-regexp@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
executable@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
dependencies:
pify "^2.2.0"
ext-list@^2.0.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37"
integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==
dependencies:
mime-db "^1.28.0"
ext-name@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6"
integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==
dependencies:
ext-list "^2.0.0"
sort-keys-length "^1.0.0"
fast-glob@^3.2.5:
version "3.2.12"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
glob-parent "^5.1.2"
merge2 "^1.3.0"
micromatch "^4.0.4"
fastq@^1.6.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
dependencies:
reusify "^1.0.4"
file-type@^17.1.6:
version "17.1.6"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-17.1.6.tgz#18669e0577a4849ef6e73a41f8bdf1ab5ae21023"
integrity sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==
dependencies:
readable-web-to-node-stream "^3.0.2"
strtok3 "^7.0.0-alpha.9"
token-types "^5.0.0-alpha.2"
filename-reserved-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz#3d5dd6d4e2d73a3fed2ebc4cd0b3448869a081f7"
integrity sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==
filenamify@^5.0.2:
version "5.1.1"
resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-5.1.1.tgz#a1ccc5ae678a5e34f578afcb9b72898264d166d2"
integrity sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==
dependencies:
filename-reserved-regex "^3.0.0"
strip-outer "^2.0.0"
trim-repeated "^2.0.0"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
find-versions@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-5.1.0.tgz#973f6739ce20f5e439a27eba8542a4b236c8e685"
integrity sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==
dependencies:
semver-regex "^4.0.5"
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
dependencies:
pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
glob-parent@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
got@^11.8.5:
version "11.8.6"
resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
dependencies:
"@sindresorhus/is" "^4.0.0"
"@szmarczak/http-timer" "^4.0.5"
"@types/cacheable-request" "^6.0.1"
"@types/responselike" "^1.0.0"
cacheable-lookup "^5.0.3"
cacheable-request "^7.0.2"
decompress-response "^6.0.0"
http2-wrapper "^1.0.0-beta.5.2"
lowercase-keys "^2.0.0"
p-cancelable "^2.0.0"
responselike "^2.0.0"
http-cache-semantics@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
http2-wrapper@^1.0.0-beta.5.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
dependencies:
quick-lru "^5.1.1"
resolve-alpn "^1.0.0"
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
inherits@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-glob@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
keyv@^4.0.0:
version "4.5.2"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56"
integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==
dependencies:
json-buffer "3.0.1"
lowercase-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
lru-cache@^4.0.1:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
merge2@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micromatch@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
dependencies:
braces "^3.0.2"
picomatch "^2.3.1"
mime-db@^1.28.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-response@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
normalize-url@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
dependencies:
path-key "^2.0.0"
npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
dependencies:
path-key "^3.0.0"
once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
os-filter-obj@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16"
integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==
dependencies:
arch "^2.1.0"
p-cancelable@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
path-key@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
path-key@^3.0.0, path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
peek-readable@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec"
integrity sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==
picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pify@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
quick-lru@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-web-to-node-stream@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb"
integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==
dependencies:
readable-stream "^3.6.0"
resolve-alpn@^1.0.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
responselike@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc"
integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==
dependencies:
lowercase-keys "^2.0.0"
reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rimraf@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.1.2.tgz#20dfbc98083bdfaa28b01183162885ef213dbf7c"
integrity sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
dependencies:
queue-microtask "^1.2.2"
safe-buffer@5.2.1, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
semver-regex@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-4.0.5.tgz#fbfa36c7ba70461311f5debcb3928821eb4f9180"
integrity sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==
semver-truncate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-2.0.0.tgz#cce4c0af36dbd97e898b821be870d17fbfb67f56"
integrity sha512-Rh266MLDYNeML5h90ttdMwfXe1+Nc4LAWd9X1KdJe8pPHP4kFmvLZALtsMNHNdvTyQygbEC0D59sIz47DIaq8w==
dependencies:
semver "^6.0.0"
semver@^6.0.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.3.5, semver@^7.3.8:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
dependencies:
shebang-regex "^1.0.0"
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
signal-exit@^3.0.0, signal-exit@^3.0.3:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
slash@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
sort-keys-length@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
integrity sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==
dependencies:
sort-keys "^1.0.0"
sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
integrity sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==
dependencies:
is-plain-obj "^1.0.0"
source-map@^0.7.3:
version "0.7.4"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
strip-final-newline@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-outer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-2.0.0.tgz#c45c724ed9b1ff6be5f660503791404f4714084b"
integrity sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==
strtok3@^7.0.0-alpha.9:
version "7.0.0"
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0.tgz#868c428b4ade64a8fd8fee7364256001c1a4cbe5"
integrity sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==
dependencies:
"@tokenizer/token" "^0.3.0"
peek-readable "^5.0.0"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
token-types@^5.0.0-alpha.2:
version "5.0.1"
resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.1.tgz#aa9d9e6b23c420a675e55413b180635b86a093b4"
integrity sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==
dependencies:
"@tokenizer/token" "^0.3.0"
ieee754 "^1.2.1"
trim-repeated@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-2.0.0.tgz#5d60556d6d40d9461b7c7e06c3ac20b6b1d50090"
integrity sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==
dependencies:
escape-string-regexp "^5.0.0"
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-2
View File
@@ -1,5 +1,3 @@
static/build/ static/build/
build/webpack/ build/webpack/
binaries/ binaries/
dist/
node_modules/
-3
View File
@@ -1,3 +0,0 @@
disturl "https://electronjs.org/headers"
target "19.0.4"
runtime "electron"
-27
View File
@@ -1,27 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
const { notarize } = require("electron-notarize");
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin") {
return;
}
if (!process.env.APPLEID || !process.env.APPLEIDPASS) {
return;
}
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: process.env.APPBUNDLEID || "io.kontena.lens-app",
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS,
ascProvider:process.env.ASCPROVIDER,
});
};
+15 -15
View File
@@ -50,14 +50,14 @@
"license": "MIT", "license": "MIT",
"author": "OpenLens Authors <info@k8slens.dev>", "author": "OpenLens Authors <info@k8slens.dev>",
"scripts": { "scripts": {
"build": "cross-env NODE_ENV=production yarn run webpack --config webpack/library-bundle.ts --progress", "build": "cross-env NODE_ENV=production webpack --config webpack/library-bundle.ts --progress",
"clean": "rimraf dist static/build", "clean": "rimraf dist static/build",
"prepare:dev": "cross-env NODE_ENV=development yarn run webpack --config webpack/library-bundle.ts --progress", "prepare:dev": "cross-env NODE_ENV=development webpack --config webpack/library-bundle.ts --progress",
"dev": "cross-env NODE_ENV=development yarn run webpack --config webpack/library-bundle.ts --watch", "dev": "cross-env NODE_ENV=development webpack --config webpack/library-bundle.ts --watch",
"test:unit": "jest --testPathIgnorePatterns integration", "test:unit": "jest --testPathIgnorePatterns integration",
"test:watch": "func() { jest ${1} --watch --testPathIgnorePatterns integration; }; func", "test:watch": "func() { jest ${1} --watch --testPathIgnorePatterns integration; }; func",
"lint": "PROD=true yarn run eslint --ext js,ts,tsx --max-warnings=0 .", "lint": "PROD=true eslint --ext js,ts,tsx --max-warnings=0 .",
"lint:fix": "yarn run lint --fix" "lint:fix": "npm run lint --fix"
}, },
"config": { "config": {
"k8sProxyVersion": "0.3.0", "k8sProxyVersion": "0.3.0",
@@ -126,7 +126,7 @@
"dependencies": { "dependencies": {
"@astronautlabs/jsonpath": "^1.1.0", "@astronautlabs/jsonpath": "^1.1.0",
"@hapi/call": "^9.0.1", "@hapi/call": "^9.0.1",
"@hapi/subtext": "^7.0.4", "@hapi/subtext": "^7.1.0",
"@k8slens/node-fetch": "^6.4.0-beta.13", "@k8slens/node-fetch": "^6.4.0-beta.13",
"@kubernetes/client-node": "^0.18.1", "@kubernetes/client-node": "^0.18.1",
"@material-ui/styles": "^4.11.5", "@material-ui/styles": "^4.11.5",
@@ -158,12 +158,12 @@
"hpagent": "^1.2.0", "hpagent": "^1.2.0",
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
"immer": "^9.0.19", "immer": "^9.0.19",
"joi": "^17.7.0", "joi": "^17.7.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"marked": "^4.2.12", "marked": "^4.2.12",
"md5-file": "^5.0.0", "md5-file": "^5.0.0",
"mobx": "^6.7.0", "mobx": "^6.8.0",
"mobx-observable-history": "^2.0.3", "mobx-observable-history": "^2.0.3",
"mobx-react": "^7.6.0", "mobx-react": "^7.6.0",
"mobx-utils": "^6.0.4", "mobx-utils": "^6.0.4",
@@ -192,7 +192,7 @@
"win-ca": "^3.5.0", "win-ca": "^3.5.0",
"winston": "^3.8.2", "winston": "^3.8.2",
"winston-transport-browserconsole": "^1.0.5", "winston-transport-browserconsole": "^1.0.5",
"ws": "^8.12.0", "ws": "^8.12.1",
"xterm-link-provider": "^1.3.1" "xterm-link-provider": "^1.3.1"
}, },
"devDependencies": { "devDependencies": {
@@ -242,7 +242,7 @@
"@types/react-window": "^1.8.5", "@types/react-window": "^1.8.5",
"@types/readable-stream": "^2.3.13", "@types/readable-stream": "^2.3.13",
"@types/semver": "^7.3.13", "@types/semver": "^7.3.13",
"@types/tar": "^6.1.3", "@types/tar": "^6.1.4",
"@types/tcp-port-used": "^1.0.1", "@types/tcp-port-used": "^1.0.1",
"@types/tempy": "^0.3.0", "@types/tempy": "^0.3.0",
"@types/triple-beam": "^1.3.2", "@types/triple-beam": "^1.3.2",
@@ -268,8 +268,7 @@
"dompurify": "^2.4.4", "dompurify": "^2.4.4",
"electron": "^19.1.9", "electron": "^19.1.9",
"electron-builder": "^23.6.0", "electron-builder": "^23.6.0",
"electron-notarize": "^0.3.0", "esbuild": "^0.17.8",
"esbuild": "^0.17.7",
"esbuild-loader": "^2.21.0", "esbuild-loader": "^2.21.0",
"eslint": "^8.33.0", "eslint": "^8.33.0",
"eslint-import-resolver-typescript": "^3.5.3", "eslint-import-resolver-typescript": "^3.5.3",
@@ -310,7 +309,7 @@
"react-table": "^7.8.0", "react-table": "^7.8.0",
"react-window": "^1.8.8", "react-window": "^1.8.8",
"rimraf": "^4.1.2", "rimraf": "^4.1.2",
"sass": "^1.58.0", "sass": "^1.58.2",
"sass-loader": "^12.6.0", "sass-loader": "^12.6.0",
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.2.4",
@@ -318,7 +317,7 @@
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"type-fest": "^2.14.0", "type-fest": "^2.14.0",
"typed-emitter": "^1.4.0", "typed-emitter": "^1.4.0",
"typedoc": "0.23.24", "typedoc": "0.23.25",
"typedoc-plugin-markdown": "^3.13.6", "typedoc-plugin-markdown": "^3.13.6",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"typescript-plugin-css-modules": "^3.4.0", "typescript-plugin-css-modules": "^3.4.0",
@@ -330,6 +329,7 @@
"xterm-addon-fit": "^0.5.0" "xterm-addon-fit": "^0.5.0"
}, },
"peerDependencies": { "peerDependencies": {
"@k8slens/application": "^6.4.0-beta.13",
"@types/byline": "^4.2.33", "@types/byline": "^4.2.33",
"@types/chart.js": "^2.9.36", "@types/chart.js": "^2.9.36",
"@types/color": "^3.0.3", "@types/color": "^3.0.3",
@@ -340,7 +340,7 @@
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5", "@types/react-window": "^1.8.5",
"@types/tar": "^6.1.3", "@types/tar": "^6.1.4",
"@types/tcp-port-used": "^1.0.1", "@types/tcp-port-used": "^1.0.1",
"@types/url-parse": "^1.4.8", "@types/url-parse": "^1.4.8",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
@@ -0,0 +1,20 @@
/**
* 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 replicationControllersRouteInjectable from "./replicationcontrollers-route.injectable";
import { navigateToRouteInjectionToken } from "../../../../navigate-to-route-injection-token";
const navigateToReplicationControllersInjectable = getInjectable({
id: "navigate-to-replicationcontrollers",
instantiate: (di) => {
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
const route = di.inject(replicationControllersRouteInjectable);
return () => navigateToRoute(route);
},
});
export default navigateToReplicationControllersInjectable;
@@ -0,0 +1,24 @@
/**
* 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 { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const replicationControllersRouteInjectable = getInjectable({
id: "replicationcontrollers-route",
instantiate: (di) => ({
path: "/replicationcontrollers",
clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "replicationcontrollers",
group: "", // core
}),
}),
injectionToken: frontEndRouteInjectionToken,
});
export default replicationControllersRouteInjectable;
@@ -2,13 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "../../../vars/application-information-token";
const welcomeRouteConfigInjectable = getInjectable({ const welcomeRouteConfigInjectable = getInjectable({
id: "welcome-route-config", id: "welcome-route-config",
instantiate: (di) => di.inject(applicationInformationToken).config.welcomeRoute, instantiate: (di) => di.inject(applicationInformationToken).welcomeRoute,
}); });
export default welcomeRouteConfigInjectable; export default welcomeRouteConfigInjectable;
@@ -19,6 +19,9 @@ import { KubeObject } from "../kube-object";
import { KubeObjectStore } from "../kube-object.store"; import { KubeObjectStore } from "../kube-object.store";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
// eslint-disable-next-line no-restricted-imports
import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-api";
class TestApi extends KubeApi<KubeObject> { class TestApi extends KubeApi<KubeObject> {
protected async checkPreferredVersion() { protected async checkPreferredVersion() {
return; return;
@@ -54,7 +57,7 @@ describe("ApiManager", () => {
}); });
describe("registerApi", () => { describe("registerApi", () => {
it("re-register store if apiBase changed", async () => { it("re-register store if apiBase changed", () => {
const apiBase = "apis/v1/foo"; const apiBase = "apis/v1/foo";
const fallbackApiBase = "/apis/extensions/v1beta1/foo"; const fallbackApiBase = "/apis/extensions/v1beta1/foo";
const kubeApi = new TestApi({ const kubeApi = new TestApi({
@@ -72,21 +75,48 @@ describe("ApiManager", () => {
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
}, kubeApi); }, kubeApi);
apiManager.registerApi(apiBase, kubeApi); apiManager.registerApi(kubeApi);
// Define to use test api for ingress store // Define to use test api for ingress store
Object.defineProperty(kubeStore, "api", { value: kubeApi }); Object.defineProperty(kubeStore, "api", { value: kubeApi });
apiManager.registerStore(kubeStore, [kubeApi]); apiManager.registerStore(kubeStore);
// Test that store is returned with original apiBase // Test that store is returned with original apiBase
expect(apiManager.getStore(kubeApi)).toBe(kubeStore); expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
// Change apiBase similar as checkPreferredVersion does // Change apiBase similar as checkPreferredVersion does
Object.defineProperty(kubeApi, "apiBase", { value: fallbackApiBase }); Object.defineProperty(kubeApi, "apiBase", { value: fallbackApiBase });
apiManager.registerApi(fallbackApiBase, kubeApi); apiManager.registerApi(kubeApi);
// Test that store is returned with new apiBase // Test that store is returned with new apiBase
expect(apiManager.getStore(kubeApi)).toBe(kubeStore); expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
}); });
}); });
describe("technical tests for autorun", () => {
it("given two extensions register apis with the same apibase, settle into using the second", () => {
const apiBase = "/apis/aquasecurity.github.io/v1alpha1/vulnerabilityreports";
const firstApi = Object.assign(new ExternalKubeApi({
objectConstructor: KubeObject,
apiBase,
kind: "VulnerabilityReport",
}), {
myField: 1,
});
const secondApi = Object.assign(new ExternalKubeApi({
objectConstructor: KubeObject,
apiBase,
kind: "VulnerabilityReport",
}), {
myField: 2,
});
void firstApi;
void secondApi;
expect(apiManager.getApi(apiBase)).toMatchObject({
myField: 2,
});
});
});
}); });
@@ -41,19 +41,22 @@ export class ApiManager {
const apis = chain(this.dependencies.apis.get().values()) const apis = chain(this.dependencies.apis.get().values())
.concat(this.externalApis.values()); .concat(this.externalApis.values());
const removedApis = new Set(this.apis.values()); const removedApis = new Set(this.apis.values());
const newState = new Map(this.apis);
for (const api of apis) { for (const api of apis) {
removedApis.delete(api); removedApis.delete(api);
this.apis.set(api.apiBase, api); newState.set(api.apiBase, api);
} }
for (const api of removedApis) { for (const api of removedApis) {
for (const [apiBase, storedApi] of this.apis) { for (const [apiBase, storedApi] of newState) {
if (storedApi === api) { if (storedApi === api) {
this.apis.delete(apiBase); newState.delete(apiBase);
} }
} }
} }
this.apis.replace(newState);
}); });
} }
@@ -33,6 +33,7 @@ export * from "./pod-metrics.api";
export * from "./pod-security-policy.api"; export * from "./pod-security-policy.api";
export * from "./priority-class.api"; export * from "./priority-class.api";
export * from "./replica-set.api"; export * from "./replica-set.api";
export * from "./replication-controller.api";
export * from "./resource-quota.api"; export * from "./resource-quota.api";
export * from "./role.api"; export * from "./role.api";
export * from "./role-binding.api"; export * from "./role-binding.api";
@@ -37,18 +37,17 @@ export interface RequestMetricsParams {
namespace?: string; namespace?: string;
} }
export interface RequestMetrics { export type RequestMetrics = ReturnType<typeof requestMetricsInjectable["instantiate"]>;
(query: string, params?: RequestMetricsParams): Promise<MetricData>;
(query: string[], params?: RequestMetricsParams): Promise<MetricData[]>;
<Keys extends string>(query: Record<Keys, Partial<Record<string, string>>>, params?: RequestMetricsParams): Promise<Record<Keys, MetricData>>;
}
const requestMetricsInjectable = getInjectable({ const requestMetricsInjectable = getInjectable({
id: "request-metrics", id: "request-metrics",
instantiate: (di) => { instantiate: (di) => {
const apiBase = di.inject(apiBaseInjectable); const apiBase = di.inject(apiBaseInjectable);
return (async (query: object, params: RequestMetricsParams = {}) => { function requestMetrics(query: string, params?: RequestMetricsParams): Promise<MetricData>;
function requestMetrics(query: string[], params?: RequestMetricsParams): Promise<MetricData[]>;
function requestMetrics<Keys extends string>(query: Record<Keys, Partial<Record<string, string>>>, params?: RequestMetricsParams): Promise<Record<Keys, MetricData>>;
async function requestMetrics(query: string | string[] | Partial<Record<string, Partial<Record<string, string>>>>, params: RequestMetricsParams = {}): Promise<MetricData | MetricData[] | Partial<Record<string, MetricData>>> {
const { range = 3600, step = 60, namespace } = params; const { range = 3600, step = 60, namespace } = params;
let { start, end } = params; let { start, end } = params;
@@ -66,7 +65,9 @@ const requestMetricsInjectable = getInjectable({
"kubernetes_namespace": namespace, "kubernetes_namespace": namespace,
}, },
}); });
}) as RequestMetrics; }
return requestMetrics;
}, },
}); });
@@ -0,0 +1,23 @@
/**
* 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 { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
import loggerInjectable from "../../logger.injectable";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
import { ReplicationControllerApi } from "./replication-controller.api";
const replicationControllerApiInjectable = getInjectable({
id: "replication-controller-api",
instantiate: (di) => {
return new ReplicationControllerApi({
logger: di.inject(loggerInjectable),
maybeKubeApi: di.inject(maybeKubeApiInjectable),
});
},
injectionToken: kubeApiInjectionToken,
});
export default replicationControllerApiInjectable;
@@ -0,0 +1,149 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api";
import { KubeApi } from "../kube-api";
import type {
BaseKubeObjectCondition, KubeObjectMetadata,
KubeObjectStatus,
NamespaceScopedMetadata,
} from "../kube-object";
import { KubeObject } from "../kube-object";
import type { PodTemplateSpec } from "./types";
export class ReplicationControllerApi extends KubeApi<ReplicationController> {
constructor(deps: KubeApiDependencies, opts?: DerivedKubeApiOptions) {
super(deps, {
...opts ?? {},
objectConstructor: ReplicationController,
});
}
protected getScaleApiUrl(params: { namespace: string; name: string }) {
return `${this.formatUrlForNotListing(params)}/scale`;
}
getScale(params: { namespace: string; name: string }): Promise<Scale> {
return this.request.get(this.getScaleApiUrl(params));
}
scale(params: { namespace: string; name: string }, replicas: number): Promise<Scale> {
return this.request.patch(this.getScaleApiUrl(params), {
data: {
metadata: params,
spec: {
replicas,
},
},
}, {
headers: {
"content-type": "application/strategic-merge-patch+json",
},
});
}
}
export interface Scale {
apiVersion: "autoscaling/v1";
kind: "Scale";
metadata: KubeObjectMetadata;
spec: {
replicas: number;
};
status: {
replicas: number;
selector: string;
};
}
export interface ReplicationControllerSpec {
/**
* Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available.
* Defaults to 0 (pod will be considered available as soon as it is ready)
*/
minReadySeconds?: number;
/**
* Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified.
* Defaults to 1. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller
*/
replicas?: number;
/**
* Selector is a label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template.
* Label keys and values that must match in order to be controlled by this replication controller, if empty defaulted to labels on Pod template.
* More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
*/
selector?: Record<string, string>;
/**
* Template is the object that describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef.
* More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
*/
template: PodTemplateSpec;
}
export interface ReplicationControllerStatus extends KubeObjectStatus {
/**
* The number of available replicas (ready for at least minReadySeconds) for this replication controller.
*/
availableReplicas: number;
/**
* The number of pods that have labels matching the labels of the pod template of the replication controller.
*/
fullyLabeledReplicas: number;
/**
* ObservedGeneration reflects the generation of the most recently observed replication controller.
*/
observedGeneration: number;
/**
* The number of ready replicas for this replication controller.
*/
readyReplicas: number;
/**
* Replicas is the most recently observed number of replicas.
* More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller
*/
replicas: number;
}
export class ReplicationController extends KubeObject<
NamespaceScopedMetadata,
ReplicationControllerStatus,
ReplicationControllerSpec
> {
static kind = "ReplicationController";
static namespaced = true;
static apiBase = "/api/v1/replicationcontrollers";
getMinReadySeconds(): number {
return this.spec?.minReadySeconds ?? 0;
}
getGeneration() {
return this.status?.observedGeneration;
}
getSelectorLabels(): string[] {
return KubeObject.stringifyLabels(this.spec.selector);
}
getReplicas(): number | undefined {
return this.status?.replicas;
}
getDesiredReplicas(): number {
return this.spec?.replicas ?? 0;
}
getAvailableReplicas(): number | undefined {
return this.status?.availableReplicas;
}
getLabeledReplicas(): number | undefined {
return this.status?.fullyLabeledReplicas;
}
getConditions(): BaseKubeObjectCondition[] {
return this.status?.conditions ?? [];
}
}
-2
View File
@@ -4,6 +4,4 @@
*/ */
// @experimental // @experimental
export { applicationInformationToken } from "./vars/application-information-token";
export type { ApplicationInformation } from "./vars/application-information-token";
export { bundledExtensionInjectionToken } from "../extensions/extension-discovery/bundled-extension-token"; export { bundledExtensionInjectionToken } from "../extensions/extension-discovery/bundled-extension-token";
+6 -1
View File
@@ -6,7 +6,7 @@
export type KubeResource = export type KubeResource =
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" | "leases" | "namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" | "leases" |
"secrets" | "configmaps" | "ingresses" | "ingressclasses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" | "secrets" | "configmaps" | "ingresses" | "ingressclasses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" | "pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "replicationcontrollers" | "jobs" | "cronjobs" |
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "verticalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" | "endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "verticalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" |
"priorityclasses" | "runtimeclasses" | "priorityclasses" | "runtimeclasses" |
"roles" | "clusterroles" | "rolebindings" | "clusterrolebindings" | "serviceaccounts"; "roles" | "clusterroles" | "rolebindings" | "clusterrolebindings" | "serviceaccounts";
@@ -171,6 +171,11 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
group: "apps", group: "apps",
namespaced: true, namespaced: true,
}, },
replicationcontrollers: {
kind: "ReplicationController",
group: "", // core
namespaced: true,
},
roles: { roles: {
kind: "Role", kind: "Role",
group: "rbac.authorization.k8s.io", group: "rbac.authorization.k8s.io",
@@ -6,7 +6,7 @@
import { getGlobalOverride } from "../test-utils/get-global-override"; import { getGlobalOverride } from "../test-utils/get-global-override";
import randomBytesInjectable from "./random-bytes.injectable"; import randomBytesInjectable from "./random-bytes.injectable";
export default getGlobalOverride(randomBytesInjectable, () => async (size) => { export default getGlobalOverride(randomBytesInjectable, () => (size) => {
const res = Buffer.alloc(size); const res = Buffer.alloc(size);
for (let i = 0; i < size; i += 1) { for (let i = 0; i < size; i += 1) {
@@ -4,13 +4,12 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { randomBytes } from "crypto"; import { randomBytes } from "crypto";
import { promisify } from "util";
export type RandomBytes = (size: number) => Promise<Buffer>; export type RandomBytes = (size: number) => Buffer;
const randomBytesInjectable = getInjectable({ const randomBytesInjectable = getInjectable({
id: "random-bytes", id: "random-bytes",
instantiate: (): RandomBytes => promisify(randomBytes), instantiate: (): RandomBytes => randomBytes,
causesSideEffects: true, causesSideEffects: true,
}); });
@@ -2,8 +2,8 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const applicationCopyrightInjectable = getInjectable({ const applicationCopyrightInjectable = getInjectable({
id: "application-copyright", id: "application-copyright",
@@ -2,8 +2,8 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const applicationDescriptionInjectable = getInjectable({ const applicationDescriptionInjectable = getInjectable({
id: "application-description", id: "application-description",
@@ -0,0 +1,30 @@
/**
* 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 { applicationInformationToken } from "@k8slens/application";
export const applicationInformationFakeInjectable = getInjectable({
id: "application-information-fake",
instantiate: () => ({
name: "some-product-name",
productName: "some-product-name",
version: "6.0.0",
updatingIsEnabled: false,
k8sProxyVersion: "0.2.1",
bundledKubectlVersion: "1.23.3",
bundledHelmVersion: "3.7.2",
sentryDsn: "",
contentSecurityPolicy:
"script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
welcomeRoute: "/welcome",
copyright: "some-copyright-information",
description: "some-descriptive-text",
}),
injectionToken: applicationInformationToken,
});
@@ -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 packageJson from "../../../package.json";
import { applicationInformationToken } from "../../common/vars/application-information-token";
const applicationInformationInjectable = getInjectable({
id: "application-information",
injectionToken: applicationInformationToken,
instantiate: () => {
const { version, config, productName, build, copyright, description, name } = packageJson;
return { version, config, productName, build, copyright, description, name };
},
causesSideEffects: true,
});
export default applicationInformationInjectable;
@@ -1,15 +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 packageJson from "../../../package.json";
export type ApplicationInformation = Pick<typeof packageJson, "version" | "config" | "productName" | "copyright" | "description" | "name"> & {
build: Partial<typeof packageJson["build"]> & { publish?: unknown[] };
};
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
id: "application-information-token",
});
@@ -1,24 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../test-utils/get-global-override";
import applicationInformationInjectable from "./application-information-injectable";
export default getGlobalOverride(applicationInformationInjectable, () => ({
name: "some-product-name",
productName: "some-product-name",
version: "6.0.0",
build: {} as any,
config: {
k8sProxyVersion: "0.2.1",
bundledKubectlVersion: "1.23.3",
bundledHelmVersion: "3.7.2",
sentryDsn: "",
contentSecurityPolicy: "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
welcomeRoute: "/welcome",
},
copyright: "some-copyright-information",
description: "some-descriptive-text",
}));
@@ -2,12 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const bundledKubectlVersionInjectable = getInjectable({ const bundledKubectlVersionInjectable = getInjectable({
id: "bundled-kubectl-version", id: "bundled-kubectl-version",
instantiate: (di) => di.inject(applicationInformationToken).config.bundledKubectlVersion, instantiate: (di) => di.inject(applicationInformationToken).bundledKubectlVersion,
}); });
export default bundledKubectlVersionInjectable; export default bundledKubectlVersionInjectable;
@@ -2,12 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const contentSecurityPolicyInjectable = getInjectable({ const contentSecurityPolicyInjectable = getInjectable({
id: "content-security-policy", id: "content-security-policy",
instantiate: (di) => di.inject(applicationInformationToken).config.contentSecurityPolicy, instantiate: (di) => di.inject(applicationInformationToken).contentSecurityPolicy,
}); });
export default contentSecurityPolicyInjectable; export default contentSecurityPolicyInjectable;
@@ -2,8 +2,8 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const productNameInjectable = getInjectable({ const productNameInjectable = getInjectable({
id: "product-name", id: "product-name",
@@ -2,12 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "./application-information-token";
const sentryDataSourceNameInjectable = getInjectable({ const sentryDataSourceNameInjectable = getInjectable({
id: "sentry-data-source-name", id: "sentry-data-source-name",
instantiate: (di) => di.inject(applicationInformationToken).config.sentryDsn, instantiate: (di) => di.inject(applicationInformationToken).sentryDsn,
}); });
export default sentryDataSourceNameInjectable; export default sentryDataSourceNameInjectable;
@@ -47,17 +47,29 @@ const getKubeApiDeps = (): KubeApiDependencies => {
}; };
}; };
export interface ExternalKubeApiOptions {
/**
* If `true` then on creation of the `KubeApi`instance a call to `apiManager.registerApi` will be
* made. This is `true` by default to maintain backwards compatability.
*
* Setting this to `false` might make `KubeObject`'s details drawer stop working.
*
* @default true
*/
autoRegister?: boolean;
}
// NOTE: this is done to preserve `instanceOf` behaviour // NOTE: this is done to preserve `instanceOf` behaviour
function KubeApiCstr< function KubeApiCstr<
Object extends KubeObject = KubeObject, Object extends KubeObject = KubeObject,
Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>, Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>,
>(opts: KubeApiOptions<Object, Data>) { >({ autoRegister = true, ...opts }: KubeApiOptions<Object, Data> & ExternalKubeApiOptions) {
const api = new InternalKubeApi(getKubeApiDeps(), opts); const api = new InternalKubeApi(getKubeApiDeps(), opts);
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
const storesAndApisCanBeCreated = di.inject(storesAndApisCanBeCreatedInjectionToken); const storesAndApisCanBeCreated = di.inject(storesAndApisCanBeCreatedInjectionToken);
if (storesAndApisCanBeCreated) { if (storesAndApisCanBeCreated && autoRegister) {
apiManager.registerApi(api); apiManager.registerApi(api);
} }
@@ -72,7 +84,7 @@ export type KubeApi<
export const KubeApi = KubeApiCstr as unknown as new< export const KubeApi = KubeApiCstr as unknown as new<
Object extends KubeObject = KubeObject, Object extends KubeObject = KubeObject,
Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>, Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>,
>(opts: KubeApiOptions<Object, Data>) => InternalKubeApi<Object, Data>; >(opts: KubeApiOptions<Object, Data> & ExternalKubeApiOptions) => InternalKubeApi<Object, Data>;
/** /**
* @deprecated Switch to using `Common.createResourceStack` instead * @deprecated Switch to using `Common.createResourceStack` instead
@@ -3,17 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { ObservableMap } from "mobx";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { getOrInsertWithAsync } from "../../../common/utils"; import { getOrInsert } from "../../../common/utils";
import randomBytesInjectable from "../../../common/utils/random-bytes.injectable"; import randomBytesInjectable from "../../../common/utils/random-bytes.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable"; import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable";
import ensureDirInjectable from "../../../common/fs/ensure-dir.injectable"; import ensureDirInjectable from "../../../common/fs/ensure-dir.injectable";
import getHashInjectable from "./get-hash.injectable"; import getHashInjectable from "./get-hash.injectable";
import getPathToLegacyPackageJsonInjectable from "./get-path-to-legacy-package-json.injectable";
import { registeredExtensionsInjectable } from "./registered-extensions.injectable";
export type EnsureHashedDirectoryForExtension = (extensionName: string, registeredExtensions: ObservableMap<string, string>) => Promise<string>; export type EnsureHashedDirectoryForExtension = (extensionName: string) => Promise<string>;
const ensureHashedDirectoryForExtensionInjectable = getInjectable({ const ensureHashedDirectoryForExtensionInjectable = getInjectable({
id: "ensure-hashed-directory-for-extension", id: "ensure-hashed-directory-for-extension",
@@ -24,14 +25,27 @@ const ensureHashedDirectoryForExtensionInjectable = getInjectable({
const directoryForExtensionData = di.inject(directoryForExtensionDataInjectable); const directoryForExtensionData = di.inject(directoryForExtensionDataInjectable);
const ensureDirectory = di.inject(ensureDirInjectable); const ensureDirectory = di.inject(ensureDirInjectable);
const getHash = di.inject(getHashInjectable); const getHash = di.inject(getHashInjectable);
const getPathToLegacyPackageJson = di.inject(getPathToLegacyPackageJsonInjectable);
const registeredExtensions = di.inject(registeredExtensionsInjectable);
return async (extensionName, registeredExtensions) => { return async (extensionName) => {
const dirPath = await getOrInsertWithAsync(registeredExtensions, extensionName, async () => { let dirPath: string;
const salt = (await randomBytes(32)).toString("hex");
const legacyDirPath = getPathToLegacyPackageJson(extensionName);
const hashedDirectoryForLegacyDirPath = registeredExtensions.get(legacyDirPath);
if (hashedDirectoryForLegacyDirPath) {
registeredExtensions.set(extensionName, hashedDirectoryForLegacyDirPath);
registeredExtensions.delete(legacyDirPath);
dirPath = hashedDirectoryForLegacyDirPath;
} else {
const salt = randomBytes(32).toString("hex");
const hashedName = getHash(`${extensionName}/${salt}`); const hashedName = getHash(`${extensionName}/${salt}`);
return joinPaths(directoryForExtensionData, hashedName); const hashedExtensionDirectory = joinPaths(directoryForExtensionData, hashedName);
});
dirPath = getOrInsert(registeredExtensions, extensionName, hashedExtensionDirectory);
}
await ensureDirectory(dirPath); await ensureDirectory(dirPath);
@@ -0,0 +1,96 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ObservableMap } from "mobx";
import { runInAction } from "mobx";
import { getDiForUnitTesting } from "../../../main/getDiForUnitTesting";
import type { EnsureHashedDirectoryForExtension } from "./ensure-hashed-directory-for-extension.injectable";
import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable";
import ensureDirInjectable from "../../../common/fs/ensure-dir.injectable";
import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { registeredExtensionsInjectable } from "./registered-extensions.injectable";
describe("ensure-hashed-directory-for-extension", () => {
let ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension;
let ensureDirMock: jest.Mock;
let registeredExtensions: ObservableMap<string, string>;
beforeEach(() => {
const di = getDiForUnitTesting({ doGeneralOverrides: true });
ensureDirMock = jest.fn();
di.override(ensureDirInjectable, () => ensureDirMock);
di.override(directoryForExtensionDataInjectable, () => "some-directory-for-extension-data");
di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data");
ensureHashedDirectoryForExtension = di.inject(
ensureHashedDirectoryForExtensionInjectable,
);
registeredExtensions = di.inject(registeredExtensionsInjectable);
});
it("given registered extension exists, returns existing directory", async () => {
runInAction(() => {
registeredExtensions.set("some-extension-name", "some-directory");
});
const actual = await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(actual).toBe("some-directory");
});
it("given registered extension does not exist, returns random directory", async () => {
const actual = await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(actual).toBe("some-directory-for-extension-data/a37a1cfefc0391af3733f23cb6b29443f596a2b8ffe6d116c35df7bc3cd99ef6");
});
describe("given extension directory was saved based on extension's package.json path", () => {
beforeEach(() => {
runInAction(() => {
registeredExtensions.set("/some-directory-for-user-data/node_modules/some-extension-name/package.json", "some-directory");
});
ensureDirMock.mockClear();
});
it("returns existing directory", async () => {
const actual = await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(actual).toBe("some-directory");
});
it("ensure dir is called with some directory", async () => {
await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(ensureDirMock).toHaveBeenCalledWith("some-directory");
});
it("is migrated to use the extension name as key", async () => {
await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(registeredExtensions.get("some-extension-name")).toEqual("some-directory");
});
it("old key is removed", async () => {
await ensureHashedDirectoryForExtension(
"some-extension-name",
);
expect(registeredExtensions.has("/some-directory-for-user-data/node_modules/some-extension-name/package.json")).toEqual(false);
});
});
});
@@ -0,0 +1,10 @@
/**
* 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 { MigrationDeclaration } from "../../../common/base-store/migrations.injectable";
export const fileSystemProvisionerStoreInjectionToken = getInjectionToken<MigrationDeclaration>({
id: "file-system-provisioner-store-injection-token",
});
@@ -15,6 +15,7 @@ import { enlistMessageChannelListenerInjectionToken } from "../../../common/util
import fileSystemProvisionerStoreMigrationVersionInjectable from "./migration-version.injectable"; import fileSystemProvisionerStoreMigrationVersionInjectable from "./migration-version.injectable";
import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable"; import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable";
import { registeredExtensionsInjectable } from "./registered-extensions.injectable";
const fileSystemProvisionerStoreInjectable = getInjectable({ const fileSystemProvisionerStoreInjectable = getInjectable({
id: "file-system-provisioner-store", id: "file-system-provisioner-store",
@@ -32,6 +33,7 @@ const fileSystemProvisionerStoreInjectable = getInjectable({
shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken),
sendMessageToChannel: di.inject(sendMessageToChannelInjectionToken), sendMessageToChannel: di.inject(sendMessageToChannelInjectionToken),
ensureHashedDirectoryForExtension: di.inject(ensureHashedDirectoryForExtensionInjectable), ensureHashedDirectoryForExtension: di.inject(ensureHashedDirectoryForExtensionInjectable),
registeredExtensions: di.inject(registeredExtensionsInjectable),
}), }),
}); });
@@ -3,7 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { action, makeObservable, observable } from "mobx"; import type { ObservableMap } from "mobx";
import { action, makeObservable } from "mobx";
import type { BaseStoreDependencies } from "../../../common/base-store/base-store"; import type { BaseStoreDependencies } from "../../../common/base-store/base-store";
import { BaseStore } from "../../../common/base-store/base-store"; import { BaseStore } from "../../../common/base-store/base-store";
import type { LensExtensionId } from "../../lens-extension"; import type { LensExtensionId } from "../../lens-extension";
@@ -16,11 +17,10 @@ interface FSProvisionModel {
interface Dependencies extends BaseStoreDependencies { interface Dependencies extends BaseStoreDependencies {
ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension; ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension;
registeredExtensions: ObservableMap<LensExtensionId, string>;
} }
export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> { export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> {
readonly registeredExtensions = observable.map<LensExtensionId, string>();
constructor(protected readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super(dependencies, { super(dependencies, {
configName: "lens-filesystem-provisioner-store", configName: "lens-filesystem-provisioner-store",
@@ -37,17 +37,17 @@ export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> {
* @returns path to the folder that the extension can safely write files to. * @returns path to the folder that the extension can safely write files to.
*/ */
async requestDirectory(extensionName: string): Promise<string> { async requestDirectory(extensionName: string): Promise<string> {
return this.dependencies.ensureHashedDirectoryForExtension(extensionName, this.registeredExtensions); return this.dependencies.ensureHashedDirectoryForExtension(extensionName);
} }
@action @action
protected fromStore({ extensions }: FSProvisionModel = { extensions: {}}): void { protected fromStore({ extensions }: FSProvisionModel = { extensions: {}}): void {
this.registeredExtensions.merge(extensions); this.dependencies.registeredExtensions.merge(extensions);
} }
toJSON(): FSProvisionModel { toJSON(): FSProvisionModel {
return toJS({ return toJS({
extensions: Object.fromEntries(this.registeredExtensions), extensions: Object.fromEntries(this.dependencies.registeredExtensions),
}); });
} }
} }
@@ -0,0 +1,22 @@
/**
* 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 directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
export type GetPathToLegacyPackageJson = (extensionName: string) => string;
const getPathToLegacyPackageJson = getInjectable({
id: "get-path-to-legacy-package-json",
instantiate: (di): GetPathToLegacyPackageJson => {
const directoryForUserData = di.inject(directoryForUserDataInjectable);
const joinPaths = di.inject(joinPathsInjectable);
return (extensionName: string) => joinPaths(directoryForUserData, "node_modules", extensionName, "package.json");
},
});
export default getPathToLegacyPackageJson;
@@ -0,0 +1,12 @@
/**
* 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 { observable } from "mobx";
import type { LensExtensionId } from "../../lens-extension";
export const registeredExtensionsInjectable = getInjectable({
id: "registered-extensions",
instantiate: () => observable.map<LensExtensionId, string>(),
});
+4 -4
View File
@@ -27,12 +27,12 @@ export abstract class IpcMain extends IpcRegistrar {
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer { listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`; const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
const cleanup = once(() => { const cleanup = once(() => {
this.extension[lensExtensionDependencies].logger.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
return ipcMain.removeListener(prefixedChannel, listener); return ipcMain.removeListener(prefixedChannel, listener);
}); });
this.extension[lensExtensionDependencies].logger.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
ipcMain.addListener(prefixedChannel, listener); ipcMain.addListener(prefixedChannel, listener);
this.extension[Disposers].push(cleanup); this.extension[Disposers].push(cleanup);
@@ -47,10 +47,10 @@ export abstract class IpcMain extends IpcRegistrar {
handle(channel: string, handler: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any): void { handle(channel: string, handler: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any): void {
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`; const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
this.extension[lensExtensionDependencies].logger.info(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
ipcMainHandle(prefixedChannel, handler); ipcMainHandle(prefixedChannel, handler);
this.extension[Disposers].push(() => { this.extension[Disposers].push(() => {
this.extension[lensExtensionDependencies].logger.info(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
return ipcMain.removeHandler(prefixedChannel); return ipcMain.removeHandler(prefixedChannel);
}); });
@@ -28,12 +28,12 @@ export abstract class IpcRenderer extends IpcRegistrar {
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer { listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`; const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
const cleanup = once(() => { const cleanup = once(() => {
console.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); console.debug(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
return ipcRenderer.removeListener(prefixedChannel, listener); return ipcRenderer.removeListener(prefixedChannel, listener);
}); });
console.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); console.debug(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
ipcRenderer.addListener(prefixedChannel, listener); ipcRenderer.addListener(prefixedChannel, listener);
this.extension[Disposers].push(cleanup); this.extension[Disposers].push(cleanup);
@@ -38,6 +38,8 @@ import kubeEventApiInjectable from "../../common/k8s-api/endpoints/events.api.in
import roleBindingApiInjectable from "../../common/k8s-api/endpoints/role-binding.api.injectable"; import roleBindingApiInjectable from "../../common/k8s-api/endpoints/role-binding.api.injectable";
import customResourceDefinitionApiInjectable from "../../common/k8s-api/endpoints/custom-resource-definition.api.injectable"; import customResourceDefinitionApiInjectable from "../../common/k8s-api/endpoints/custom-resource-definition.api.injectable";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token"; import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import requestMetricsInjectable from "../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
export function isAllowedResource(resources: KubeResource | KubeResource[]) { export function isAllowedResource(resources: KubeResource | KubeResource[]) {
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
@@ -93,6 +95,17 @@ export const crdApi = asLegacyGlobalForExtensionApi(customResourceDefinitionApiI
export * from "../common-api/k8s-api"; export * from "../common-api/k8s-api";
export const requestMetrics = asLegacyGlobalFunctionForExtensionApi(requestMetricsInjectable);
export type {
RequestMetrics,
RequestMetricsParams,
} from "../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
export type {
MetricData,
MetricResult,
} from "../../common/k8s-api/endpoints/metrics.api";
export { export {
KubeObjectStatusLevel, KubeObjectStatusLevel,
type KubeObjectStatus, type KubeObjectStatus,
@@ -0,0 +1,23 @@
/**
* 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 { bundledExtensionInjectionToken } from "../../../../../../common/library";
import buildSemanticVersionInjectable from "../../../../../../common/vars/build-semantic-version.injectable";
const aboutBundledExtensionsInjectable = getInjectable({
id: "about-bundled-extensions",
instantiate: (di) => {
const buildSemanticVersion = di.inject(buildSemanticVersionInjectable);
const bundledExtensions = di.injectMany(bundledExtensionInjectionToken);
if (buildSemanticVersion.get().prerelease[0] === "latest") {
return [];
}
return bundledExtensions.map(ext => `${ext.manifest.name}: ${ext.manifest.version}`);
},
});
export default aboutBundledExtensionsInjectable;
@@ -10,6 +10,7 @@ import productNameInjectable from "../../../../../../common/vars/product-name.in
import buildVersionInjectable from "../../../../../../main/vars/build-version/build-version.injectable"; import buildVersionInjectable from "../../../../../../main/vars/build-version/build-version.injectable";
import extensionApiVersionInjectable from "../../../../../../common/vars/extension-api-version.injectable"; import extensionApiVersionInjectable from "../../../../../../common/vars/extension-api-version.injectable";
import applicationCopyrightInjectable from "../../../../../../common/vars/application-copyright.injectable"; import applicationCopyrightInjectable from "../../../../../../common/vars/application-copyright.injectable";
import aboutBundledExtensionsInjectable from "./about-bundled-extensions.injectable";
const showAboutInjectable = getInjectable({ const showAboutInjectable = getInjectable({
id: "show-about", id: "show-about",
@@ -22,6 +23,7 @@ const showAboutInjectable = getInjectable({
const appName = di.inject(appNameInjectable); const appName = di.inject(appNameInjectable);
const productName = di.inject(productNameInjectable); const productName = di.inject(productNameInjectable);
const applicationCopyright = di.inject(applicationCopyrightInjectable); const applicationCopyright = di.inject(applicationCopyrightInjectable);
const aboutBundledExtensions = di.inject(aboutBundledExtensionsInjectable);
return () => { return () => {
const appInfo = [ const appInfo = [
@@ -30,6 +32,7 @@ const showAboutInjectable = getInjectable({
`Electron: ${process.versions.electron}`, `Electron: ${process.versions.electron}`,
`Chrome: ${process.versions.chrome}`, `Chrome: ${process.versions.chrome}`,
`Node: ${process.versions.node}`, `Node: ${process.versions.node}`,
...aboutBundledExtensions,
applicationCopyright, applicationCopyright,
]; ];
@@ -2,12 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { applicationInformationToken } from "@k8slens/application";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "../../../../../common/vars/application-information-token";
const publishIsConfiguredInjectable = getInjectable({ const publishIsConfiguredInjectable = getInjectable({
id: "publish-is-configured", id: "publish-is-configured",
instantiate: (di) => Boolean(di.inject(applicationInformationToken).build.publish?.length), instantiate: (di) => Boolean(di.inject(applicationInformationToken).updatingIsEnabled),
}); });
export default publishIsConfiguredInjectable; export default publishIsConfiguredInjectable;
@@ -4323,3 +4323,497 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
</div> </div>
`; `;
exports[`cluster - sidebar and tab navigation for extensions given extension with cluster pages and cluster page menus with explicit 'orderNumber' given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered renders 1`] = `
<div>
<div
class="Animate slide-right Drawer KubeObjectDetails flex column right enter leave"
style="--size: 725px; --enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="drawer-wrapper flex column"
>
<div
class="drawer-title flex align-center"
>
<div
class="drawer-title-text flex gaps align-center"
>
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
<div>
Close
</div>
</div>
<div
class="drawer-content flex column box grow"
/>
</div>
<div
class="ResizingAnchor horizontal leading"
/>
</div>
<div
class="Notifications flex column align-flex-end"
/>
<div
class="mainLayout"
style="--sidebar-width: 200px;"
>
<div
class="sidebar"
>
<div
class="flex flex-col"
data-testid="cluster-sidebar"
>
<div
class="SidebarCluster"
>
<div
class="Avatar rounded loadingAvatar"
style="width: 40px; height: 40px;"
>
??
</div>
<div
class="loadingClusterName"
/>
</div>
<div
class="sidebarNav sidebar-active-status"
>
<div
class="SidebarItem"
data-is-active-test="true"
data-testid="sidebar-item-some-extension-name-some-parent-id"
>
<a
aria-current="page"
class="navItem active"
data-testid="sidebar-item-link-for-some-extension-name-some-parent-id"
href="/"
>
<div>
Some icon
</div>
<span>
Parent
</span>
<i
class="Icon expandIcon material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-workloads"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-workloads"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span>
Workloads
</span>
<i
class="Icon expandIcon material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-config"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-config"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="list"
>
list
</span>
</i>
<span>
Config
</span>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-network"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-network"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="device_hub"
>
device_hub
</span>
</i>
<span>
Network
</span>
<i
class="Icon expandIcon material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-storage"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-storage"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="storage"
>
storage
</span>
</i>
<span>
Storage
</span>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-helm"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-helm"
href="/"
>
<i
class="Icon svg focusable"
>
<span
class="icon"
/>
</i>
<span>
Helm
</span>
<i
class="Icon expandIcon material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-user-management"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-user-management"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="security"
>
security
</span>
</i>
<span>
Access Control
</span>
</a>
</div>
<div
class="SidebarItem"
data-is-active-test="false"
data-testid="sidebar-item-custom-resources"
>
<a
class="navItem"
data-testid="sidebar-item-link-for-custom-resources"
href="/"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="extension"
>
extension
</span>
</i>
<span>
Custom Resources
</span>
<i
class="Icon expandIcon material focusable"
>
<span
class="icon"
data-icon-name="keyboard_arrow_down"
>
keyboard_arrow_down
</span>
</i>
</a>
</div>
</div>
</div>
<div
class="ResizingAnchor horizontal trailing"
/>
</div>
<div
class="contents"
>
<div
class="TabLayout"
data-testid="tab-layout"
>
<div
class="Tabs center scrollable"
>
<div
class="Tab flex gaps align-center active"
data-is-active-test="true"
data-testid="tab-link-for-some-extension-name-some-child-id"
role="tab"
tabindex="0"
>
<div
class="label"
>
Child 1
</div>
</div>
<div
class="Tab flex gaps align-center"
data-is-active-test="false"
data-testid="tab-link-for-some-extension-name-some-other-child-id"
role="tab"
tabindex="0"
>
<div
class="label"
>
Child 2
</div>
</div>
</div>
<main
class=""
>
<div
data-testid="some-child-page"
>
Some child page
</div>
</main>
</div>
</div>
<div
class="footer"
>
<div
class="Dock"
tabindex="-1"
>
<div
class="ResizingAnchor vertical leading"
/>
<div
class="tabs-container flex align-center"
>
<div
class="dockTabs"
role="tablist"
>
<div
class="Tabs tabs"
>
<div
class="Tab flex gaps align-center DockTab TerminalTab active"
data-testid="dock-tab-for-terminal"
id="tab-terminal"
role="tab"
tabindex="0"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="terminal"
>
terminal
</span>
</i>
<div
class="label"
>
<div
class="flex align-center"
>
<span
class="title"
>
Terminal
</span>
<div
class="close"
>
<i
class="Icon material interactive focusable small"
data-testid="dock-tab-close-for-terminal"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
<div
data-testid="tooltip-content-for-dock-tab-close-for-terminal"
>
Close ⌘+W
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="toolbar flex gaps align-center box grow"
>
<div
class="dock-menu box grow"
>
<i
class="Icon new-dock-tab material interactive focusable"
id="menu-actions-for-dock"
tabindex="0"
>
<span
class="icon"
data-icon-name="add"
>
add
</span>
</i>
<div>
New tab
</div>
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="fullscreen"
>
fullscreen
</span>
</i>
<div>
Fit to window
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="keyboard_arrow_up"
>
keyboard_arrow_up
</span>
</i>
<div>
Open
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
@@ -79,7 +79,11 @@ exports[`disable kube object detail items when cluster is not relevant given ext
<span <span
class="value" class="value"
> >
some-namespace <a
href="/workloads?kube-details=%2Fapi%2Fv1%2Fnamespaces%2Fsome-namespace&kube-selected=%2Fapis%2Fsome-api-version%2Fnamespaces%2Fsome-namespace%2Fsome-kind%2Fsome-name"
>
some-namespace
</a>
</span> </span>
</div> </div>
<div <div
@@ -710,7 +714,11 @@ exports[`disable kube object detail items when cluster is not relevant given ext
<span <span
class="value" class="value"
> >
some-namespace <a
href="/workloads?kube-details=%2Fapi%2Fv1%2Fnamespaces%2Fsome-namespace&kube-selected=%2Fapis%2Fsome-api-version%2Fnamespaces%2Fsome-namespace%2Fsome-kind%2Fsome-name"
>
some-namespace
</a>
</span> </span>
</div> </div>
<div> <div>
@@ -1336,7 +1344,11 @@ exports[`disable kube object detail items when cluster is not relevant given not
<span <span
class="value" class="value"
> >
some-namespace <a
href="/workloads?kube-details=%2Fapi%2Fv1%2Fnamespaces%2Fsome-namespace&kube-selected=%2Fapis%2Fsome-api-version%2Fnamespaces%2Fsome-namespace%2Fsome-kind%2Fsome-name"
>
some-namespace
</a>
</span> </span>
</div> </div>
<div> <div>
@@ -79,7 +79,11 @@ exports[`reactively hide kube object detail item renders 1`] = `
<span <span
class="value" class="value"
> >
some-namespace <a
href="/workloads?kube-details=%2Fapi%2Fv1%2Fnamespaces%2Fsome-namespace&kube-selected=%2Fapis%2Fsome-api-version%2Fnamespaces%2Fsome-namespace%2Fsome-kind%2Fsome-name"
>
some-namespace
</a>
</span> </span>
</div> </div>
<div> <div>
@@ -705,7 +709,11 @@ exports[`reactively hide kube object detail item when the item is shown renders
<span <span
class="value" class="value"
> >
some-namespace <a
href="/workloads?kube-details=%2Fapi%2Fv1%2Fnamespaces%2Fsome-namespace&kube-selected=%2Fapis%2Fsome-api-version%2Fnamespaces%2Fsome-namespace%2Fsome-kind%2Fsome-name"
>
some-namespace
</a>
</span> </span>
</div> </div>
<div <div
@@ -21,6 +21,7 @@ import { runInAction, computed, observable } from "mobx";
import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable"; import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { flushPromises } from "../../common/test-utils/flush-promises"; import { flushPromises } from "../../common/test-utils/flush-promises";
import type { ClusterPageMenuRegistration } from "../../extensions/common-api/types";
describe("cluster - sidebar and tab navigation for extensions", () => { describe("cluster - sidebar and tab navigation for extensions", () => {
let applicationBuilder: ApplicationBuilder; let applicationBuilder: ApplicationBuilder;
@@ -141,15 +142,12 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
const route = windowDi const route = windowDi
.inject(routesInjectable) .inject(routesInjectable)
.get() .get()
.find( .find(matches({
matches({ path: "/extension/some-extension-name/some-child-page-id",
path: "/extension/some-extension-name/some-child-page-id", }));
}),
);
assert(route); assert(route);
navigateToRoute(route); navigateToRoute(route);
}); });
it("renders", () => { it("renders", () => {
@@ -455,4 +453,131 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
}); });
}); });
describe("given extension with cluster pages and cluster page menus with explicit 'orderNumber'", () => {
let someObservable: IObservableValue<boolean>;
beforeEach(() => {
someObservable = observable.box(false);
const testExtension = {
id: "some-extension-id",
name: "some-extension-name",
rendererOptions: {
clusterPages: [
{
components: {
Page: () => {
throw new Error("should never come here");
},
},
},
{
id: "some-child-page-id",
components: {
Page: () => <div data-testid="some-child-page">Some child page</div>,
},
},
{
id: "some-other-child-page-id",
components: {
Page: () => (
<div data-testid="some-other-child-page">Some other child page</div>
),
},
},
],
clusterPageMenus: [
{
id: "some-parent-id",
title: "Parent",
components: {
Icon: () => <div>Some icon</div>,
},
orderNumber: -Infinity,
},
{
id: "some-child-id",
target: { pageId: "some-child-page-id" },
parentId: "some-parent-id",
title: "Child 1",
components: {
Icon: null as never,
},
},
{
id: "some-other-child-id",
target: { pageId: "some-other-child-page-id" },
parentId: "some-parent-id",
title: "Child 2",
components: {
Icon: null as never,
},
},
{
id: "some-menu-with-controlled-visibility",
title: "Some menu with controlled visibility",
visible: computed(() => someObservable.get()),
components: {
Icon: () => <div>Some icon</div>,
},
},
] as ClusterPageMenuRegistration[],
},
};
applicationBuilder.extensions.enable(testExtension);
});
describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => {
beforeEach(async () => {
rendered = await applicationBuilder.render();
const windowDi = applicationBuilder.applicationWindow.only.di;
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
const route = windowDi
.inject(routesInjectable)
.get()
.find(matches({
path: "/extension/some-extension-name/some-child-page-id",
}));
assert(route);
navigateToRoute(route);
});
it("renders", () => {
expect(rendered.container).toMatchSnapshot();
});
it("renderes parent as first item in sidebar", () => {
const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
assert(parent);
expect(parent.previousSibling).toBeNull();
});
it("parent is highlighted", () => {
const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("true");
});
it("parent sidebar item is not expanded", () => {
const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
expect(child).toBeNull();
});
it("child page is shown", () => {
expect(rendered.getByTestId("some-child-page")).not.toBeNull();
});
});
});
}); });
@@ -2939,7 +2939,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -3016,7 +3016,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -3142,7 +3142,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
class="Select__menu-portal css-1no2yl0-MenuPortal" class="Select__menu-portal css-1no2yl0-MenuPortal"
> >
<div <div
class="theme-outlined install-chart-version-select-for-some-first-tab-id-options Select__menu css-1nmdiq5-menu" class="theme-dark install-chart-version-select-for-some-first-tab-id-options Select__menu css-1nmdiq5-menu"
id="react-select-install-chart-version-select-for-some-first-tab-id-listbox" id="react-select-install-chart-version-select-for-some-first-tab-id-listbox"
> >
<div <div
@@ -3958,7 +3958,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -4033,7 +4033,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -4951,7 +4951,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -5026,7 +5026,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -5939,7 +5939,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -6014,7 +6014,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -6927,7 +6927,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -7002,7 +7002,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -7937,7 +7937,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -8012,7 +8012,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -8140,7 +8140,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
class="Select__menu-portal css-1no2yl0-MenuPortal" class="Select__menu-portal css-1no2yl0-MenuPortal"
> >
<div <div
class="NamespaceSelectMenu theme-outlined install-chart-namespace-select-for-some-first-tab-id-options Select__menu css-1nmdiq5-menu" class="NamespaceSelectMenu theme-dark install-chart-namespace-select-for-some-first-tab-id-options Select__menu css-1nmdiq5-menu"
id="react-select-install-chart-namespace-select-for-some-first-tab-id-listbox" id="react-select-install-chart-namespace-select-for-some-first-tab-id-listbox"
> >
<div <div
@@ -8956,7 +8956,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -9031,7 +9031,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -9944,7 +9944,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -10019,7 +10019,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -13453,7 +13453,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -13528,7 +13528,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -15566,7 +15566,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -15643,7 +15643,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -16608,7 +16608,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -16683,7 +16683,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -17596,7 +17596,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -17671,7 +17671,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -18584,7 +18584,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -18659,7 +18659,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -1125,7 +1125,7 @@ exports[`installing helm chart from previously opened tab given tab for installi
Version Version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -1200,7 +1200,7 @@ exports[`installing helm chart from previously opened tab given tab for installi
Namespace Namespace
</span> </span>
<div <div
class="Select theme-outlined NamespaceSelect css-b62m3t-container" class="Select theme-dark NamespaceSelect css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -4064,7 +4064,7 @@ exports[`New Upgrade Helm Chart Dock Tab given a namespace is selected when navi
Upgrade version Upgrade version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -5074,7 +5074,7 @@ exports[`New Upgrade Helm Chart Dock Tab given a namespace is selected when navi
Upgrade version Upgrade version
</span> </span>
<div <div
class="Select theme-outlined chart-version css-b62m3t-container" class="Select theme-dark chart-version css-b62m3t-container"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
@@ -225,15 +225,96 @@ describe("showing details for helm release", () => {
it("closes details for first release", () => { it("closes details for first release", () => {
expect( expect(
rendered.queryByTestId("helm-release-details-for-some-namespace/some-name"), rendered.queryByTestId(
"helm-release-details-for-some-namespace/some-name",
),
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
}); });
it("opens details for second release", () => { it("opens details for second release", () => {
expect( expect(
rendered.getByTestId("helm-release-details-for-some-other-namespace/some-other-name"), rendered.getByTestId(
"helm-release-details-for-some-other-namespace/some-other-name",
),
).toBeInTheDocument(); ).toBeInTheDocument();
}); });
it("shows spinner", () => {
expect(
rendered.getByTestId("helm-release-detail-content-spinner"),
).toBeInTheDocument();
});
describe("when details for second release resolve", () => {
beforeEach(async () => {
await requestDetailedHelmReleaseMock.resolve({
callWasSuccessful: true,
response: {
release: {
appVersion: "some-app-version",
chart: "some-chart-1.0.0",
status: "some-status",
updated: "some-updated",
revision: "some-revision",
name: "some-other-name",
namespace: "some-other-namespace",
},
details: {
name: "some-other-name",
namespace: "some-other-namespace",
version: "some-version",
config: "some-config",
manifest: "some-manifest",
info: {
deleted: "some-deleted",
description: "some-description",
first_deployed: "some-first-deployed",
last_deployed: "some-last-deployed",
notes: "some-notes",
status: "some-status",
},
resources: [
{
kind: "some-kind",
apiVersion: "some-api-version",
metadata: {
uid: "some-uid",
name: "some-resource",
namespace: "some-namespace",
creationTimestamp: "2015-10-22T07:28:00Z",
},
},
],
},
},
});
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("calls for release configuration", () => {
expect(
requestHelmReleaseConfigurationMock,
).toHaveBeenCalledWith("some-other-name", "some-other-namespace", true);
});
describe("when configuration resolves", () => {
beforeEach(async () => {
await requestHelmReleaseConfigurationMock.resolve(
"some-other-configuration",
);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
});
});
}); });
describe("when details is closed", () => { describe("when details is closed", () => {
@@ -411,7 +492,7 @@ describe("showing details for helm release", () => {
describe("when changing the configuration", () => { describe("when changing the configuration", () => {
beforeEach(() => { beforeEach(() => {
const configuration = rendered.getByTestId( const configuration = rendered.getByTestId(
"monaco-editor-for-helm-release-configuration", "monaco-editor-for-helm-release-configuration-some-namespace/some-name",
); );
fireEvent.change(configuration, { fireEvent.change(configuration, {
@@ -425,7 +506,7 @@ describe("showing details for helm release", () => {
it("has the configuration", () => { it("has the configuration", () => {
const input = rendered.getByTestId( const input = rendered.getByTestId(
"monaco-editor-for-helm-release-configuration", "monaco-editor-for-helm-release-configuration-some-namespace/some-name",
); );
expect(input).toHaveValue("some-new-configuration"); expect(input).toHaveValue("some-new-configuration");
@@ -467,7 +548,7 @@ describe("showing details for helm release", () => {
it("overrides the user inputted configuration with new configuration", () => { it("overrides the user inputted configuration with new configuration", () => {
const input = rendered.getByTestId( const input = rendered.getByTestId(
"monaco-editor-for-helm-release-configuration", "monaco-editor-for-helm-release-configuration-some-namespace/some-name",
); );
expect(input).toHaveValue("some-other-configuration"); expect(input).toHaveValue("some-other-configuration");
@@ -6,12 +6,12 @@
// Fix embedded kubeconfig paths under snap config // Fix embedded kubeconfig paths under snap config
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { applicationInformationToken } from "../../../common/vars/application-information-token";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token"; import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable"; import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable";
import type { ClusterModel } from "../../../common/cluster-types"; import type { ClusterModel } from "../../../common/cluster-types";
import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable"; import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable";
import { applicationInformationToken } from "@k8slens/application";
const clusterStoreSnapMigrationInjectable = getInjectable({ const clusterStoreSnapMigrationInjectable = getInjectable({
id: "cluster-store-snap-migration", id: "cluster-store-snap-migration",
+1 -11
View File
@@ -3,15 +3,5 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { createContainer } from "@ogre-tools/injectable"; import { createContainer } from "@ogre-tools/injectable";
import { runInAction } from "mobx";
import applicationInformationInjectable from "../common/vars/application-information-injectable";
export const getDi = () => { export const getDi = () => createContainer("main");
const di = createContainer("main");
runInAction(() => {
di.register(applicationInformationInjectable);
});
return di;
};
@@ -29,9 +29,9 @@ import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
import electronInjectable from "./utils/resolve-system-proxy/electron.injectable"; import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable"; import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable";
import type { GlobalOverride } from "../common/test-utils/get-global-override"; import type { GlobalOverride } from "../common/test-utils/get-global-override";
import applicationInformationInjectable from "../common/vars/application-information-injectable";
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token"; import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes"; import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes";
import { applicationInformationFakeInjectable } from "../common/vars/application-information-fake-injectable";
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) { export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
const { const {
@@ -57,9 +57,10 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
.filter(isInjectable) .filter(isInjectable)
) as Injectable<any, any, any>[]; ) as Injectable<any, any, any>[];
registerMobX(di);
runInAction(() => { runInAction(() => {
registerMobX(di); di.register(applicationInformationFakeInjectable);
di.register(applicationInformationInjectable);
chunk(100)(injectables).forEach(chunkInjectables => { chunk(100)(injectables).forEach(chunkInjectables => {
di.register(...chunkInjectables); di.register(...chunkInjectables);
@@ -13,9 +13,9 @@ import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-b
import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable"; import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable";
import lensResourcesDirInjectable from "../../../../common/vars/lens-resources-dir.injectable"; import lensResourcesDirInjectable from "../../../../common/vars/lens-resources-dir.injectable";
import isLinuxInjectable from "../../../../common/vars/is-linux.injectable"; import isLinuxInjectable from "../../../../common/vars/is-linux.injectable";
import { applicationInformationToken } from "../../../../common/vars/application-information-token";
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable"; import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
import lensProxyCertificateInjectable from "../../../../common/certificate/lens-proxy-certificate.injectable"; import lensProxyCertificateInjectable from "../../../../common/certificate/lens-proxy-certificate.injectable";
import { applicationInformationToken } from "@k8slens/application";
export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover"; export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover";
@@ -27,10 +27,11 @@ export interface UrlSource {
} }
export type ContentSource = RequireExactlyOne<FileSource & UrlSource>; export type ContentSource = RequireExactlyOne<FileSource & UrlSource>;
// see https://www.electronjs.org/docs/latest/api/session#sessetcertificateverifyprocproc
enum ChromiumNetError { enum ChromiumNetError {
SUCCESS = 0, SUCCESS = 0,
FAILURE = 1, FAILURE = -2,
RESULT_FROM_CHROMIUM, RESULT_FROM_CHROMIUM = -3,
} }
export interface ElectronWindowConfiguration { export interface ElectronWindowConfiguration {
@@ -7,8 +7,8 @@ import { docsUrl, slackUrl } from "../../../common/vars";
import type { WeblinkData } from "../../../common/weblinks-store/weblink-store"; import type { WeblinkData } from "../../../common/weblinks-store/weblink-store";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { weblinkStoreMigrationInjectionToken } from "../../../common/weblinks-store/migration-token"; import { weblinkStoreMigrationInjectionToken } from "../../../common/weblinks-store/migration-token";
import { applicationInformationToken } from "../../../common/vars/application-information-token";
import { lensDocumentationWeblinkId, lensSlackWeblinkId } from "../links"; import { lensDocumentationWeblinkId, lensSlackWeblinkId } from "../links";
import { applicationInformationToken } from "@k8slens/application";
const currentVersionWeblinkStoreMigrationInjectable = getInjectable({ const currentVersionWeblinkStoreMigrationInjectable = getInjectable({
id: "current-version-weblink-store-migration", id: "current-version-weblink-store-migration",
+3 -11
View File
@@ -29,17 +29,9 @@ export async function bootstrap(di: DiContainer) {
assert(rootElem, "#app MUST exist"); assert(rootElem, "#app MUST exist");
const extensionLoader = di.inject(extensionLoaderInjectable); await di.inject(extensionLoaderInjectable).init();
await di.inject(extensionDiscoveryInjectable).init();
extensionLoader.init(); di.inject(extensionInstallationStateStoreInjectable).bindIpcListeners();
const extensionDiscovery = di.inject(extensionDiscoveryInjectable);
extensionDiscovery.init();
const extensionInstallationStateStore = di.inject(extensionInstallationStateStoreInjectable);
extensionInstallationStateStore.bindIpcListeners();
let App; let App;
let initializeApp; let initializeApp;
@@ -127,7 +127,7 @@
} }
.catalogAvatar { .catalogAvatar {
font-size: 1.2ch; font-size: 1.2ch !important;
} }
.views { .views {
@@ -85,6 +85,7 @@ const NonInjectedReleaseDetailsContent = observer(({ model }: Dependencies & Rel
</DrawerItem> </DrawerItem>
<ReleaseValues <ReleaseValues
releaseId={model.id}
configuration={model.configuration} configuration={model.configuration}
onlyUserSuppliedValuesAreShown={ onlyUserSuppliedValuesAreShown={
model.onlyUserSuppliedValuesAreShown model.onlyUserSuppliedValuesAreShown
@@ -150,11 +151,12 @@ const ResourceGroup = ({
); );
interface ReleaseValuesProps { interface ReleaseValuesProps {
releaseId: string;
configuration: ConfigurationInput; configuration: ConfigurationInput;
onlyUserSuppliedValuesAreShown: OnlyUserSuppliedValuesAreShownToggle; onlyUserSuppliedValuesAreShown: OnlyUserSuppliedValuesAreShownToggle;
} }
const ReleaseValues = observer(({ configuration, onlyUserSuppliedValuesAreShown }: ReleaseValuesProps) => { const ReleaseValues = observer(({ releaseId, configuration, onlyUserSuppliedValuesAreShown }: ReleaseValuesProps) => {
const configurationIsLoading = configuration.isLoading.get(); const configurationIsLoading = configuration.isLoading.get();
return ( return (
@@ -171,7 +173,7 @@ const ReleaseValues = observer(({ configuration, onlyUserSuppliedValuesAreShown
/> />
<MonacoEditor <MonacoEditor
id="helm-release-configuration" id={`helm-release-configuration-${releaseId}`}
style={{ minHeight: 300 }} style={{ minHeight: 300 }}
value={configuration.nonSavedValue.get()} value={configuration.nonSavedValue.get()}
onChange={configuration.onChange} onChange={configuration.onChange}
@@ -9,7 +9,7 @@ import React from "react";
import upperFirst from "lodash/upperFirst"; import upperFirst from "lodash/upperFirst";
import kebabCase from "lodash/kebabCase"; import kebabCase from "lodash/kebabCase";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem, DrawerItemLabels } from "../drawer"; import { DrawerItem } from "../drawer";
import { Badge } from "../badge"; import { Badge } from "../badge";
import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { KubeObjectDetailsProps } from "../kube-object-details";
import { formatNodeTaint, Node } from "../../../common/k8s-api/endpoints"; import { formatNodeTaint, Node } from "../../../common/k8s-api/endpoints";
@@ -23,7 +23,8 @@ import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.inj
import type { PodStore } from "../+workloads-pods/store"; import type { PodStore } from "../+workloads-pods/store";
import podStoreInjectable from "../+workloads-pods/store.injectable"; import podStoreInjectable from "../+workloads-pods/store.injectable";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import loadPodsFromAllNamespacesInjectable from "../+workloads-pods/load-pods-from-all-namespaces.injectable"; import loadPodsFromAllNamespacesInjectable
from "../+workloads-pods/load-pods-from-all-namespaces.injectable";
export interface NodeDetailsProps extends KubeObjectDetailsProps<Node> { export interface NodeDetailsProps extends KubeObjectDetailsProps<Node> {
} }
@@ -97,14 +98,6 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
</DrawerItem> </DrawerItem>
</> </>
)} )}
<DrawerItemLabels
name="Labels"
labels={node.getLabels()}
/>
<DrawerItemLabels
name="Annotations"
labels={node.getAnnotations()}
/>
{taints.length > 0 && ( {taints.length > 0 && (
<DrawerItem name="Taints" labelsOnly> <DrawerItem name="Taints" labelsOnly>
{taints.map(taint => <Badge key={taint.key} label={formatNodeTaint(taint)} />)} {taints.map(taint => <Badge key={taint.key} label={formatNodeTaint(taint)} />)}
@@ -78,7 +78,7 @@ class NonInjectedDeploymentReplicaSets extends React.Component<DeploymentReplica
sortSyncWithUrl={false} sortSyncWithUrl={false}
className="box grow" className="box grow"
> >
<TableHead flat> <TableHead flat sticky={false}>
<TableCell className="name" sortBy={sortBy.name}>Name</TableCell> <TableCell className="name" sortBy={sortBy.name}>Name</TableCell>
<TableCell className="warning"/> <TableCell className="warning"/>
<TableCell className="namespace" sortBy={sortBy.namespace}>Namespace</TableCell> <TableCell className="namespace" sortBy={sortBy.namespace}>Namespace</TableCell>
@@ -190,7 +190,7 @@ class NonInjectedPodDetailsList extends React.Component<PodDetailsListProps & De
)} )}
className="box grow" className="box grow"
> >
<TableHead flat> <TableHead flat sticky={virtual}>
<TableCell className="name" sortBy={sortBy.name}>Name</TableCell> <TableCell className="name" sortBy={sortBy.name}>Name</TableCell>
<TableCell className="warning"/> <TableCell className="warning"/>
<TableCell className="node" sortBy={sortBy.node}>Node</TableCell> <TableCell className="node" sortBy={sortBy.node}>Node</TableCell>
@@ -0,0 +1,7 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export * from "./replicationcontrollers";
export * from "./replicationcontroller-details";
@@ -0,0 +1,24 @@
/**
* 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 { ReplicationControllers } from "./replicationcontrollers";
import {
routeSpecificComponentInjectionToken,
} from "../../routes/route-specific-component-injection-token";
import replicationControllersRouteInjectable
from "../../../common/front-end-routing/routes/cluster/workloads/replicationcontrollers/replicationcontrollers-route.injectable";
const replicationControllersRouteComponentInjectable = getInjectable({
id: "replicationcontroller-route-component",
instantiate: (di) => ({
route: di.inject(replicationControllersRouteInjectable),
Component: ReplicationControllers,
}),
injectionToken: routeSpecificComponentInjectionToken,
});
export default replicationControllersRouteComponentInjectable;
@@ -0,0 +1,16 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
.ReplicationControllerDetails {
.replicas {
display: flex;
gap: calc(var(--margin) * 2);
align-items: center;
> * {
flex-shrink: 0;
}
}
}
@@ -0,0 +1,122 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import styles from "./replicationcontroller-details.module.scss";
import React from "react";
import { action, makeObservable, observable } from "mobx";
import { observer } from "mobx-react";
import { withInjectables } from "@ogre-tools/injectable-react";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import type { KubeObjectDetailsProps } from "../kube-object-details";
import type {
ReplicationController,
ReplicationControllerApi,
} from "../../../common/k8s-api/endpoints";
import replicationControllerApiInjectable
from "../../../common/k8s-api/endpoints/replication-controller.api.injectable";
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
import type { ShowNotification } from "../notifications";
import { Slider } from "../slider";
export interface ReplicationControllerDetailsProps extends KubeObjectDetailsProps<ReplicationController> {
}
interface Dependencies {
api: ReplicationControllerApi;
showNotificationError: ShowNotification;
}
@observer
class NonInjectedReplicationControllerDetails<Props extends ReplicationControllerDetailsProps & Dependencies> extends React.Component<Props> {
@observable sliderReplicasValue = this.props.object.getDesiredReplicas();
@observable sliderReplicasDisabled = false;
constructor(props: Props) {
super(props);
makeObservable(this);
}
@action
async scale(replicas: number) {
const { object: resource, api, showNotificationError } = this.props;
try {
await api.scale({
name: resource.getName(),
namespace: resource.getNs(),
}, replicas);
} catch (error) {
this.sliderReplicasValue = resource.getDesiredReplicas(); // rollback to last valid value
showNotificationError(error as Error);
}
}
@action
async onScaleSliderChangeCommitted(evt: React.FormEvent<any>, replicas: number) {
this.sliderReplicasDisabled = true;
await this.scale(replicas);
this.sliderReplicasDisabled = false;
}
render() {
const { object: resource } = this.props;
return (
<div className={styles.ReplicationControllerDetails}>
<DrawerTitle>
Spec
</DrawerTitle>
<DrawerItem name="Replicas">
<div className={styles.replicas}>
<div>{resource.getDesiredReplicas()}</div>
<div>Scale</div>
<Slider
min={0}
max={100}
valueLabelDisplay="auto"
disabled={this.sliderReplicasDisabled}
value={this.sliderReplicasValue}
onChange={(evt, value) => this.sliderReplicasValue = value}
onChangeCommitted={(event, value) => this.onScaleSliderChangeCommitted(event, value as number)}
/>
</div>
</DrawerItem>
<DrawerItem name="Selectors" labelsOnly>
{
resource.getSelectorLabels().map(label => (<Badge key={label} label={label} />))
}
</DrawerItem>
<DrawerTitle>
Status
</DrawerTitle>
<DrawerItem name="Replicas">
{resource.getReplicas()}
</DrawerItem>
<DrawerItem name="Available Replicas">
{resource.getAvailableReplicas()}
</DrawerItem>
<DrawerItem name="Labeled Replicas">
{resource.getLabeledReplicas()}
</DrawerItem>
<DrawerItem name="Controller Generation">
{resource.getGeneration()}
</DrawerItem>
<DrawerItem name="Minimum Pod Readiness">
{`${resource.getMinReadySeconds()} seconds`}
</DrawerItem>
</div>
);
}
}
export const ReplicationControllerDetails = withInjectables<Dependencies, ReplicationControllerDetailsProps>(NonInjectedReplicationControllerDetails, {
getProps: (di, props) => ({
...props,
api: di.inject(replicationControllerApiInjectable),
showNotificationError: di.inject(showErrorNotificationInjectable),
}),
});
@@ -0,0 +1,39 @@
/**
* 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 { computed } from "mobx";
import { workloadsSidebarItemId } from "../+workloads/workloads-sidebar-items.injectable";
import { sidebarItemsInjectionToken } from "../layout/sidebar-items.injectable";
import routeIsActiveInjectable from "../../routes/route-is-active.injectable";
import replicationControllersRouteInjectable
from "../../../common/front-end-routing/routes/cluster/workloads/replicationcontrollers/replicationcontrollers-route.injectable";
import navigateToReplicationControllersInjectable
from "../../../common/front-end-routing/routes/cluster/workloads/replicationcontrollers/navigate-to-replication-controllers.injectable";
const replicationControllerSidebarItemsInjectable = getInjectable({
id: "replicationctrl-sidebar-items",
instantiate: (di) => {
const route = di.inject(replicationControllersRouteInjectable);
const navigateToPage = di.inject(navigateToReplicationControllersInjectable);
const routeIsActive = di.inject(routeIsActiveInjectable, route);
return computed(() => [
{
id: "replication-controllers",
parentId: workloadsSidebarItemId,
title: "Replication Controllers",
onClick: navigateToPage,
isActive: routeIsActive,
isVisible: route.isEnabled,
orderNumber: 61,
},
]);
},
injectionToken: sidebarItemsInjectionToken,
});
export default replicationControllerSidebarItemsInjectable;
@@ -0,0 +1,26 @@
/**
* 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 { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/kube-object-store-token";
import { ReplicationControllerStore } from "./replicationcontroller-store";
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import replicationControllerApiInjectable
from "../../../common/k8s-api/endpoints/replication-controller.api.injectable";
const replicationControllerStoreInjectable = getInjectable({
id: "replication-controller-store",
instantiate: (di) => {
const api = di.inject(replicationControllerApiInjectable);
return new ReplicationControllerStore({
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
logger: di.inject(loggerInjectable),
}, api);
},
injectionToken: kubeObjectStoreInjectionToken,
});
export default replicationControllerStoreInjectable;
@@ -0,0 +1,23 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type {
ReplicationController,
ReplicationControllerApi,
} from "../../../common/k8s-api/endpoints";
import type {
KubeObjectStoreDependencies,
KubeObjectStoreOptions,
} from "../../../common/k8s-api/kube-object.store";
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
export interface ReplicationControllerStoreDependencies extends KubeObjectStoreDependencies {
}
export class ReplicationControllerStore extends KubeObjectStore<ReplicationController, ReplicationControllerApi> {
constructor(protected readonly dependencies: ReplicationControllerStoreDependencies, api: ReplicationControllerApi, opts?: KubeObjectStoreOptions) {
super(dependencies, api, opts);
}
}
@@ -0,0 +1,8 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
.ReplicationControllers {
}
@@ -0,0 +1,86 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import styles from "./replicationcontrollers.module.scss";
import React from "react";
import { observer } from "mobx-react";
import { KubeObjectListLayout } from "../kube-object-list-layout";
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
import type { ReplicationControllerStore } from "./replicationcontroller-store";
import { withInjectables } from "@ogre-tools/injectable-react";
import replicationControllerStoreInjectable from "./replicationcontroller-store.injectable";
import { NamespaceSelectBadge } from "../+namespaces/namespace-select-badge";
import { Badge } from "../badge";
enum columnId {
name = "name",
namespace = "namespace",
replicas = "replicas",
replicasDesired = "replicasDesired",
selector = "selector",
}
interface Dependencies {
store: ReplicationControllerStore;
}
const NonInjectedReplicationControllers = observer((props: Dependencies) => {
return (
<SiblingsInTabLayout>
<KubeObjectListLayout
isConfigurable
tableId="workload_replicationcontrollers"
className={styles.ReplicationControllers}
store={props.store}
sortingCallbacks={{
[columnId.name]: item => item.getName(),
[columnId.namespace]: item => item.getNs(),
[columnId.selector]: item => item.getSelectorLabels(),
[columnId.replicas]: item => item.getReplicas(),
[columnId.replicasDesired]: item => item.getDesiredReplicas(),
}}
searchFilters={[
item => item.getSearchFields(),
item => item.getSelectorLabels(),
]}
renderHeaderTitle="Replication Controllers"
renderTableHeader={[
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
{
title: "Namespace",
className: "namespace",
sortBy: columnId.namespace,
id: columnId.namespace,
},
{ title: "Replicas", sortBy: columnId.replicas, id: columnId.replicas },
{
title: "Desired Replicas",
sortBy: columnId.replicasDesired,
id: columnId.replicasDesired,
},
{
title: "Selector",
sortBy: columnId.selector,
id: columnId.selector,
},
]}
renderTableContents={item => [
item.getName(),
<NamespaceSelectBadge key="namespace" namespace={item.getNs()} />,
item.getReplicas(),
item.getDesiredReplicas(),
item.getSelectorLabels().map(label => (<Badge key={label} label={label} />)),
]}
/>
</SiblingsInTabLayout>
);
});
export const ReplicationControllers = withInjectables<Dependencies>(NonInjectedReplicationControllers, {
getProps: (di, props) => ({
...props,
store: di.inject(replicationControllerStoreInjectable),
}),
});
@@ -142,7 +142,6 @@ class NonInjectedCreateResource extends React.Component<CreateResourceProps & De
options={this.props.createResourceTemplates.get()} options={this.props.createResourceTemplates.get()}
formatGroupLabel={group => group.label} formatGroupLabel={group => group.label}
menuPlacement="top" menuPlacement="top"
themeName="outlined"
onChange={(option) => { onChange={(option) => {
if (option) { if (option) {
this.props.createResourceTabStore.setData(this.tabId, option.value); this.props.createResourceTabStore.setData(this.tabId, option.value);
@@ -93,14 +93,12 @@ const NonInjectedInstallChart = observer(
options={version.options.get()} options={version.options.get()}
onChange={(changed) => version.onChange(changed?.value)} onChange={(changed) => version.onChange(changed?.value)}
menuPlacement="top" menuPlacement="top"
themeName="outlined"
id={`install-chart-version-select-for-${tabId}`} id={`install-chart-version-select-for-${tabId}`}
/> />
<span>Namespace</span> <span>Namespace</span>
<NamespaceSelect <NamespaceSelect
showIcons={false} showIcons={false}
menuPlacement="top" menuPlacement="top"
themeName="outlined"
value={namespace.value.get()} value={namespace.value.get()}
onChange={namespace.onChange} onChange={namespace.onChange}
id={`install-chart-namespace-select-for-${tabId}`} id={`install-chart-namespace-select-for-${tabId}`}
@@ -7,10 +7,6 @@
--overlay-bg: #8cc474b8; --overlay-bg: #8cc474b8;
--overlay-active-bg: orange; --overlay-active-bg: orange;
// fix for `this.logsElement.scrollTop = this.logsElement.scrollHeight`
// `overflow: overlay` don't allow scroll to the last line
overflow: auto;
position: relative; position: relative;
color: var(--logsForeground); color: var(--logsForeground);
background: var(--logsBackground); background: var(--logsBackground);
@@ -21,6 +17,7 @@
.list { .list {
overflow-x: scroll!important; overflow-x: scroll!important;
overflow-y: auto!important;
.LogRow { .LogRow {
padding: 2px 16px; padding: 2px 16px;
@@ -28,7 +28,7 @@ export interface InstantiateArgs {
const logsViewModelInjectable = getInjectable({ const logsViewModelInjectable = getInjectable({
id: "logs-view-model", id: "logs-view-model",
instantiate: (di, { tabId }: InstantiateArgs) => new LogTabViewModel(tabId, { instantiate: (di, tabId) => new LogTabViewModel(tabId, {
getLogs: di.inject(getLogsInjectable), getLogs: di.inject(getLogsInjectable),
getLogsWithoutTimestamps: di.inject(getLogsWithoutTimestampsInjectable), getLogsWithoutTimestamps: di.inject(getLogsWithoutTimestampsInjectable),
getTimestampSplitLogs: di.inject(getTimestampSplitLogsInjectable), getTimestampSplitLogs: di.inject(getTimestampSplitLogsInjectable),
@@ -45,7 +45,10 @@ const logsViewModelInjectable = getInjectable({
downloadAllLogs: di.inject(downloadAllLogsInjectable), downloadAllLogs: di.inject(downloadAllLogsInjectable),
searchStore: di.inject(searchStoreInjectable), searchStore: di.inject(searchStoreInjectable),
}), }),
lifecycle: lifecycleEnum.transient,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, tabId: TabId) => `log-tab-view-model-${tabId}}`,
}),
}); });
export default logsViewModelInjectable; export default logsViewModelInjectable;
@@ -101,9 +101,7 @@ const NonInjectedLogsDockTab = observer(({
export const LogsDockTab = withInjectables<Dependencies, LogsDockTabProps>(NonInjectedLogsDockTab, { export const LogsDockTab = withInjectables<Dependencies, LogsDockTabProps>(NonInjectedLogsDockTab, {
getProps: (di, props) => ({ getProps: (di, props) => ({
...props, ...props,
model: di.inject(logsViewModelInjectable, { model: di.inject(logsViewModelInjectable, props.tab.id),
tabId: props.tab.id,
}),
subscribeStores: di.inject(subscribeStoresInjectable), subscribeStores: di.inject(subscribeStoresInjectable),
podStore: di.inject(podStoreInjectable), podStore: di.inject(podStoreInjectable),
}), }),
@@ -81,7 +81,6 @@ export class NonInjectedUpgradeChart extends React.Component<UpgradeChartProps &
id="char-version-input" id="char-version-input"
className="chart-version" className="chart-version"
menuPlacement="top" menuPlacement="top"
themeName="outlined"
value={model.version.value.get()} value={model.version.value.get()}
options={model.versionOptions.get()} options={model.versionOptions.get()}
onChange={model.version.set} onChange={model.version.set}
@@ -0,0 +1,35 @@
/**
* 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 { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token";
import { computed } from "mobx";
import {
kubeObjectMatchesToKindAndApiVersion,
} from "../kube-object-matches-to-kind-and-api-version";
import currentKubeObjectInDetailsInjectable from "../../current-kube-object-in-details.injectable";
import { ReplicationControllerDetails } from "../../../+workloads-replicationcontrollers";
const replicationControllerDetailItemInjectable = getInjectable({
id: "replication-controller-detail-item",
instantiate(di) {
const kubeObject = di.inject(currentKubeObjectInDetailsInjectable);
return {
Component: ReplicationControllerDetails,
enabled: computed(() => isReplicationController(kubeObject.value.get()?.object)),
orderNumber: 10,
};
},
injectionToken: kubeObjectDetailItemInjectionToken,
});
export const isReplicationController = kubeObjectMatchesToKindAndApiVersion(
"ReplicationController",
["v1"],
);
export default replicationControllerDetailItemInjectable;
@@ -19,6 +19,8 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import type { NamespaceApi } from "../../../common/k8s-api/endpoints";
import namespaceApiInjectable from "../../../common/k8s-api/endpoints/namespace.api.injectable";
export interface KubeObjectMetaProps { export interface KubeObjectMetaProps {
object: KubeObject; object: KubeObject;
@@ -28,20 +30,24 @@ export interface KubeObjectMetaProps {
interface Dependencies { interface Dependencies {
getDetailsUrl: GetDetailsUrl; getDetailsUrl: GetDetailsUrl;
apiManager: ApiManager; apiManager: ApiManager;
namespaceApi: NamespaceApi;
logger: Logger; logger: Logger;
} }
const NonInjectedKubeObjectMeta = observer(({ const NonInjectedKubeObjectMeta = observer((
apiManager, {
getDetailsUrl, apiManager,
object, getDetailsUrl,
hideFields = [ object,
"uid", hideFields = [
"resourceVersion", "uid",
"selfLink", "resourceVersion",
], "selfLink",
logger, ],
}: Dependencies & KubeObjectMetaProps) => { logger,
namespaceApi,
}
: Dependencies & KubeObjectMetaProps) => {
if (!object) { if (!object) {
return null; return null;
} }
@@ -59,6 +65,10 @@ const NonInjectedKubeObjectMeta = observer(({
getFinalizers, getId, getName, metadata: { creationTimestamp }, getFinalizers, getId, getName, metadata: { creationTimestamp },
} = object; } = object;
const ownerRefs = object.getOwnerRefs(); const ownerRefs = object.getOwnerRefs();
const namespace = getNs();
const namespaceDetailsUrl = namespace ? getDetailsUrl(
namespaceApi.formatUrlForNotListing({ name: namespace }),
) : "";
return ( return (
<> <>
@@ -71,8 +81,8 @@ const NonInjectedKubeObjectMeta = observer(({
{getName()} {getName()}
<KubeObjectStatusIcon key="icon" object={object} /> <KubeObjectStatusIcon key="icon" object={object} />
</DrawerItem> </DrawerItem>
<DrawerItem name="Namespace" hidden={isHidden("namespace") || !getNs()}> <DrawerItem name="Namespace" hidden={isHidden("namespace") || !namespace}>
{getNs()} <Link to={namespaceDetailsUrl}>{namespace}</Link>
</DrawerItem> </DrawerItem>
<DrawerItem name="UID" hidden={isHidden("uid")}> <DrawerItem name="UID" hidden={isHidden("uid")}>
{getId()} {getId()}
@@ -122,5 +132,6 @@ export const KubeObjectMeta = withInjectables<Dependencies, KubeObjectMetaProps>
getDetailsUrl: di.inject(getDetailsUrlInjectable), getDetailsUrl: di.inject(getDetailsUrlInjectable),
apiManager: di.inject(apiManagerInjectable), apiManager: di.inject(apiManagerInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
namespaceApi: di.inject(namespaceApiInjectable),
}), }),
}); });
@@ -15,6 +15,7 @@ export interface ClusterPageMenuRegistration {
title: React.ReactNode; title: React.ReactNode;
components: ClusterPageMenuComponents; components: ClusterPageMenuComponents;
visible?: IComputedValue<boolean>; visible?: IComputedValue<boolean>;
orderNumber?: number;
} }
export interface ClusterPageMenuComponents { export interface ClusterPageMenuComponents {
@@ -57,7 +57,7 @@ const extensionSidebarItemRegistratorInjectable = getInjectable({
const res: SidebarItemRegistration = { const res: SidebarItemRegistration = {
id: `${extension.sanitizedExtensionId}-${registration.id}`, id: `${extension.sanitizedExtensionId}-${registration.id}`,
orderNumber: 9999, orderNumber: registration.orderNumber ?? 9999,
parentId: registration.parentId parentId: registration.parentId
? `${extension.sanitizedExtensionId}-${registration.parentId}` ? `${extension.sanitizedExtensionId}-${registration.parentId}`
@@ -43,10 +43,6 @@ html {
} }
} }
&__value-container {
margin-bottom: 1px;
}
&__single-value { &__single-value {
color: var(--textColorSecondary); color: var(--textColorSecondary);
overflow: visible; overflow: visible;
@@ -93,6 +89,8 @@ html {
&__option { &__option {
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
border-radius: 3px;
padding: 6px 8px;
&:active { &:active {
background: var(--primary); background: var(--primary);
@@ -179,21 +177,6 @@ html {
} }
} }
&.theme-outlined {
.Select__control {
box-shadow: 0 0 0 1px var(--colorVague);
color: var(--primary);
.Select__value-container {
padding: 0 $padding * 0.5;
}
.Select__dropdown-indicator {
padding: 3px;
}
}
}
&.theme-lens { &.theme-lens {
:hover { :hover {
&.Select__control { &.Select__control {
@@ -38,7 +38,6 @@
} }
&.flat { &.flat {
background-color: transparent;
font-weight: 600; font-weight: 600;
} }
} }
Loaded 100 of 158 files, more files were not shown because too many files have changed in this diff. Show more