WebUI: remove "lodash" dep (#6369)

make our webui smaler by 0.1Mb ... and remove dep that is haunted by security issues and almost replaced by modern browser APIs.

https://developer.mozilla.org/de/docs/Web/API/Window/structuredClone#browser-kompatibilit%C3%A4t
This commit is contained in:
6543
2026-04-04 14:20:16 +02:00
committed by GitHub
parent 63b75b89fa
commit de4f9c21eb
14 changed files with 27 additions and 43 deletions

View File

@@ -25,7 +25,6 @@
"dompurify": "^3.3.2",
"fuse.js": "^7.1.0",
"js-base64": "^3.7.7",
"lodash": "^4.17.21",
"marked": "^17.0.0",
"node-emoji": "^2.2.0",
"pinia": "^3.0.3",
@@ -45,7 +44,6 @@
"@intlify/unplugin-vue-i18n": "^11.0.0",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "4.2.2",
"@types/lodash": "^4.17.20",
"@types/node": "^24.0.0",
"@types/prismjs": "^1.26.5",
"@types/semver": "^7.7.0",

11
web/pnpm-lock.yaml generated
View File

@@ -32,9 +32,6 @@ importers:
js-base64:
specifier: ^3.7.7
version: 3.7.8
lodash:
specifier: ^4.17.21
version: 4.18.1
marked:
specifier: ^17.0.0
version: 17.0.5
@@ -87,9 +84,6 @@ importers:
'@tailwindcss/vite':
specifier: 4.2.2
version: 4.2.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.2)(jiti@2.6.1)(yaml@2.8.3))
'@types/lodash':
specifier: ^4.17.20
version: 4.17.24
'@types/node':
specifier: ^24.0.0
version: 24.12.2
@@ -1048,9 +1042,6 @@ packages:
'@types/katex@0.16.8':
resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==}
'@types/lodash@4.17.24':
resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
@@ -4035,8 +4026,6 @@ snapshots:
'@types/katex@0.16.8': {}
'@types/lodash@4.17.24': {}
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3

View File

@@ -31,7 +31,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -92,7 +91,7 @@ const { doSubmit: deleteAgent, isLoading: isDeleting } = useAsyncAction(async (_
});
function editAgent(agent: Agent) {
selectedAgent.value = cloneDeep(agent);
selectedAgent.value = structuredClone(agent);
}
function showAddAgent() {

View File

@@ -126,7 +126,6 @@ import '~/style/console.css';
import { useStorage } from '@vueuse/core';
import { AnsiUp } from 'ansi_up';
import { decode } from 'js-base64';
import { debounce } from 'lodash';
import { computed, nextTick, onBeforeUnmount, onMounted, ref, toRef, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
@@ -138,6 +137,7 @@ import useConfig from '~/compositions/useConfig';
import { requiredInject } from '~/compositions/useInjectProvide';
import useNotifications from '~/compositions/useNotifications';
import type { Pipeline, PipelineStep, PipelineWorkflow } from '~/lib/api/types';
import { debounce } from '~/lib/utils';
interface LogLine {
index: number;

View File

@@ -0,0 +1,7 @@
export function debounce<T extends unknown[]>(fn: (...args: T) => void, delay: number): (...args: T) => void {
let timer: ReturnType<typeof setTimeout>;
return (...args: T) => {
clearTimeout(timer);
timer = setTimeout(fn, delay, ...args);
};
}

View File

@@ -38,7 +38,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -98,11 +97,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async
});
function editRegistry(registry: Registry) {
selectedRegistry.value = cloneDeep(registry);
selectedRegistry.value = structuredClone(registry);
}
function showAddRegistry() {
selectedRegistry.value = cloneDeep(emptyRegistry);
selectedRegistry.value = structuredClone(emptyRegistry);
}
useWPTitle(computed(() => [i18n.t('registries.registries'), i18n.t('admin.settings.settings')]));

View File

@@ -33,7 +33,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -95,11 +94,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (
});
function editSecret(secret: Secret) {
selectedSecret.value = cloneDeep(secret);
selectedSecret.value = structuredClone(secret);
}
function showAddSecret() {
selectedSecret.value = cloneDeep(emptySecret);
selectedSecret.value = structuredClone(emptySecret);
}
useWPTitle(computed(() => [i18n.t('secrets.secrets'), i18n.t('admin.settings.settings')]));

View File

@@ -86,7 +86,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -153,11 +152,11 @@ const { doSubmit: deleteUser, isLoading: isDeleting } = useAsyncAction(async (_u
});
function editUser(user: User) {
selectedUser.value = cloneDeep(user);
selectedUser.value = structuredClone(user);
}
function showAddUser() {
selectedUser.value = cloneDeep({ login: '' });
selectedUser.value = { login: '' };
}
useWPTitle(computed(() => [t('admin.settings.users.users'), t('admin.settings.settings')]));

View File

@@ -34,7 +34,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -131,11 +130,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async
});
function editRegistry(registry: Registry) {
selectedRegistry.value = cloneDeep(registry);
selectedRegistry.value = structuredClone(registry);
}
function showAddRegistry() {
selectedRegistry.value = cloneDeep(emptyRegistry);
selectedRegistry.value = structuredClone(emptyRegistry);
}
useWPTitle(computed(() => [i18n.t('registries.registries'), org.value.name]));

View File

@@ -25,7 +25,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -88,11 +87,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (
});
function editSecret(secret: Secret) {
selectedSecret.value = cloneDeep(secret);
selectedSecret.value = structuredClone(secret);
}
function showAddSecret() {
selectedSecret.value = cloneDeep(emptySecret);
selectedSecret.value = structuredClone(emptySecret);
}
useWPTitle(computed(() => [i18n.t('secrets.secrets'), org.value.name]));

View File

@@ -30,7 +30,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -133,11 +132,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async
});
function editRegistry(registry: Registry) {
selectedRegistry.value = cloneDeep(registry);
selectedRegistry.value = structuredClone(registry);
}
function showAddRegistry() {
selectedRegistry.value = cloneDeep(emptyRegistry);
selectedRegistry.value = structuredClone(emptyRegistry);
}
useWPTitle(computed(() => [i18n.t('registries.registries'), repo.value.full_name]));

View File

@@ -25,7 +25,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -129,11 +128,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (
});
function editSecret(secret: Secret) {
selectedSecret.value = cloneDeep(secret);
selectedSecret.value = structuredClone(secret);
}
function showAddSecret() {
selectedSecret.value = cloneDeep(emptySecret);
selectedSecret.value = structuredClone(emptySecret);
}
useWPTitle(computed(() => [i18n.t('secrets.secrets'), repo.value.full_name]));

View File

@@ -34,7 +34,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -102,11 +101,11 @@ const { doSubmit: deleteRegistry, isLoading: isDeleting } = useAsyncAction(async
});
function editRegistry(registry: Registry) {
selectedRegistry.value = cloneDeep(registry);
selectedRegistry.value = structuredClone(registry);
}
function showAddRegistry() {
selectedRegistry.value = cloneDeep(emptyRegistry);
selectedRegistry.value = structuredClone(emptyRegistry);
}
useWPTitle(computed(() => [i18n.t('registries.registries'), i18n.t('user.settings.settings')]));

View File

@@ -29,7 +29,6 @@
</template>
<script lang="ts" setup>
import { cloneDeep } from 'lodash';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -99,11 +98,11 @@ const { doSubmit: deleteSecret, isLoading: isDeleting } = useAsyncAction(async (
});
function editSecret(secret: Secret) {
selectedSecret.value = cloneDeep(secret);
selectedSecret.value = structuredClone(secret);
}
function showAddSecret() {
selectedSecret.value = cloneDeep(emptySecret);
selectedSecret.value = structuredClone(emptySecret);
}
useWPTitle(computed(() => [i18n.t('secrets.secrets'), i18n.t('user.settings.settings')]));