diff --git a/Makefile b/Makefile index 86cdf24e95..068116b3ba 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,10 @@ compile-dev: yarn compile:renderer --cache dev: - test -f out/main.js || make init - yarn dev # run electron and watch files +ifeq ("$(wildcard static/build/main.js)","") + make init +endif + yarn dev lint: yarn lint @@ -53,6 +55,12 @@ else endif clean: +ifeq "$(DETECTED_OS)" "Windows" + if exist binaries\client del /s /q binaries\client\*.* + if exist dist del /s /q dist\*.* + if exist static\build del /s /q static\build\*.* +else rm -rf binaries/client/* rm -rf dist/* - rm -rf out/* + rm -rf static/build/* +endif \ No newline at end of file diff --git a/locales/en/messages.po b/locales/en/messages.po index 46d7fdae36..8859dde6a8 100644 --- a/locales/en/messages.po +++ b/locales/en/messages.po @@ -79,7 +79,7 @@ msgid "Account Name" msgstr "Account Name" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:51 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:46 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:50 msgid "Active" msgstr "Active" @@ -173,7 +173,7 @@ msgstr "Affinities" #: src/renderer/components/+user-management-roles/roles.tsx:35 #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:38 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:38 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:52 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:50 #: src/renderer/components/+workloads-deployments/deployments.tsx:63 #: src/renderer/components/+workloads-jobs/jobs.tsx:41 @@ -675,7 +675,7 @@ msgstr "Created at" msgid "Credentials Ref" msgstr "Credentials Ref" -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:40 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 msgid "Cron Jobs" msgstr "Cron Jobs" @@ -1154,6 +1154,10 @@ msgstr "Item list is empty" msgid "JSON Path" msgstr "JSON Path" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:91 +msgid "Job name" +msgstr "Job name" + #: src/renderer/components/+workloads/workloads.tsx:69 #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62 #: src/renderer/components/+workloads-jobs/jobs.tsx:36 @@ -1218,7 +1222,7 @@ msgid "Last Failure Time" msgstr "Last Failure Time" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:57 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:51 msgid "Last schedule" msgstr "Last schedule" @@ -1448,7 +1452,7 @@ msgstr "Mounts" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:35 #: src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx:29 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:36 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:41 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:45 #: src/renderer/components/+workloads-deployments/deployments.tsx:58 #: src/renderer/components/+workloads-jobs/jobs.tsx:37 @@ -1498,7 +1502,7 @@ msgstr "Names" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:37 #: src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx:79 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:37 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:43 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:46 #: src/renderer/components/+workloads-deployments/deployments.tsx:59 #: src/renderer/components/+workloads-jobs/jobs.tsx:38 @@ -2155,7 +2159,7 @@ msgid "Scale Deployment <0>{deploymentName}" msgstr "Scale Deployment <0>{deploymentName}" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:46 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 msgid "Schedule" msgstr "Schedule" @@ -2413,7 +2417,7 @@ msgid "Supplemental Groups" msgstr "Supplemental Groups" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:54 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:49 msgid "Suspend" msgstr "Suspend" @@ -2482,6 +2486,16 @@ msgstr "Tolerations" msgid "Transmit" msgstr "Transmit" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80 +msgid "Trigger" +msgstr "Trigger" + +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103 +msgid "Trigger CronJob <0>{cronjobName}" +msgstr "Trigger CronJob <0>{cronjobName}" + #: src/renderer/components/+cluster/cluster-issues.tsx:102 #: src/renderer/components/+config-secrets/secret-details.tsx:74 #: src/renderer/components/+config-secrets/secrets.tsx:45 @@ -2717,7 +2731,7 @@ msgid "listKind" msgstr "listKind" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:48 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:57 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:61 msgid "never" msgstr "never" diff --git a/locales/fi/messages.po b/locales/fi/messages.po index 8e41f2b6a2..464a49bf9e 100644 --- a/locales/fi/messages.po +++ b/locales/fi/messages.po @@ -79,7 +79,7 @@ msgid "Account Name" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:51 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:46 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:50 msgid "Active" msgstr "" @@ -173,7 +173,7 @@ msgstr "" #: src/renderer/components/+user-management-roles/roles.tsx:35 #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:38 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:38 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:52 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:50 #: src/renderer/components/+workloads-deployments/deployments.tsx:63 #: src/renderer/components/+workloads-jobs/jobs.tsx:41 @@ -671,7 +671,7 @@ msgstr "" msgid "Credentials Ref" msgstr "" -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:40 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 msgid "Cron Jobs" msgstr "" @@ -1145,6 +1145,10 @@ msgstr "" msgid "JSON Path" msgstr "" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:91 +msgid "Job name" +msgstr "" + #: src/renderer/components/+workloads/workloads.tsx:69 #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62 #: src/renderer/components/+workloads-jobs/jobs.tsx:36 @@ -1209,7 +1213,7 @@ msgid "Last Failure Time" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:57 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:51 msgid "Last schedule" msgstr "" @@ -1439,7 +1443,7 @@ msgstr "" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:35 #: src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx:29 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:36 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:41 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:45 #: src/renderer/components/+workloads-deployments/deployments.tsx:58 #: src/renderer/components/+workloads-jobs/jobs.tsx:37 @@ -1489,7 +1493,7 @@ msgstr "" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:37 #: src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx:79 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:37 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:43 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:46 #: src/renderer/components/+workloads-deployments/deployments.tsx:59 #: src/renderer/components/+workloads-jobs/jobs.tsx:38 @@ -2138,7 +2142,7 @@ msgid "Scale Deployment <0>{deploymentName}" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:46 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 msgid "Schedule" msgstr "" @@ -2396,7 +2400,7 @@ msgid "Supplemental Groups" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:54 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:49 msgid "Suspend" msgstr "" @@ -2465,6 +2469,16 @@ msgstr "" msgid "Transmit" msgstr "" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80 +msgid "Trigger" +msgstr "" + +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103 +msgid "Trigger CronJob <0>{cronjobName}" +msgstr "" + #: src/renderer/components/+cluster/cluster-issues.tsx:102 #: src/renderer/components/+config-secrets/secret-details.tsx:74 #: src/renderer/components/+config-secrets/secrets.tsx:45 @@ -2700,7 +2714,7 @@ msgid "listKind" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:48 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:57 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:61 msgid "never" msgstr "" diff --git a/locales/ru/messages.po b/locales/ru/messages.po index adcbd19aed..0200d47b72 100644 --- a/locales/ru/messages.po +++ b/locales/ru/messages.po @@ -80,7 +80,7 @@ msgid "Account Name" msgstr "Название аккаунта" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:51 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:46 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:50 msgid "Active" msgstr "Активный" @@ -174,7 +174,7 @@ msgstr "Аффинитеты" #: src/renderer/components/+user-management-roles/roles.tsx:35 #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:38 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:38 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:52 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:50 #: src/renderer/components/+workloads-deployments/deployments.tsx:63 #: src/renderer/components/+workloads-jobs/jobs.tsx:41 @@ -676,7 +676,7 @@ msgstr "Создано" msgid "Credentials Ref" msgstr "Credentials Ref" -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:40 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 msgid "Cron Jobs" msgstr "" @@ -1155,6 +1155,10 @@ msgstr "Список пуст" msgid "JSON Path" msgstr "" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:91 +msgid "Job name" +msgstr "" + #: src/renderer/components/+workloads/workloads.tsx:69 #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:62 #: src/renderer/components/+workloads-jobs/jobs.tsx:36 @@ -1219,7 +1223,7 @@ msgid "Last Failure Time" msgstr "Время последнего сбоя" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:57 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:51 msgid "Last schedule" msgstr "Последний запуск" @@ -1449,7 +1453,7 @@ msgstr "Установки" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:35 #: src/renderer/components/+user-management-service-accounts/service-accounts-secret.tsx:29 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:36 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:41 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:45 #: src/renderer/components/+workloads-deployments/deployments.tsx:58 #: src/renderer/components/+workloads-jobs/jobs.tsx:37 @@ -1499,7 +1503,7 @@ msgstr "" #: src/renderer/components/+user-management-roles-bindings/role-bindings.tsx:37 #: src/renderer/components/+user-management-service-accounts/create-service-account-dialog.tsx:79 #: src/renderer/components/+user-management-service-accounts/service-accounts.tsx:37 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:43 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:47 #: src/renderer/components/+workloads-daemonsets/daemonsets.tsx:46 #: src/renderer/components/+workloads-deployments/deployments.tsx:59 #: src/renderer/components/+workloads-jobs/jobs.tsx:38 @@ -2156,7 +2160,7 @@ msgid "Scale Deployment <0>{deploymentName}" msgstr "Масштабировать Deployment <0>{deploymentName}" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:46 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:44 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:48 msgid "Schedule" msgstr "Расписание" @@ -2414,7 +2418,7 @@ msgid "Supplemental Groups" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:54 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:45 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:49 msgid "Suspend" msgstr "Заморозка" @@ -2483,6 +2487,16 @@ msgstr "Толерантности" msgid "Transmit" msgstr "Транзит" +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:107 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:79 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:80 +msgid "Trigger" +msgstr "" + +#: src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx:103 +msgid "Trigger CronJob <0>{cronjobName}" +msgstr "" + #: src/renderer/components/+cluster/cluster-issues.tsx:102 #: src/renderer/components/+config-secrets/secret-details.tsx:74 #: src/renderer/components/+config-secrets/secrets.tsx:45 @@ -2718,7 +2732,7 @@ msgid "listKind" msgstr "" #: src/renderer/components/+workloads-cronjobs/cronjob-details.tsx:48 -#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:57 +#: src/renderer/components/+workloads-cronjobs/cronjobs.tsx:61 msgid "never" msgstr "" diff --git a/package.json b/package.json index d4581123b0..54e4038c77 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ }, "scripts": { "dev": "concurrently -k \"yarn dev-run -C\" \"yarn dev:main\" \"yarn dev:renderer\"", - "dev-run": "nodemon --watch static/build/main.js --exec \"electron --inspect .\" $@", - "dev:main": "env DEBUG=true yarn compile:main --watch $@", - "dev:renderer": "env DEBUG=true yarn compile:renderer --watch $@", + "dev-run": "cross-env DEBUG=true nodemon --watch static/build/main.js --exec \"electron --inspect .\"", + "dev:main": "cross-env DEBUG=true yarn compile:main --watch", + "dev:renderer": "cross-env DEBUG=true yarn compile:renderer --watch", "compile": "env NODE_ENV=production concurrently yarn:compile:*", "compile:main": "webpack --config webpack.main.ts", "compile:renderer": "webpack --config webpack.renderer.ts", @@ -175,6 +175,7 @@ "crypto-js": "^4.0.0", "electron-updater": "^4.3.1", "electron-window-state": "^5.0.3", + "file-type": "^14.7.1", "filenamify": "^4.1.0", "fs-extra": "^9.0.1", "handlebars": "^4.7.6", @@ -184,6 +185,7 @@ "jsonpath": "^1.0.2", "lodash": "^4.17.15", "mac-ca": "^1.0.4", + "make-synchronous": "^0.1.1", "marked": "^1.1.0", "md5-file": "^5.0.0", "mobx": "^5.15.5", @@ -264,6 +266,7 @@ "circular-dependency-plugin": "^5.2.0", "color": "^3.1.2", "concurrently": "^5.2.0", + "cross-env": "^7.0.2", "css-element-queries": "^1.2.3", "css-loader": "^3.5.3", "dompurify": "^2.0.11", diff --git a/src/common/cluster-store.ts b/src/common/cluster-store.ts index ad25f43f26..6e9930f5ad 100644 --- a/src/common/cluster-store.ts +++ b/src/common/cluster-store.ts @@ -1,6 +1,5 @@ import type { WorkspaceId } from "./workspace-store"; -import path from "path"; -import { app, ipcRenderer, remote } from "electron"; +import { ipcRenderer } from "electron"; import { unlink } from "fs-extra"; import { action, computed, observable, toJS } from "mobx"; import { BaseStore } from "./base-store"; @@ -50,11 +49,6 @@ export interface ClusterPreferences { } export class ClusterStore extends BaseStore { - static get iconsDir() { - // TODO: remove remote cheat - return path.join((app || remote.app).getPath("userData"), "icons"); - } - private constructor() { super({ configName: "lens-cluster-store", diff --git a/src/common/cluster-store_test.ts b/src/common/cluster-store_test.ts index 3fc3e0b60e..6e5b99dbaf 100644 --- a/src/common/cluster-store_test.ts +++ b/src/common/cluster-store_test.ts @@ -6,6 +6,10 @@ import { ClusterStore } from "./cluster-store"; import { workspaceStore } from "./workspace-store"; import { saveConfigToAppFiles } from "./kube-helpers"; +const testDataIcon = fs.readFileSync("test-data/cluster-store-migration-icon.png") + +console.log("") // fix bug + let clusterStore: ClusterStore; describe("empty config", () => { @@ -236,12 +240,13 @@ describe("pre 2.6.0 config with a cluster icon", () => { }, cluster1: { kubeConfig: "foo", - icon: "icon path", + icon: "icon_path", preferences: { terminalCWD: "/tmp" } }, - }) + }), + "icon_path": testDataIcon, } } mockFs(mockOpts); @@ -257,7 +262,7 @@ describe("pre 2.6.0 config with a cluster icon", () => { const storedClusterData = clusterStore.clustersList[0]; expect(storedClusterData.hasOwnProperty('icon')).toBe(false); expect(storedClusterData.preferences.hasOwnProperty('icon')).toBe(true); - expect(storedClusterData.preferences.icon).toBe("icon path"); + expect(storedClusterData.preferences.icon.startsWith("data:image/jpeg;base64,")).toBe(true); }) }) @@ -274,7 +279,6 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => { }, cluster1: { kubeConfig: "foo", - icon: "icon path", preferences: { terminalCWD: "/tmp" } @@ -305,16 +309,20 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => { 'lens-cluster-store.json': JSON.stringify({ __internal__: { migrations: { - version: "2.7.0" + version: "3.5.0" } }, clusters: [ { id: 'cluster1', - kubeConfig: 'kubeconfig content' + kubeConfig: 'kubeconfig content', + preferences: { + icon: "store://icon_path", + } } ] - }) + }), + "icon_path": testDataIcon, } }; mockFs(mockOpts); @@ -330,4 +338,9 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => { const config = clusterStore.clustersList[0].kubeConfigPath; expect(fs.readFileSync(config, "utf8")).toBe("kubeconfig content"); }) + + it("migrates to modern format with icon not in file", async () => { + const { icon } = clusterStore.clustersList[0].preferences; + expect(icon.startsWith("data:image/jpeg;base64, ")).toBe(true); + }) }) \ No newline at end of file diff --git a/src/migrations/cluster-store/2.7.0-beta.0.ts b/src/migrations/cluster-store/2.7.0-beta.0.ts index 22c4e6bba9..3e0ae9337f 100644 --- a/src/migrations/cluster-store/2.7.0-beta.0.ts +++ b/src/migrations/cluster-store/2.7.0-beta.0.ts @@ -6,7 +6,7 @@ export default migration({ run(store, log) { for (const value of store) { const clusterKey = value[0]; - if(clusterKey === "__internal__") continue + if (clusterKey === "__internal__") continue const cluster = value[1]; cluster.workspace = "default" store.set(clusterKey, cluster) diff --git a/src/migrations/cluster-store/3.6.0-beta.1.ts b/src/migrations/cluster-store/3.6.0-beta.1.ts index adc354d9ef..db39cb741d 100644 --- a/src/migrations/cluster-store/3.6.0-beta.1.ts +++ b/src/migrations/cluster-store/3.6.0-beta.1.ts @@ -1,34 +1,71 @@ // Move embedded kubeconfig into separate file and add reference to it to cluster settings +// convert file path cluster icons to their base64 encoded versions import path from "path" import { app, remote } from "electron" import { migration } from "../migration-wrapper"; -import { ensureDirSync } from "fs-extra" +import fse from "fs-extra" import { ClusterModel } from "../../common/cluster-store"; import { loadConfig, saveConfigToAppFiles } from "../../common/kube-helpers"; +import makeSynchronous from "make-synchronous" + +const AsyncFunction = Object.getPrototypeOf(async function () { return }).constructor; +const getFileTypeFnString = `return require("file-type").fromBuffer(fileData)`; +const getFileType = new AsyncFunction("fileData", getFileTypeFnString); export default migration({ version: "3.6.0-beta.1", run(store, printLog) { - const migratedClusters: ClusterModel[] = [] - const storedClusters: ClusterModel[] = store.get("clusters"); - const kubeConfigBase = path.join((app || remote.app).getPath("userData"), "kubeconfigs") + const userDataPath = (app || remote.app).getPath("userData") + const kubeConfigBase = path.join(userDataPath, "kubeconfigs") + const storedClusters: ClusterModel[] = store.get("clusters") || []; - if (!storedClusters) return; - ensureDirSync(kubeConfigBase); + if (!storedClusters.length) return; + fse.ensureDirSync(kubeConfigBase); printLog("Number of clusters to migrate: ", storedClusters.length) - for (const cluster of storedClusters) { - try { - // take the embedded kubeconfig and dump it into a file - cluster.kubeConfigPath = saveConfigToAppFiles(cluster.id, cluster.kubeConfig) - cluster.contextName = loadConfig(cluster.kubeConfigPath).getCurrentContext(); - delete cluster.kubeConfig; - migratedClusters.push(cluster) - } catch (error) { - printLog(`Failed to migrate Kubeconfig for cluster "${cluster.id}"`, error) - } - } + const migratedClusters = storedClusters + .map(cluster => { + /** + * migrate kubeconfig + */ + try { + // take the embedded kubeconfig and dump it into a file + cluster.kubeConfigPath = saveConfigToAppFiles(cluster.id, cluster.kubeConfig) + cluster.contextName = loadConfig(cluster.kubeConfigPath).getCurrentContext(); + delete cluster.kubeConfig; + + } catch (error) { + printLog(`Failed to migrate Kubeconfig for cluster "${cluster.id}", removing cluster...`, error) + return undefined; + } + + /** + * migrate cluster icon + */ + try { + if (cluster.preferences?.icon) { + printLog(`migrating ${cluster.preferences.icon} for ${cluster.preferences.clusterName}`) + const iconPath = cluster.preferences.icon.replace("store://", "") + const fileData = fse.readFileSync(path.join(userDataPath, iconPath)); + const { mime = "" } = makeSynchronous(getFileType)(fileData); + + if (!mime) { + printLog(`mime type not detected for ${cluster.preferences.clusterName}'s icon: ${iconPath}`) + } + + cluster.preferences.icon = `data:${mime};base64, ${fileData.toString('base64')}`; + } else { + delete cluster.preferences?.icon; + } + } catch (error) { + printLog(`Failed to migrate cluster icon for cluster "${cluster.id}"`, error) + delete cluster.preferences.icon; + } + + return cluster; + }) + .filter(c => c); // "overwrite" the cluster configs if (migratedClusters.length > 0) { diff --git a/src/renderer/api/endpoints/cron-job.api.ts b/src/renderer/api/endpoints/cron-job.api.ts index e48a8636b8..887ec9833c 100644 --- a/src/renderer/api/endpoints/cron-job.api.ts +++ b/src/renderer/api/endpoints/cron-job.api.ts @@ -32,6 +32,12 @@ export class CronJob extends KubeObject { jobTemplate: { metadata: { creationTimestamp?: string; + labels?: { + [key: string]: string; + }; + annotations?: { + [key: string]: string; + }; }; spec: { template: { @@ -53,7 +59,7 @@ export class CronJob extends KubeObject { failedJobsHistoryLimit: number; } status: { - lastScheduleTime: string; + lastScheduleTime?: string; } getSuspendFlag() { @@ -61,6 +67,7 @@ export class CronJob extends KubeObject { } getLastScheduleTime() { + if (!this.status.lastScheduleTime) return "-" const diff = moment().diff(this.status.lastScheduleTime) return formatDuration(diff, true) } diff --git a/src/renderer/api/endpoints/job.api.ts b/src/renderer/api/endpoints/job.api.ts index d4657605f6..6c6c1967c1 100644 --- a/src/renderer/api/endpoints/job.api.ts +++ b/src/renderer/api/endpoints/job.api.ts @@ -13,7 +13,7 @@ export class Job extends WorkloadKubeObject { parallelism?: number; completions?: number; backoffLimit?: number; - selector: { + selector?: { matchLabels: { [name: string]: string; }; @@ -21,8 +21,11 @@ export class Job extends WorkloadKubeObject { template: { metadata: { creationTimestamp?: string; - labels: { - name: string; + labels?: { + [name: string]: string; + }; + annotations?: { + [name: string]: string; }; }; spec: { @@ -35,7 +38,7 @@ export class Job extends WorkloadKubeObject { nodeSelector?: { [selector: string]: string; }; - tolerations: { + tolerations?: { key: string; operator: string; effect: string; diff --git a/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx index 20b4e6d6d5..04b7ef1fc6 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-icon-setting.tsx @@ -28,7 +28,7 @@ export class ClusterIconSetting extends React.Component { try { if (file) { const buf = Buffer.from(await file.arrayBuffer()); - cluster.preferences.icon = `data:image/jpeg;base64, ${buf.toString('base64')}`; + cluster.preferences.icon = `data:${file.type};base64, ${buf.toString('base64')}`; } else { // this has to be done as a seperate branch (and not always) because `cluster` // is observable and triggers an update loop. diff --git a/src/renderer/components/+landing-page/landing-page.scss b/src/renderer/components/+landing-page/landing-page.scss index 6cc726f5d9..0d05c418d8 100644 --- a/src/renderer/components/+landing-page/landing-page.scss +++ b/src/renderer/components/+landing-page/landing-page.scss @@ -1,8 +1,24 @@ .LandingPage { height: 100%; - background: #282b2f url(../../components/icon/crane.svg) no-repeat; - background-position: 0 35%; - background-size: 85%; - background-clip: content-box; text-align: center; + z-index: 0; + + &::after { + content: ""; + background: url(../../components/icon/crane.svg) no-repeat; + background-position: 0 35%; + background-size: 85%; + background-clip: content-box; + opacity: 1; + top: 0; + left: 0; + bottom: 0; + right: 0; + position: absolute; + z-index: -1; + + .theme-light & { + opacity: 0.2; + } + } } \ No newline at end of file diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.scss b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.scss new file mode 100644 index 0000000000..ef52eebb08 --- /dev/null +++ b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.scss @@ -0,0 +1,18 @@ +.CronJobTriggerDialog { + .Wizard { + .header { + span { + color: #a0a0a0; + white-space: nowrap; + text-overflow: ellipsis; + } + } + + .WizardStep { + .step-content { + min-height: 90px; + overflow: hidden; + } + } + } +} \ No newline at end of file diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx new file mode 100644 index 0000000000..7f29c0478d --- /dev/null +++ b/src/renderer/components/+workloads-cronjobs/cronjob-trigger-dialog.tsx @@ -0,0 +1,127 @@ +import "./cronjob-trigger-dialog.scss"; + +import React, { Component } from "react"; +import { observable } from "mobx"; +import { observer } from "mobx-react"; +import { Trans } from "@lingui/macro"; +import { Dialog, DialogProps } from "../dialog"; +import { Wizard, WizardStep } from "../wizard"; +import { CronJob, cronJobApi, jobApi, Job } from "../../api/endpoints"; +import { Notifications } from "../notifications"; +import { cssNames } from "../../utils"; +import { Input } from "../input"; +import { systemName, maxLength } from "../input/input.validators"; + +interface Props extends Partial { +} + +@observer +export class CronJobTriggerDialog extends Component { + @observable static isOpen = false; + @observable static data: CronJob = null; + + @observable jobName = ""; + + @observable ready = false; + + static open(cronjob: CronJob) { + CronJobTriggerDialog.isOpen = true; + CronJobTriggerDialog.data = cronjob; + } + + static close() { + CronJobTriggerDialog.isOpen = false; + } + + get cronjob() { + return CronJobTriggerDialog.data; + } + + close = () => { + CronJobTriggerDialog.close(); + } + + onOpen = async () => { + const { cronjob } = this; + this.jobName = cronjob ? cronjob.getName() + "-manual-" + Math.random().toString(36).slice(2, 7) : ""; + this.jobName = this.jobName.slice(0, 63); + this.ready = true; + } + + onClose = () => { + this.ready = false; + } + + trigger = async () => { + const { cronjob } = this; + const { close } = this; + try { + const cronjobDefinition = await cronJobApi.get({ + name: cronjob.getName(), + namespace: cronjob.getNs() + }); + + await jobApi.create({ + name: this.jobName, + namespace: cronjob.getNs() + }, { + spec: cronjobDefinition.spec.jobTemplate.spec + }); + + close(); + } catch (err) { + Notifications.error(err); + } + } + + renderContents() { + return ( + <> +
+ Job name: +
+
+ this.jobName = v.toLowerCase()} + className="box grow" + /> +
+ + ) + } + + render() { + const { className, ...dialogProps } = this.props; + const cronjobName = this.cronjob ? this.cronjob.getName() : ""; + const header = ( +
+ Trigger CronJob {cronjobName} +
+ ); + return ( + + + Trigger} + disabledNext={!this.ready} + > + {this.renderContents()} + + + + ); + } +} \ No newline at end of file diff --git a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts b/src/renderer/components/+workloads-cronjobs/cronjob.store.ts index 9e75c25121..e8fa3719ae 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts +++ b/src/renderer/components/+workloads-cronjobs/cronjob.store.ts @@ -9,13 +9,13 @@ export class CronJobStore extends KubeObjectStore { api = cronJobApi getStatuses(cronJobs?: CronJob[]) { - const status = { failed: 0, running: 0 } + const status = { suspended: 0, scheduled: 0 } cronJobs.forEach(cronJob => { if (cronJob.spec.suspend) { - status.failed++ + status.suspended++ } else { - status.running++ + status.scheduled++ } }) return status diff --git a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx index 4221302116..32a2dc50dc 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx @@ -3,8 +3,10 @@ import "./cronjobs.scss"; import React from "react"; import { observer } from "mobx-react"; import { RouteComponentProps } from "react-router"; -import { Trans } from "@lingui/macro"; +import { t, Trans } from "@lingui/macro"; import { CronJob, cronJobApi } from "../../api/endpoints/cron-job.api"; +import { MenuItem } from "../menu"; +import { Icon } from "../icon"; import { cronJobStore } from "./cronjob.store"; import { jobStore } from "../+workloads-jobs/job.store"; import { eventStore } from "../+events/event.store"; @@ -12,7 +14,9 @@ import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object- import { ICronJobsRouteParams } from "../+workloads"; import { KubeObjectListLayout } from "../kube-object"; import { KubeEventIcon } from "../+events/kube-event-icon"; +import { _i18n } from "../../i18n"; import { apiManager } from "../../api/api-manager"; +import { CronJobTriggerDialog } from "./cronjob-trigger-dialog"; enum sortBy { name = "name", @@ -79,8 +83,14 @@ export class CronJobs extends React.Component { } export function CronJobMenu(props: KubeObjectMenuProps) { + const { object, toolbar } = props; return ( - + + CronJobTriggerDialog.open(object)}> + + Trigger + + ) } diff --git a/src/renderer/components/+workloads-overview/overview-workload-status.scss b/src/renderer/components/+workloads-overview/overview-workload-status.scss index c06ed5b4c8..4d47570973 100644 --- a/src/renderer/components/+workloads-overview/overview-workload-status.scss +++ b/src/renderer/components/+workloads-overview/overview-workload-status.scss @@ -3,6 +3,8 @@ --workload-status-pending: #{$pod-status-pending-color}; --workload-status-evicted: #{$pod-status-evicted-color}; --workload-status-succeeded: #{$pod-status-succeeded-color}; + --workload-status-scheduled: #{$cronjob-scheduled}; + --workload-status-suspended: #{$cronjob-suspended}; --workload-status-failed: #{$pod-status-failed-color}; --workload-status-terminated: #{$pod-status-terminated-color}; --workload-status-unknown: #{$pod-status-unknown-color}; diff --git a/src/renderer/components/+workloads/workloads-mixins.scss b/src/renderer/components/+workloads/workloads-mixins.scss index 84bcca8219..8ba7f76665 100644 --- a/src/renderer/components/+workloads/workloads-mixins.scss +++ b/src/renderer/components/+workloads/workloads-mixins.scss @@ -26,6 +26,10 @@ $deployment-replicafailure: $colorError; $job-complete: $colorSuccess; $job-failed: $colorError; +// Cronjob +$cronjob-scheduled: $colorSuccess; +$cronjob-suspended: $colorTerminated; + // Pod Statuses $pod-status-color-list: ( running: $pod-status-running-color, @@ -48,6 +52,12 @@ $job-condition-color-list: ( failed: $job-failed, ); +// Cronjob Conditions +$cronjob-condition-color-list: ( + scheduled: $cronjob-scheduled, + suspended: $cronjob-suspended, +); + @mixin pod-status-bgs { @each $status, $color in $pod-status-color-list { &.#{$status} { diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index abdef9b7f4..23e71e2be9 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -25,6 +25,7 @@ import { KubeObjectDetails } from "./kube-object/kube-object-details"; import { AddRoleBindingDialog } from "./+user-management-roles-bindings"; import { PodLogsDialog } from "./+workloads-pods/pod-logs-dialog"; import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale-dialog"; +import { CronJobTriggerDialog } from "./+workloads-cronjobs/cronjob-trigger-dialog"; import { CustomResources } from "./+custom-resources/custom-resources"; import { crdRoute } from "./+custom-resources"; import { isAllowedResource } from "../../common/rbac"; @@ -80,6 +81,7 @@ export class App extends React.Component { + diff --git a/src/renderer/components/chart/chart.tsx b/src/renderer/components/chart/chart.tsx index 92e3619031..a5fa4b9706 100644 --- a/src/renderer/components/chart/chart.tsx +++ b/src/renderer/components/chart/chart.tsx @@ -63,14 +63,14 @@ export class Chart extends React.Component { this.renderChart() } - componentDidUpdate(prevProps: ChartProps) { - const { data, showChart, redraw } = this.props + componentDidUpdate() { + const { showChart, redraw } = this.props if (redraw) { this.chart.destroy() this.renderChart() return } - if (!isEqual(prevProps.data, data) && showChart) { + if (showChart) { if (!this.chart) this.renderChart() else this.updateChart() } diff --git a/src/renderer/components/cluster-manager/clusters-menu.scss b/src/renderer/components/cluster-manager/clusters-menu.scss index 0ee1f59d7e..9b412e5035 100644 --- a/src/renderer/components/cluster-manager/clusters-menu.scss +++ b/src/renderer/components/cluster-manager/clusters-menu.scss @@ -1,5 +1,4 @@ .ClustersMenu { - @include hidden-scrollbar; $spacing: $padding * 2; position: relative; @@ -23,8 +22,7 @@ padding: $spacing; width: 320px; background: $bgc; - z-index: 100; - color: white; + color: $textColorAccent; filter: drop-shadow(0 0px 2px #ffffff33); pointer-events: none; @@ -38,6 +36,19 @@ border-right: $arrowSize solid $bgc; right: 100%; } + + .theme-light & { + filter: drop-shadow(0 0px 2px #777); + background: white; + + &:before { + border-right-color: white; + } + } + } + + .clusters { + @include hidden-scrollbar; } > .add-cluster { diff --git a/src/renderer/components/cluster-manager/clusters-menu.tsx b/src/renderer/components/cluster-manager/clusters-menu.tsx index 23d85507c3..d4fb4cefb1 100644 --- a/src/renderer/components/cluster-manager/clusters-menu.tsx +++ b/src/renderer/components/cluster-manager/clusters-menu.tsx @@ -110,18 +110,20 @@ export class ClustersMenu extends React.Component {

)} - {clusters.map(cluster => { - return ( - this.showCluster(cluster.id)} - onContextMenu={() => this.showContextMenu(cluster)} - /> - ) - })} +
+ {clusters.map(cluster => { + return ( + this.showCluster(cluster.id)} + onContextMenu={() => this.showContextMenu(cluster)} + /> + ) + })} +
Add Cluster diff --git a/test-data/cluster-store-migration-icon.png b/test-data/cluster-store-migration-icon.png new file mode 100644 index 0000000000..623a0fea77 Binary files /dev/null and b/test-data/cluster-store-migration-icon.png differ diff --git a/yarn.lock b/yarn.lock index d8881d0f1d..9e75e68c2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1588,6 +1588,11 @@ dependencies: defer-to-connect "^1.0.1" +"@tokenizer/token@^0.1.0", "@tokenizer/token@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3" + integrity sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w== + "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" @@ -3997,6 +4002,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-env@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.2.tgz#bd5ed31339a93a3418ac4f3ca9ca3403082ae5f9" + integrity sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw== + dependencies: + cross-spawn "^7.0.1" + cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -4016,7 +4028,7 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5189,6 +5201,16 @@ file-loader@^6.0.0: loader-utils "^2.0.0" schema-utils "^2.6.5" +file-type@^14.7.1: + version "14.7.1" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-14.7.1.tgz#f748732b3e70478bff530e1cf0ec2fe33608b1bb" + integrity sha512-sXAMgFk67fQLcetXustxfKX+PZgHIUFn96Xld9uH8aXPdX3xOp0/jg9OdouVTvQrf7mrn+wAa4jN/y9fUOOiRA== + dependencies: + readable-web-to-node-stream "^2.0.0" + strtok3 "^6.0.3" + token-types "^2.0.0" + typedarray-to-buffer "^3.1.5" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -6067,7 +6089,7 @@ identity-obj-proxy@^3.0.0: dependencies: harmony-reflect "^1.4.6" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== @@ -7625,6 +7647,14 @@ make-plural@^6.2.1: resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-6.2.1.tgz#2790af1d05fb2fc35a111ce759ffdb0aca1339a3" integrity sha512-AmkruwJ9EjvyTv6AM8MBMK3TAeOJvhgTv5YQXzF0EP2qawhpvMjDpHvsdOIIT0Vn+BB0+IogmYZ1z+Ulm/m0Fg== +make-synchronous@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/make-synchronous/-/make-synchronous-0.1.1.tgz#0169f6ec769c3cf8948d66790da262740c1209e7" + integrity sha512-Y4SxxqhaoyMDokJQ0AZz0E+bLhRkOSR7Z/IQoTKPdS6HYi3aobal2kMHoHHoqBadPWjf07P4K1FQLXOx3wf9Yw== + dependencies: + subsume "^3.0.0" + type-fest "^0.16.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -8936,6 +8966,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +peek-readable@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-3.1.0.tgz#250b08b7de09db8573d7fd8ea475215bbff14348" + integrity sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA== + pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -9529,6 +9564,11 @@ readable-stream@^3.1.1, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-web-to-node-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz#751e632f466552ac0d5c440cc01470352f93c4b7" + integrity sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA== + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -10648,6 +10688,15 @@ strip-outer@^1.0.1: dependencies: escape-string-regexp "^1.0.2" +strtok3@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.0.4.tgz#ede0d20fde5aa9fda56417c3558eaafccc724694" + integrity sha512-rqWMKwsbN9APU47bQTMEYTPcwdpKDtmf1jVhHzNW2cL1WqAxaM9iBb9t5P2fj+RV2YsErUWgQzHD5JwV0uCTEQ== + dependencies: + "@tokenizer/token" "^0.1.1" + "@types/debug" "^4.1.5" + peek-readable "^3.1.0" + style-loader@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a" @@ -10656,6 +10705,14 @@ style-loader@^1.2.1: loader-utils "^2.0.0" schema-utils "^2.6.6" +subsume@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/subsume/-/subsume-3.0.0.tgz#22c92730f441ad72ee9af4bdad42dc4ff830cfaf" + integrity sha512-6n/UfV8UWKwJNO8OAOiKntwEMihuBeeoJfzpL542C+OuvT4iWG9SwjrXkOmsxjb4SteHUsos9SvrdqZ9+ICwTQ== + dependencies: + escape-string-regexp "^2.0.0" + unique-string "^2.0.0" + sumchecker@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" @@ -10977,6 +11034,14 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +token-types@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-2.0.0.tgz#b23618af744818299c6fbf125e0fdad98bab7e85" + integrity sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw== + dependencies: + "@tokenizer/token" "^0.1.0" + ieee754 "^1.1.13" + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -11150,6 +11215,11 @@ type-fest@^0.13.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== +type-fest@^0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" + integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== + type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"