diff --git a/src/client/components/packages/PackageList.vue b/src/client/components/packages/PackageList.vue
index c26edfa..3eca558 100644
--- a/src/client/components/packages/PackageList.vue
+++ b/src/client/components/packages/PackageList.vue
@@ -25,6 +25,7 @@ const emit = defineEmits<{
const packagesRef = computed(() => props.packages)
const { query, filter, filtered, counts, setQuery, setFilter } = useSearch(packagesRef)
+
const filters: { value: FilterType; label: string; countKey: keyof typeof counts.value }[] = [
{ value: 'all', label: 'All', countKey: 'total' },
{ value: 'outdated', label: 'Outdated', countKey: 'outdated' },
diff --git a/src/client/composables/useTheme.ts b/src/client/composables/useTheme.ts
new file mode 100644
index 0000000..ae41e0c
--- /dev/null
+++ b/src/client/composables/useTheme.ts
@@ -0,0 +1,30 @@
+import { ref } from 'vue'
+
+type Theme = 'system' | 'light' | 'dark'
+
+const STORAGE_KEY = 'packy-theme'
+const theme = ref((localStorage.getItem(STORAGE_KEY) as Theme) ?? 'system')
+const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
+
+function apply() {
+ const isDark = theme.value === 'dark' || (theme.value === 'system' && mediaQuery.matches)
+ document.documentElement.classList.toggle('dark', isDark)
+}
+
+mediaQuery.addEventListener('change', apply)
+apply()
+
+export function useTheme() {
+ function setTheme(value: Theme) {
+ theme.value = value
+ localStorage.setItem(STORAGE_KEY, value)
+ apply()
+ }
+
+ function toggleTheme() {
+ const cycle: Theme[] = ['light', 'dark', 'system']
+ setTheme(cycle[(cycle.indexOf(theme.value) + 1) % cycle.length])
+ }
+
+ return { theme, setTheme, toggleTheme }
+}
diff --git a/src/client/stores/ui.ts b/src/client/stores/ui.ts
index 59b6202..f71291d 100644
--- a/src/client/stores/ui.ts
+++ b/src/client/stores/ui.ts
@@ -2,34 +2,17 @@ import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useUiStore = defineStore('ui', () => {
- // Dialog states
const isOperationLogOpen = ref(false)
-
- // Selected package for detail view
const selectedPackage = ref(null)
- // Actions
- function openOperationLog() {
- isOperationLogOpen.value = true
- }
-
- function closeOperationLog() {
- isOperationLogOpen.value = false
- }
-
- function toggleOperationLog() {
- isOperationLogOpen.value = !isOperationLogOpen.value
- }
-
- function selectPackage(name: string | null) {
- selectedPackage.value = name
- }
+ function openOperationLog() { isOperationLogOpen.value = true }
+ function closeOperationLog() { isOperationLogOpen.value = false }
+ function toggleOperationLog() { isOperationLogOpen.value = !isOperationLogOpen.value }
+ function selectPackage(name: string | null) { selectedPackage.value = name }
return {
- // State
isOperationLogOpen,
selectedPackage,
- // Actions
openOperationLog,
closeOperationLog,
toggleOperationLog,
From 6d9bb17891cf0d129a9c73d2dcba3438181aa462 Mon Sep 17 00:00:00 2001
From: njevric
Date: Tue, 12 May 2026 23:39:49 +0200
Subject: [PATCH 4/9] fix: lint errors
---
src/client/App.vue | 1 -
src/client/components/ui/badge/Badge.vue | 1 +
src/client/components/ui/button/Button.vue | 1 +
3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/client/App.vue b/src/client/App.vue
index 93b6713..8ebc79a 100644
--- a/src/client/App.vue
+++ b/src/client/App.vue
@@ -121,6 +121,5 @@ const themeOptions = [
-
diff --git a/src/client/components/ui/badge/Badge.vue b/src/client/components/ui/badge/Badge.vue
index 3800e7c..2073cdb 100644
--- a/src/client/components/ui/badge/Badge.vue
+++ b/src/client/components/ui/badge/Badge.vue
@@ -9,6 +9,7 @@ interface Props {
const props = withDefaults(defineProps
(), {
variant: 'default',
+ class: undefined,
})
diff --git a/src/client/components/ui/button/Button.vue b/src/client/components/ui/button/Button.vue
index f2eae50..556df95 100644
--- a/src/client/components/ui/button/Button.vue
+++ b/src/client/components/ui/button/Button.vue
@@ -14,6 +14,7 @@ const props = withDefaults(defineProps(), {
as: 'button',
variant: 'default',
size: 'default',
+ class: undefined,
})
const delegatedProps = computed(() => {
From 0d094400aced859b936e539a2bf3b8a9b81d707e Mon Sep 17 00:00:00 2001
From: njevric
Date: Wed, 13 May 2026 00:03:29 +0200
Subject: [PATCH 5/9] feat: unused dependencies
---
package-lock.json | 837 +++++++++++++++++-
package.json | 2 +
.../components/packages/DepcheckPanel.vue | 225 +++++
.../components/packages/PackageList.vue | 126 ++-
.../components/packages/SmartFiltersPanel.vue | 225 +++++
src/client/composables/useDepcheck.ts | 37 +
src/client/composables/useSmartFilters.ts | 119 +++
src/client/views/DependenciesView.vue | 14 +-
src/server/app.ts | 2 +
src/server/routes/depcheck.ts | 48 +
src/server/routes/packages.ts | 19 +-
src/server/services/depcheckService.ts | 27 +
src/server/services/registryClient.ts | 63 ++
src/shared/types.ts | 15 +
14 files changed, 1707 insertions(+), 52 deletions(-)
create mode 100644 src/client/components/packages/DepcheckPanel.vue
create mode 100644 src/client/components/packages/SmartFiltersPanel.vue
create mode 100644 src/client/composables/useDepcheck.ts
create mode 100644 src/client/composables/useSmartFilters.ts
create mode 100644 src/server/routes/depcheck.ts
create mode 100644 src/server/services/depcheckService.ts
diff --git a/package-lock.json b/package-lock.json
index 6c976a3..9e5d1ca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"cors": "^2.8.6",
+ "depcheck": "^1.4.7",
"express": "^5.2.1",
"get-port": "^7.2.0",
"open": "^11.0.0",
@@ -120,11 +121,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/generator": {
"version": "7.29.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
@@ -137,11 +151,19 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -151,7 +173,6 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -161,7 +182,6 @@
"version": "7.29.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
"integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.0"
@@ -173,11 +193,42 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/types": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -1089,7 +1140,6 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1111,7 +1161,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1121,14 +1170,12 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -2279,6 +2326,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "license": "MIT"
+ },
"node_modules/@types/node": {
"version": "25.6.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz",
@@ -2289,6 +2342,12 @@
"undici-types": "~7.19.0"
}
},
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
+ "license": "MIT"
+ },
"node_modules/@types/qs": {
"version": "6.15.1",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz",
@@ -2769,7 +2828,6 @@
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
"integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.3",
@@ -2783,7 +2841,6 @@
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
"integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.34",
@@ -2794,7 +2851,6 @@
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
"integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.3",
@@ -2812,7 +2868,6 @@
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
"integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.34",
@@ -2920,7 +2975,6 @@
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz",
"integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
- "dev": true,
"license": "MIT"
},
"node_modules/@vue/test-utils": {
@@ -3072,7 +3126,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -3091,6 +3144,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
"node_modules/aria-hidden": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
@@ -3104,6 +3166,33 @@
"node": ">=10"
}
},
+ "node_modules/array-differ": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -3272,6 +3361,18 @@
"node": "18 || 20 || >=22"
}
},
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/browserslist": {
"version": "4.28.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
@@ -3385,6 +3486,35 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/callsite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+ "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/caniuse-lite": {
"version": "1.0.30001792",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz",
@@ -3567,7 +3697,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -3580,7 +3709,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
"license": "MIT"
},
"node_modules/commander": {
@@ -3593,6 +3721,12 @@
"node": ">=14"
}
},
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "license": "MIT"
+ },
"node_modules/concurrently": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
@@ -3726,6 +3860,31 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cosmiconfig/node_modules/yaml": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
+ "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3867,6 +4026,193 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/depcheck": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz",
+ "integrity": "sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.23.0",
+ "@babel/traverse": "^7.23.2",
+ "@vue/compiler-sfc": "^3.3.4",
+ "callsite": "^1.0.0",
+ "camelcase": "^6.3.0",
+ "cosmiconfig": "^7.1.0",
+ "debug": "^4.3.4",
+ "deps-regex": "^0.2.0",
+ "findup-sync": "^5.0.0",
+ "ignore": "^5.2.4",
+ "is-core-module": "^2.12.0",
+ "js-yaml": "^3.14.1",
+ "json5": "^2.2.3",
+ "lodash": "^4.17.21",
+ "minimatch": "^7.4.6",
+ "multimatch": "^5.0.0",
+ "please-upgrade-node": "^3.2.0",
+ "readdirp": "^3.6.0",
+ "require-package-name": "^2.0.1",
+ "resolve": "^1.22.3",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.4",
+ "yargs": "^16.2.0"
+ },
+ "bin": {
+ "depcheck": "bin/depcheck.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/depcheck/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/depcheck/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/depcheck/node_modules/brace-expansion": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+ "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/depcheck/node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/depcheck/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/depcheck/node_modules/minimatch": {
+ "version": "7.4.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.9.tgz",
+ "integrity": "sha512-Brg/fp/iAVDOQoHxkuN5bEYhyQlZhxddI78yWsCbeEwTHXQjlNLtiJDUsp1GIptVqMI7/gkJMz4vVAc01mpoBw==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/depcheck/node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/depcheck/node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/depcheck/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/depcheck/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/depcheck/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/depcheck/node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/depcheck/node_modules/yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -3876,6 +4222,21 @@
"node": ">= 0.8"
}
},
+ "node_modules/deps-regex": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.2.0.tgz",
+ "integrity": "sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==",
+ "license": "MIT"
+ },
+ "node_modules/detect-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+ "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -4006,7 +4367,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -4015,6 +4375,15 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -4098,7 +4467,6 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -4271,6 +4639,19 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/esquery": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
@@ -4311,7 +4692,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true,
"license": "MIT"
},
"node_modules/esutils": {
@@ -4333,6 +4713,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/expand-tilde": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+ "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==",
+ "license": "MIT",
+ "dependencies": {
+ "homedir-polyfill": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/expect-type": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
@@ -4427,6 +4819,18 @@
"node": ">=16.0.0"
}
},
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/finalhandler": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
@@ -4465,6 +4869,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/findup-sync": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz",
+ "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-file": "^1.0.0",
+ "is-glob": "^4.0.3",
+ "micromatch": "^4.0.4",
+ "resolve-dir": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
"node_modules/fix-dts-default-cjs-exports": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz",
@@ -4575,7 +4994,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
@@ -4711,6 +5129,48 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/global-modules": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+ "license": "MIT",
+ "dependencies": {
+ "global-prefix": "^1.0.1",
+ "is-windows": "^1.0.1",
+ "resolve-dir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/global-prefix": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+ "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==",
+ "license": "MIT",
+ "dependencies": {
+ "expand-tilde": "^2.0.2",
+ "homedir-polyfill": "^1.0.1",
+ "ini": "^1.3.4",
+ "is-windows": "^1.0.1",
+ "which": "^1.2.14"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -4764,6 +5224,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/homedir-polyfill": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+ "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+ "license": "MIT",
+ "dependencies": {
+ "parse-passwd": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@@ -4824,12 +5296,36 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -4850,7 +5346,6 @@
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
"license": "ISC"
},
"node_modules/ipaddr.js": {
@@ -4862,6 +5357,27 @@
"node": ">= 0.10"
}
},
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-docker": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
@@ -4881,7 +5397,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -4891,7 +5406,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -4901,7 +5415,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -4940,6 +5453,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@@ -4966,6 +5488,15 @@
"url": "https://github.com/sponsors/mesqueeb"
}
},
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-wsl": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
@@ -4985,7 +5516,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
"license": "ISC"
},
"node_modules/jackspeak": {
@@ -5056,6 +5586,25 @@
"node": ">=14"
}
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/jsdom": {
"version": "29.1.1",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
@@ -5111,7 +5660,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
@@ -5127,6 +5675,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "license": "MIT"
+ },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -5145,7 +5699,6 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
@@ -5456,7 +6009,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
"license": "MIT"
},
"node_modules/load-tsconfig": {
@@ -5522,6 +6074,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT"
+ },
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -5543,7 +6101,6 @@
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -5602,6 +6159,31 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/micromatch/node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
@@ -5686,6 +6268,53 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/multimatch": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
+ "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/minimatch": "^3.0.3",
+ "array-differ": "^3.0.0",
+ "array-union": "^2.1.0",
+ "arrify": "^2.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/multimatch/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/multimatch/node_modules/brace-expansion": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/multimatch/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@@ -5702,7 +6331,6 @@
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -5899,6 +6527,45 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/parse5": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
@@ -5961,6 +6628,12 @@
"node": ">=8"
}
},
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
+ },
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
@@ -5988,6 +6661,15 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -6006,7 +6688,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
@@ -6076,11 +6757,19 @@
"pathe": "^2.0.1"
}
},
+ "node_modules/please-upgrade-node": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
+ "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
+ "license": "MIT",
+ "dependencies": {
+ "semver-compare": "^1.0.0"
+ }
+ },
"node_modules/postcss": {
"version": "8.5.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
"integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -6390,7 +7079,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -6406,11 +7094,50 @@
"node": ">=0.10.0"
}
},
+ "node_modules/require-package-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz",
+ "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==",
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-dir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+ "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==",
+ "license": "MIT",
+ "dependencies": {
+ "expand-tilde": "^2.0.0",
+ "global-modules": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6602,6 +7329,12 @@
"node": ">=10"
}
},
+ "node_modules/semver-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+ "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
+ "license": "MIT"
+ },
"node_modules/send": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
@@ -6795,7 +7528,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -6811,6 +7543,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -7000,6 +7738,18 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -7151,6 +7901,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -8115,7 +8877,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
diff --git a/package.json b/package.json
index 054442d..72464e7 100644
--- a/package.json
+++ b/package.json
@@ -59,6 +59,7 @@
},
"dependencies": {
"cors": "^2.8.6",
+ "depcheck": "^1.4.7",
"express": "^5.2.1",
"get-port": "^7.2.0",
"open": "^11.0.0",
@@ -80,6 +81,7 @@
"concurrently": "^9.2.1",
"eslint": "^10.3.0",
"eslint-plugin-vue": "^10.9.1",
+ "vue-eslint-parser": "^9.4.3",
"jsdom": "^29.1.1",
"lucide-vue-next": "^1.0.0",
"pinia": "^3.0.4",
diff --git a/src/client/components/packages/DepcheckPanel.vue b/src/client/components/packages/DepcheckPanel.vue
new file mode 100644
index 0000000..2a0f748
--- /dev/null
+++ b/src/client/components/packages/DepcheckPanel.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+ Unused Dependencies
+
+
+
+
+
+
+
+
+
+ Scan your project to detect packages that are declared in package.json but not used in your code.
+
+
+
+
+
+
+
+
+ Scanning project files...
+
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+ No unused dependencies found.
+
+
+
+
+
+
+
+ Unused ({{ result.dependencies.length }})
+
+
+ {{ name }}
+
+
+
+
+
+
+
+ Unused Dev ({{ result.devDependencies.length }})
+
+
+ {{ name }}
+
+
+
+
+
+
+
+ Missing ({{ missingEntries.length }})
+
+
+
{{ entry.name }}
+
+ {{ entry.files[0] }}
+ +{{ entry.files.length - 1 }} more
+
+
+
+
+
+
+
+
diff --git a/src/client/components/packages/PackageList.vue b/src/client/components/packages/PackageList.vue
index 3eca558..e56648c 100644
--- a/src/client/components/packages/PackageList.vue
+++ b/src/client/components/packages/PackageList.vue
@@ -5,7 +5,9 @@ import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Skeleton } from '@/components/ui/skeleton'
import PackageItem from './PackageItem.vue'
+import SmartFiltersPanel from './SmartFiltersPanel.vue'
import { useSearch, type FilterType } from '@/composables/useSearch'
+import { useSmartFilters } from '@/composables/useSmartFilters'
import type { Package } from '@shared/types'
const props = defineProps<{
@@ -25,17 +27,67 @@ const emit = defineEmits<{
const packagesRef = computed(() => props.packages)
const { query, filter, filtered, counts, setQuery, setFilter } = useSearch(packagesRef)
+const {
+ availableLicenses,
+ isLoading: isSmartLoading,
+ hasData: hasSmartData,
+ selectedLicenses,
+ popularityFilter,
+ ageFilter,
+ filteredNames,
+ activeFilterCount,
+ loadSmartData,
+ clearFilters,
+} = useSmartFilters(packagesRef)
-const filters: { value: FilterType; label: string; countKey: keyof typeof counts.value }[] = [
+const baseFilters: { value: FilterType; label: string; countKey: keyof typeof counts.value }[] = [
{ value: 'all', label: 'All', countKey: 'total' },
{ value: 'outdated', label: 'Outdated', countKey: 'outdated' },
{ value: 'dependencies', label: 'Dependencies', countKey: 'dependencies' },
{ value: 'devDependencies', label: 'Dev', countKey: 'devDependencies' },
]
-const displayedPackages = computed(() =>
- props.limit ? filtered.value.slice(0, props.limit) : filtered.value
-)
+const popularityLabels: Record = {
+ 'very-popular': '>1M / wk',
+ popular: '>100K / wk',
+ niche: '<100K / wk',
+}
+
+const ageLabels: Record = {
+ active: '<6 months',
+ recent: '6–12 months',
+ stable: '1–2 years',
+ stale: '>2 years',
+}
+
+// Tags to show below the controls row for active smart filters
+const activeTags = computed(() => {
+ const tags: { key: string; label: string; onRemove: () => void }[] = []
+ for (const lic of selectedLicenses.value) {
+ tags.push({ key: `lic:${lic}`, label: lic, onRemove: () => {
+ selectedLicenses.value = selectedLicenses.value.filter(l => l !== lic)
+ }})
+ }
+ if (popularityFilter.value !== 'all') {
+ tags.push({ key: 'pop', label: popularityLabels[popularityFilter.value] ?? popularityFilter.value, onRemove: () => {
+ popularityFilter.value = 'all'
+ }})
+ }
+ if (ageFilter.value !== 'all') {
+ tags.push({ key: 'age', label: ageLabels[ageFilter.value] ?? ageFilter.value, onRemove: () => {
+ ageFilter.value = 'all'
+ }})
+ }
+ return tags
+})
+
+const displayedPackages = computed(() => {
+ let result = filtered.value
+ if (filteredNames.value !== null) {
+ result = result.filter(pkg => filteredNames.value!.has(pkg.name))
+ }
+ return props.limit ? result.slice(0, props.limit) : result
+})
const hasMore = computed(() =>
!!props.limit && props.packages.length > props.limit
@@ -43,10 +95,10 @@ const hasMore = computed(() =>
-
-
+
+
-
+
+
+
+
+ Filtered by:
+
+
+
diff --git a/src/client/components/packages/SmartFiltersPanel.vue b/src/client/components/packages/SmartFiltersPanel.vue
new file mode 100644
index 0000000..43bd2d3
--- /dev/null
+++ b/src/client/components/packages/SmartFiltersPanel.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fetching package metadata…
+
+
+
+
+
+
+
+ Load license, popularity, and age data from npm.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Popularity (weekly downloads)
+
+
+
+
+
+
+
+
+
+
+
+ Last Published
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/client/composables/useDepcheck.ts b/src/client/composables/useDepcheck.ts
new file mode 100644
index 0000000..961d4fe
--- /dev/null
+++ b/src/client/composables/useDepcheck.ts
@@ -0,0 +1,37 @@
+import { ref } from 'vue'
+import { useApi } from './useApi'
+import type { DepcheckResult } from '@shared/types'
+
+export function useDepcheck() {
+ const { get } = useApi()
+
+ const result = ref
(null)
+ const isLoading = ref(false)
+ const error = ref(null)
+
+ async function run() {
+ isLoading.value = true
+ error.value = null
+ try {
+ result.value = await get('/depcheck')
+ } catch (err) {
+ error.value = err instanceof Error ? err.message : 'Failed to run analysis'
+ } finally {
+ isLoading.value = false
+ }
+ }
+
+ async function refresh() {
+ isLoading.value = true
+ error.value = null
+ try {
+ result.value = await get('/depcheck/refresh')
+ } catch (err) {
+ error.value = err instanceof Error ? err.message : 'Failed to run analysis'
+ } finally {
+ isLoading.value = false
+ }
+ }
+
+ return { result, isLoading, error, run, refresh }
+}
diff --git a/src/client/composables/useSmartFilters.ts b/src/client/composables/useSmartFilters.ts
new file mode 100644
index 0000000..de56578
--- /dev/null
+++ b/src/client/composables/useSmartFilters.ts
@@ -0,0 +1,119 @@
+import { ref, computed, type Ref } from 'vue'
+import { useQuery } from '@tanstack/vue-query'
+import { useApi } from './useApi'
+import type { SmartPackageData } from '@shared/types'
+
+export type PopularityFilter = 'all' | 'very-popular' | 'popular' | 'niche'
+export type AgeFilter = 'all' | 'active' | 'recent' | 'stable' | 'stale'
+
+export function normalizeLicense(license: string | null): string {
+ if (!license) return 'Unknown'
+ return license.replace(/^\(|\)$/g, '').trim()
+}
+
+function getAgeCategory(lastPublished: string | null): Exclude {
+ if (!lastPublished) return 'stale'
+ const ageDays = (Date.now() - new Date(lastPublished).getTime()) / 86_400_000
+ if (ageDays < 180) return 'active'
+ if (ageDays < 365) return 'recent'
+ if (ageDays < 730) return 'stable'
+ return 'stale'
+}
+
+function getPopularityCategory(weeklyDownloads: number | null): Exclude {
+ if (!weeklyDownloads) return 'niche'
+ if (weeklyDownloads >= 1_000_000) return 'very-popular'
+ if (weeklyDownloads >= 100_000) return 'popular'
+ return 'niche'
+}
+
+export function useSmartFilters(_packages: Ref) {
+ const { get } = useApi()
+
+ const enabled = ref(false)
+
+ const { data: smartData, isLoading, isFetching } = useQuery({
+ queryKey: ['packages', 'smart-data'],
+ queryFn: () => get('/packages/smart-data'),
+ enabled,
+ staleTime: 5 * 60 * 1000,
+ })
+
+ const selectedLicenses = ref([])
+ const popularityFilter = ref('all')
+ const ageFilter = ref('all')
+
+ const smartDataMap = computed(() => {
+ const map = new Map()
+ smartData.value?.forEach(d => map.set(d.name, d))
+ return map
+ })
+
+ const availableLicenses = computed(() => {
+ if (!smartData.value) return []
+ const licenses = new Set()
+ smartData.value.forEach(d => licenses.add(normalizeLicense(d.license)))
+ return [...licenses].sort()
+ })
+
+ // Returns null when no smart filters are active (skip filtering), otherwise a Set of passing names
+ const filteredNames = computed((): Set | null => {
+ if (!smartData.value) return null
+
+ const hasFilters = selectedLicenses.value.length > 0
+ || popularityFilter.value !== 'all'
+ || ageFilter.value !== 'all'
+
+ if (!hasFilters) return null
+
+ return new Set(
+ smartData.value
+ .filter(d => {
+ if (selectedLicenses.value.length > 0) {
+ if (!selectedLicenses.value.includes(normalizeLicense(d.license))) return false
+ }
+ if (popularityFilter.value !== 'all') {
+ if (getPopularityCategory(d.weeklyDownloads) !== popularityFilter.value) return false
+ }
+ if (ageFilter.value !== 'all') {
+ if (getAgeCategory(d.lastPublished) !== ageFilter.value) return false
+ }
+ return true
+ })
+ .map(d => d.name)
+ )
+ })
+
+ const activeFilterCount = computed(() => {
+ let count = 0
+ if (selectedLicenses.value.length > 0) count++
+ if (popularityFilter.value !== 'all') count++
+ if (ageFilter.value !== 'all') count++
+ return count
+ })
+
+ function loadSmartData() {
+ enabled.value = true
+ }
+
+ function clearFilters() {
+ selectedLicenses.value = []
+ popularityFilter.value = 'all'
+ ageFilter.value = 'all'
+ }
+
+ return {
+ smartData,
+ smartDataMap,
+ isLoading: computed(() => isLoading.value || isFetching.value),
+ hasData: computed(() => !!smartData.value),
+ selectedLicenses,
+ popularityFilter,
+ ageFilter,
+ availableLicenses,
+ filteredNames,
+ activeFilterCount,
+ loadSmartData,
+ clearFilters,
+ }
+}
diff --git a/src/client/views/DependenciesView.vue b/src/client/views/DependenciesView.vue
index 90d2687..9f03c76 100644
--- a/src/client/views/DependenciesView.vue
+++ b/src/client/views/DependenciesView.vue
@@ -3,6 +3,7 @@ import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import PackageList from '@/components/packages/PackageList.vue'
import OutdatedCard from '@/components/dashboard/OutdatedCard.vue'
+import DepcheckPanel from '@/components/packages/DepcheckPanel.vue'
import OperationToast from '@/components/operations/OperationToast.vue'
import { ConfirmDialog } from '@/components/ui/confirm-dialog'
import { Button } from '@/components/ui/button'
@@ -75,11 +76,14 @@ function handleSelectPackage(name: string) {
@select="handleSelectPackage"
/>
-
+
+
+
+
{
+ try {
+ if (cache && Date.now() - cache.timestamp < CACHE_TTL) {
+ res.json({ success: true, data: cache.result })
+ return
+ }
+
+ const result = await runDepcheck(projectPath)
+ cache = { result, timestamp: Date.now() }
+ res.json({ success: true, data: result })
+ } catch (error) {
+ console.error('Depcheck error:', error)
+ res.status(500).json({ success: false, error: 'Failed to run dependency analysis' })
+ }
+ })
+
+ // GET /api/depcheck/refresh - force fresh run
+ router.get('/refresh', async (_req: Request, res: Response) => {
+ try {
+ cache = null
+ const result = await runDepcheck(projectPath)
+ cache = { result, timestamp: Date.now() }
+ res.json({ success: true, data: result })
+ } catch (error) {
+ console.error('Depcheck error:', error)
+ res.status(500).json({ success: false, error: 'Failed to run dependency analysis' })
+ }
+ })
+
+ return router
+}
diff --git a/src/server/routes/packages.ts b/src/server/routes/packages.ts
index 63c970f..32c9001 100644
--- a/src/server/routes/packages.ts
+++ b/src/server/routes/packages.ts
@@ -1,6 +1,6 @@
import { Router, type Request, type Response } from 'express'
import { getPackages } from '../services/packageJson.js'
-import { getLatestVersion } from '../services/registryClient.js'
+import { getLatestVersion, getSmartMetadata } from '../services/registryClient.js'
import {
detectPackageManager,
getUninstallCommand,
@@ -45,6 +45,23 @@ export function createPackagesRouter(projectPath: string): Router {
}
})
+ // GET /api/packages/smart-data - Batch enriched metadata for smart filters
+ router.get('/smart-data', async (_req: Request, res: Response) => {
+ try {
+ const packages = getPackages(projectPath)
+ const smartData = await Promise.all(
+ packages.map(async (pkg) => {
+ const meta = await getSmartMetadata(pkg.name)
+ return { name: pkg.name, ...meta }
+ })
+ )
+ res.json({ success: true, data: smartData })
+ } catch (error) {
+ console.error('Error fetching smart data:', error)
+ res.status(500).json({ success: false, error: 'Failed to fetch smart metadata' })
+ }
+ })
+
// GET /api/packages/:name - Get a single package
router.get('/:name', async (req: Request<{ name: string }>, res: Response) => {
try {
diff --git a/src/server/services/depcheckService.ts b/src/server/services/depcheckService.ts
new file mode 100644
index 0000000..1d4f4f8
--- /dev/null
+++ b/src/server/services/depcheckService.ts
@@ -0,0 +1,27 @@
+import { createRequire } from 'module'
+import type { DepcheckResult } from '@shared/types'
+
+const require = createRequire(import.meta.url)
+
+interface DepcheckUnused {
+ dependencies: string[]
+ devDependencies: string[]
+ missing: Record
+}
+
+type DepcheckFn = (path: string, options: Record) => Promise
+
+export async function runDepcheck(projectPath: string): Promise {
+ const depcheck = require('depcheck') as DepcheckFn
+
+ const result = await depcheck(projectPath, {
+ ignorePatterns: ['dist', 'build', '.packy-logs', 'coverage'],
+ ignoreMatches: ['@types/*', '@tailwindcss/postcss', 'autoprefixer', '@vue/test-utils', '@shared/*'],
+ })
+
+ return {
+ dependencies: result.dependencies,
+ devDependencies: result.devDependencies,
+ missing: result.missing,
+ }
+}
diff --git a/src/server/services/registryClient.ts b/src/server/services/registryClient.ts
index 8f2b5d5..933fd9f 100644
--- a/src/server/services/registryClient.ts
+++ b/src/server/services/registryClient.ts
@@ -190,3 +190,66 @@ export function clearCache(packageName?: string): void {
cache.clear()
}
}
+
+// Cache for last-published date lookups
+const publishDateCache = new Map()
+
+/**
+ * Fetches the last published date for the latest version of a package.
+ */
+export async function getLastPublished(packageName: string): Promise {
+ const cached = publishDateCache.get(packageName)
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
+ return cached.date
+ }
+
+ try {
+ const encodedName = packageName.startsWith('@')
+ ? `@${encodeURIComponent(packageName.slice(1))}`
+ : encodeURIComponent(packageName)
+
+ const response = await fetch(`${NPM_REGISTRY}/${encodedName}`, {
+ headers: { Accept: 'application/vnd.npm.install-v1+json' },
+ })
+
+ if (!response.ok) {
+ publishDateCache.set(packageName, { date: null, timestamp: Date.now() })
+ return null
+ }
+
+ const data = await response.json() as {
+ 'dist-tags': { latest: string }
+ time?: Record
+ }
+
+ const latestVersion = data['dist-tags']?.latest
+ const date = (latestVersion && data.time?.[latestVersion]) ?? data.time?.modified ?? null
+
+ publishDateCache.set(packageName, { date, timestamp: Date.now() })
+ return date
+ } catch {
+ publishDateCache.set(packageName, { date: null, timestamp: Date.now() })
+ return null
+ }
+}
+
+/**
+ * Fetches smart filter metadata (license, downloads, lastPublished) for a package.
+ */
+export async function getSmartMetadata(packageName: string): Promise<{
+ license: string | null
+ weeklyDownloads: number | null
+ lastPublished: string | null
+}> {
+ const [info, downloads, lastPublished] = await Promise.all([
+ getPackageInfo(packageName),
+ getDownloadCounts(packageName),
+ getLastPublished(packageName),
+ ])
+
+ return {
+ license: info?.license ?? null,
+ weeklyDownloads: downloads?.weekly ?? null,
+ lastPublished,
+ }
+}
diff --git a/src/shared/types.ts b/src/shared/types.ts
index 9b3f305..b4740df 100644
--- a/src/shared/types.ts
+++ b/src/shared/types.ts
@@ -158,6 +158,21 @@ export interface AuditFixRequest {
packageName?: string
}
+// Smart filter types
+export interface SmartPackageData {
+ name: string
+ license: string | null
+ weeklyDownloads: number | null
+ lastPublished: string | null
+}
+
+// Depcheck types
+export interface DepcheckResult {
+ dependencies: string[]
+ devDependencies: string[]
+ missing: Record
+}
+
// Audit log types
export interface AuditLogEntry {
id: string
From 56c84f1d63e0e519c920d955b2a393d94c3d939f Mon Sep 17 00:00:00 2001
From: njevric
Date: Wed, 13 May 2026 00:28:40 +0200
Subject: [PATCH 6/9] fix: package-lock
---
package-lock.json | 73 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 61 insertions(+), 12 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 9e5d1ca..6d13d42 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -50,6 +50,7 @@
"vite": "^8.0.11",
"vitest": "^4.1.5",
"vue": "^3.5.34",
+ "vue-eslint-parser": "^9.4.3",
"vue-router": "^5.0.6",
"vue-tsc": "^3.2.8"
},
@@ -8517,28 +8518,76 @@
}
},
"node_modules/vue-eslint-parser": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz",
- "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
+ "version": "9.4.3",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
+ "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
- "debug": "^4.4.0",
- "eslint-scope": "^8.2.0 || ^9.0.0",
- "eslint-visitor-keys": "^4.2.0 || ^5.0.0",
- "espree": "^10.3.0 || ^11.0.0",
- "esquery": "^1.6.0",
- "semver": "^7.6.3"
+ "debug": "^4.3.4",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.1",
+ "esquery": "^1.4.0",
+ "lodash": "^4.17.21",
+ "semver": "^7.3.6"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": "^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
+ "eslint": ">=6.0.0"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/vue-router": {
From ab509b03083a71175c32c7e4fdb7fc29bed89c6c Mon Sep 17 00:00:00 2001
From: njevric
Date: Wed, 13 May 2026 00:31:51 +0200
Subject: [PATCH 7/9] fix: lint error
---
package-lock.json | 73 ++++++++---------------------------------------
package.json | 2 +-
2 files changed, 13 insertions(+), 62 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 6d13d42..bb0e3a5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -50,7 +50,7 @@
"vite": "^8.0.11",
"vitest": "^4.1.5",
"vue": "^3.5.34",
- "vue-eslint-parser": "^9.4.3",
+ "vue-eslint-parser": "^10.3.0",
"vue-router": "^5.0.6",
"vue-tsc": "^3.2.8"
},
@@ -8518,76 +8518,27 @@
}
},
"node_modules/vue-eslint-parser": {
- "version": "9.4.3",
- "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
- "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz",
+ "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^4.3.4",
- "eslint-scope": "^7.1.1",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
- "esquery": "^1.4.0",
- "lodash": "^4.17.21",
- "semver": "^7.3.6"
+ "debug": "^4.4.0",
+ "eslint-scope": "^8.2.0 || ^9.0.0",
+ "eslint-visitor-keys": "^4.2.0 || ^5.0.0",
+ "espree": "^10.3.0 || ^11.0.0",
+ "esquery": "^1.6.0",
+ "semver": "^7.6.3"
},
"engines": {
- "node": "^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
},
"peerDependencies": {
- "eslint": ">=6.0.0"
- }
- },
- "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/vue-eslint-parser/node_modules/espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.9.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
}
},
"node_modules/vue-router": {
diff --git a/package.json b/package.json
index 72464e7..c9c6dc4 100644
--- a/package.json
+++ b/package.json
@@ -81,7 +81,7 @@
"concurrently": "^9.2.1",
"eslint": "^10.3.0",
"eslint-plugin-vue": "^10.9.1",
- "vue-eslint-parser": "^9.4.3",
+ "vue-eslint-parser": "^10.3.0",
"jsdom": "^29.1.1",
"lucide-vue-next": "^1.0.0",
"pinia": "^3.0.4",
From 7201dcde75ed3e8951dd9d979e107e6c5283cf5f Mon Sep 17 00:00:00 2001
From: njevric
Date: Wed, 13 May 2026 00:37:43 +0200
Subject: [PATCH 8/9] fix: codeql analyze allert
---
src/server/routes/audit.ts | 9 ++++-----
src/server/routes/packages.ts | 9 +++------
src/server/routes/scripts.ts | 2 +-
src/server/services/auditService.ts | 26 +++++++++++++-------------
src/server/services/operationRunner.ts | 16 +++++++---------
src/server/services/packageManager.ts | 26 +++++++++++++-------------
6 files changed, 41 insertions(+), 47 deletions(-)
diff --git a/src/server/routes/audit.ts b/src/server/routes/audit.ts
index 177bc27..9d33d4e 100644
--- a/src/server/routes/audit.ts
+++ b/src/server/routes/audit.ts
@@ -81,8 +81,7 @@ export function createAuditRouter(projectPath: string): Router {
return
}
- const command = getAuditCommand(packageManager)
- const operationId = runCommand(command, projectPath, 'audit')
+ const operationId = runCommand(getAuditCommand(packageManager), projectPath, 'audit')
// Accumulate stdout from the operation event stream directly — no second spawn needed
let stdout = ''
@@ -169,11 +168,11 @@ export function createAuditRouter(projectPath: string): Router {
return
}
- const command = getAuditFixCommand(packageManager, force, packageName)
- console.log('[AUDIT FIX] Running command:', command)
+ const auditFixArgv = getAuditFixCommand(packageManager, force, packageName)
+ console.log('[AUDIT FIX] Running command:', auditFixArgv.join(' '))
console.log('[AUDIT FIX] Force:', force, 'Package:', packageName)
- const operationId = runCommand(command, projectPath, 'audit-fix', packageName)
+ const operationId = runCommand(auditFixArgv, projectPath, 'audit-fix', packageName)
// Log the fix attempt
addFixLog(projectPath, packageName, force, operationId)
diff --git a/src/server/routes/packages.ts b/src/server/routes/packages.ts
index 32c9001..3545f49 100644
--- a/src/server/routes/packages.ts
+++ b/src/server/routes/packages.ts
@@ -117,8 +117,7 @@ export function createPackagesRouter(projectPath: string): Router {
return
}
- const command = getUpdateAllCommand(packageManager, outdated)
- const operationId = runCommand(command, projectPath, 'update', undefined, undefined)
+ const operationId = runCommand(getUpdateAllCommand(packageManager, outdated), projectPath, 'update', undefined, undefined)
res.json({ success: true, data: { operationId } })
} catch (error) {
@@ -134,8 +133,7 @@ export function createPackagesRouter(projectPath: string): Router {
// Handle scoped packages - the name might be URL encoded
const packageName = decodeURIComponent(name)
- const command = getUninstallCommand(packageManager, packageName)
- const operationId = runCommand(command, projectPath, 'remove', packageName)
+ const operationId = runCommand(getUninstallCommand(packageManager, packageName), projectPath, 'remove', packageName)
res.json({
success: true,
@@ -163,8 +161,7 @@ export function createPackagesRouter(projectPath: string): Router {
const packageName = decodeURIComponent(name)
const fromVersion = getPackages(projectPath).find((p) => p.name === packageName)?.current
- const command = getUpdateCommand(packageManager, packageName, version)
- const operationId = runCommand(command, projectPath, 'update', packageName, fromVersion)
+ const operationId = runCommand(getUpdateCommand(packageManager, packageName, version), projectPath, 'update', packageName, fromVersion)
res.json({
success: true,
diff --git a/src/server/routes/scripts.ts b/src/server/routes/scripts.ts
index 7497dd4..2841d41 100644
--- a/src/server/routes/scripts.ts
+++ b/src/server/routes/scripts.ts
@@ -58,7 +58,7 @@ export function createScriptsRouter(projectPath: string): Router {
}
const operationId = runCommand(
- `npm run ${name}`,
+ ['npm', 'run', name],
projectPath,
'script',
undefined,
diff --git a/src/server/services/auditService.ts b/src/server/services/auditService.ts
index 2fd7ae7..b966583 100644
--- a/src/server/services/auditService.ts
+++ b/src/server/services/auditService.ts
@@ -205,16 +205,16 @@ export function clearCache(): void {
/**
* Gets the audit command for a package manager
*/
-export function getAuditCommand(packageManager: PackageManager): string {
+export function getAuditCommand(packageManager: PackageManager): string[] {
switch (packageManager) {
case 'npm':
- return 'npm audit --json'
+ return ['npm', 'audit', '--json']
case 'yarn':
- return 'yarn audit --json'
+ return ['yarn', 'audit', '--json']
case 'pnpm':
- return 'pnpm audit --json'
+ return ['pnpm', 'audit', '--json']
default:
- return 'npm audit --json'
+ return ['npm', 'audit', '--json']
}
}
@@ -225,29 +225,29 @@ export function getAuditFixCommand(
packageManager: PackageManager,
force: boolean = false,
packageName?: string
-): string {
+): string[] {
if (packageName) {
// Fix specific package by updating it
switch (packageManager) {
case 'npm':
- return `npm update ${packageName}`
+ return ['npm', 'update', packageName]
case 'yarn':
- return `yarn upgrade ${packageName}`
+ return ['yarn', 'upgrade', packageName]
case 'pnpm':
- return `pnpm update ${packageName}`
+ return ['pnpm', 'update', packageName]
}
}
// Fix all vulnerabilities
switch (packageManager) {
case 'npm':
- return force ? 'npm audit fix --force' : 'npm audit fix'
+ return force ? ['npm', 'audit', 'fix', '--force'] : ['npm', 'audit', 'fix']
case 'yarn':
// yarn audit fix doesn't exist; npx yarn-audit-fix is the community equivalent
- return 'npx yarn-audit-fix@10.1.1'
+ return ['npx', 'yarn-audit-fix@10.1.1']
case 'pnpm':
- return 'pnpm audit fix'
+ return ['pnpm', 'audit', 'fix']
default:
- return force ? 'npm audit fix --force' : 'npm audit fix'
+ return force ? ['npm', 'audit', 'fix', '--force'] : ['npm', 'audit', 'fix']
}
}
diff --git a/src/server/services/operationRunner.ts b/src/server/services/operationRunner.ts
index 4196e87..d0474f3 100644
--- a/src/server/services/operationRunner.ts
+++ b/src/server/services/operationRunner.ts
@@ -23,7 +23,7 @@ export const operationEvents = new EventEmitter()
* Runs a shell command and streams output via events
*/
export function runCommand(
- command: string,
+ argv: string[],
cwd: string,
type: Operation['type'],
packageName?: string,
@@ -31,6 +31,7 @@ export function runCommand(
scriptName?: string
): string {
const operationId = generateOperationId()
+ const command = argv.join(' ')
const operation: Operation = {
id: operationId,
@@ -47,23 +48,25 @@ export function runCommand(
// Start operation asynchronously
setImmediate(() => {
- executeCommand(operationId, command, cwd)
+ executeCommand(operationId, argv, cwd)
})
return operationId
}
-async function executeCommand(operationId: string, command: string, cwd: string): Promise {
+async function executeCommand(operationId: string, argv: string[], cwd: string): Promise {
const operation = activeOperations.get(operationId)
if (!operation) return
operation.status = 'running'
+ const [cmd, ...args] = argv
+
// Emit start event
const startEvent: OperationEvent = {
type: 'start',
operationId,
- command,
+ command: operation.command,
operationType: operation.type,
packageName: operation.packageName,
scriptName: operation.scriptName,
@@ -71,11 +74,6 @@ async function executeCommand(operationId: string, command: string, cwd: string)
}
operationEvents.emit('event', startEvent)
- // Parse command into parts
- const parts = command.split(' ')
- const cmd = parts[0]
- const args = parts.slice(1)
-
let childProcess: ChildProcess
try {
diff --git a/src/server/services/packageManager.ts b/src/server/services/packageManager.ts
index d45cd74..eda2a74 100644
--- a/src/server/services/packageManager.ts
+++ b/src/server/services/packageManager.ts
@@ -45,15 +45,15 @@ export function getInstallCommand(
export function getUninstallCommand(
pm: PackageManager,
packageName: string
-): string {
+): string[] {
switch (pm) {
case 'pnpm':
- return `pnpm remove ${packageName}`
+ return ['pnpm', 'remove', packageName]
case 'yarn':
- return `yarn remove ${packageName}`
+ return ['yarn', 'remove', packageName]
case 'npm':
default:
- return `npm uninstall ${packageName}`
+ return ['npm', 'uninstall', packageName]
}
}
@@ -64,34 +64,34 @@ export function getUpdateCommand(
pm: PackageManager,
packageName: string,
version?: string
-): string {
+): string[] {
const pkg = version ? `${packageName}@${version}` : `${packageName}@latest`
switch (pm) {
case 'pnpm':
- return `pnpm add ${pkg}`
+ return ['pnpm', 'add', pkg]
case 'yarn':
- return `yarn add ${pkg}`
+ return ['yarn', 'add', pkg]
case 'npm':
default:
- return `npm install ${pkg}`
+ return ['npm', 'install', pkg]
}
}
/**
* Returns a command to update all given packages to latest
*/
-export function getUpdateAllCommand(pm: PackageManager, packageNames: string[]): string {
- const pkgs = packageNames.map((name) => `${name}@latest`).join(' ')
+export function getUpdateAllCommand(pm: PackageManager, packageNames: string[]): string[] {
+ const pkgs = packageNames.map((name) => `${name}@latest`)
switch (pm) {
case 'pnpm':
- return `pnpm add ${pkgs}`
+ return ['pnpm', 'add', ...pkgs]
case 'yarn':
- return `yarn add ${pkgs}`
+ return ['yarn', 'add', ...pkgs]
case 'npm':
default:
- return `npm install ${pkgs}`
+ return ['npm', 'install', ...pkgs]
}
}
From d2ef8314fd1e39122d9d05b61094457021420526 Mon Sep 17 00:00:00 2001
From: njevric
Date: Wed, 13 May 2026 00:43:23 +0200
Subject: [PATCH 9/9] chore: updated package version and readme/changelog
---
CHANGELOG.md | 20 ++++++++++++++++++++
README.md | 4 ++++
package.json | 2 +-
3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9db075d..a7c2571 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## [1.7.0] — 2026-05-13
+
+### Added
+- **Unused dependency detection** — powered by `depcheck`; surfaces packages listed in `package.json` that are not imported anywhere in the project, shown in a dedicated panel
+- **Smart filters panel** — contextual filter chips that adapt to the current package list (e.g. unused, outdated, dev-only)
+
+### Fixed
+- CodeQL static-analysis alert
+
+---
+
+## [1.5.0] — 2026-05-12
+
+### Added
+- **Script runner** — dedicated Scripts view for running any `package.json` script from the browser with live streaming output and per-script run history
+- **Dark mode** — system-aware theme with manual toggle; preference persisted across sessions
+- **CI / CodeQL workflows** — GitHub Actions pipeline for lint, typecheck, and build; CodeQL security scanning on every push and PR
+
+---
+
## [1.3.3] — 2026-05-10
### Added
diff --git a/README.md b/README.md
index f613d1a..d58ef59 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,10 @@ Run `packy` in any Node.js project to open a fully responsive dashboard for inst
- **Activity feed** — timeline of recent installs, updates, removals, and audits across sessions
- **Real-time streaming** — command output streamed live to the browser via SSE
- **Smart filtering** — search packages by name, filter by type (all / outdated / dependencies / devDependencies)
+- **Unused dependency detection** — powered by `depcheck`; highlights packages declared in `package.json` but not imported in the project
+- **Smart filters panel** — contextual filter chips that surface the most relevant package subsets at a glance
+- **Script runner** — run any `package.json` script from the browser with live output streaming and per-script run history
+- **Dark mode** — system-aware theme with a manual toggle; preference persisted across sessions
- **Fully responsive** — works on mobile, tablet, and desktop
## Requirements
diff --git a/package.json b/package.json
index c9c6dc4..bf12bf1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "packydash",
- "version": "1.3.3",
+ "version": "1.7.0",
"description": "Modern UI for managing npm dependencies and packages",
"type": "module",
"main": "dist/server/index.js",