aboutsummaryrefslogtreecommitdiff
path: root/front-end
diff options
context:
space:
mode:
Diffstat (limited to 'front-end')
-rw-r--r--front-end/package-lock.json370
-rw-r--r--front-end/package.json6
-rw-r--r--front-end/src/buttons.scss10
-rw-r--r--front-end/src/components/Bookmarks.vue1
-rw-r--r--front-end/src/components/Boomarks/AddOrUpdateForm.vue118
-rw-r--r--front-end/src/components/Settings.vue8
-rw-r--r--front-end/src/components/Settings/Bookmarks.vue84
-rw-r--r--front-end/src/components/Settings/PkiSettings.vue5
-rw-r--r--front-end/src/components/Settings/Registation.vue2
-rw-r--r--front-end/src/main.ts4
-rw-r--r--front-end/src/store/bookmarks.ts4
-rw-r--r--front-end/src/store/socialMfaPlugin.ts74
-rw-r--r--front-end/src/store/websiteLookup.ts76
13 files changed, 453 insertions, 309 deletions
diff --git a/front-end/package-lock.json b/front-end/package-lock.json
index 9231ae5..856b959 100644
--- a/front-end/package-lock.json
+++ b/front-end/package-lock.json
@@ -10,7 +10,7 @@
"license": "agpl3",
"dependencies": {
"@headlessui/vue": "^1.7.17",
- "@vnuge/vnlib.browser": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/eb9752ab262522271ccaf1ff127658b7202289a4/@vnuge-vnlib.browser/release.tgz",
+ "@vnuge/vnlib.browser": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/f2ac807486a00db4ba8486133d567e392f0fe98a/@vnuge-vnlib.browser/release.tgz",
"@vuelidate/core": "^2.0.2",
"@vuelidate/validators": "^2.0.2",
"@vueuse/core": "^10.3.x",
@@ -62,9 +62,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.23.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
- "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==",
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz",
+ "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -588,14 +588,14 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz",
- "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true,
"dependencies": {
- "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
+ "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
@@ -611,9 +611,9 @@
}
},
"node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"engines": {
"node": ">=6.0.0"
@@ -625,9 +625,9 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.23",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz",
- "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -686,9 +686,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz",
- "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz",
+ "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==",
"cpu": [
"arm"
],
@@ -699,9 +699,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz",
- "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz",
+ "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==",
"cpu": [
"arm64"
],
@@ -712,9 +712,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz",
- "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz",
+ "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==",
"cpu": [
"arm64"
],
@@ -725,9 +725,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz",
- "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz",
+ "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==",
"cpu": [
"x64"
],
@@ -738,9 +738,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz",
- "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz",
+ "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==",
"cpu": [
"arm"
],
@@ -751,9 +751,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz",
- "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz",
+ "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==",
"cpu": [
"arm64"
],
@@ -764,9 +764,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz",
- "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz",
+ "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==",
"cpu": [
"arm64"
],
@@ -777,9 +777,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz",
- "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz",
+ "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==",
"cpu": [
"riscv64"
],
@@ -790,9 +790,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz",
- "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz",
+ "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==",
"cpu": [
"x64"
],
@@ -803,9 +803,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz",
- "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz",
+ "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==",
"cpu": [
"x64"
],
@@ -816,9 +816,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz",
- "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz",
+ "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==",
"cpu": [
"arm64"
],
@@ -829,9 +829,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz",
- "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz",
+ "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==",
"cpu": [
"ia32"
],
@@ -842,9 +842,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz",
- "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz",
+ "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==",
"cpu": [
"x64"
],
@@ -855,20 +855,20 @@
]
},
"node_modules/@tanstack/virtual-core": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.2.tgz",
- "integrity": "sha512-DATZJs8iejkIUqXZe6ruDAnjFo78BKnIIgqQZrc7CmEFqfLEN/TPD91n4hRfo6hpRB6xC00bwKxv7vdjFNEmOg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.3.tgz",
+ "integrity": "sha512-Y5B4EYyv1j9V8LzeAoOVeTg0LI7Fo5InYKgAjkY1Pu9GjtUwX/EKxNcU7ng3sKr99WEf+bPTcktAeybyMOYo+g==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/vue-virtual": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.1.2.tgz",
- "integrity": "sha512-RmUnhsFtRw9p4Ti/+rG2Hr3y4yFhs8Xdsn7x9tkPoKINbVya/5RSCoNUCCAg2iXNjOI5a55iBNzNV0SVwxMwKA==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.1.3.tgz",
+ "integrity": "sha512-OoRCSgp8Bc85Te3pg4OHFUukbWZeB25/O5rNd7MgMtrYIfJjNOaicZeJcvwqK6lDVTMpzohWUMVK/loqR1H8ig==",
"dependencies": {
- "@tanstack/virtual-core": "3.1.2"
+ "@tanstack/virtual-core": "3.1.3"
},
"funding": {
"type": "github",
@@ -930,8 +930,8 @@
},
"node_modules/@vnuge/vnlib.browser": {
"version": "0.1.13",
- "resolved": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/eb9752ab262522271ccaf1ff127658b7202289a4/@vnuge-vnlib.browser/release.tgz",
- "integrity": "sha512-yqJXL0H8g27KoCijlPXSG75ZxfWab4cFVdT2t2b+iodpHeytZHemlNteTubzMurA8WRg95WW3Z3mf5R184UnZA==",
+ "resolved": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/f2ac807486a00db4ba8486133d567e392f0fe98a/@vnuge-vnlib.browser/release.tgz",
+ "integrity": "sha512-j3BwCdXWJ46Q7GohS+rZg7M5k1/AS+uuycP7wY8RWI2YBKS80uTE6jbWZ0OuCybclBrCufvW7SlTTpfsbf33mw==",
"license": "MIT",
"peerDependencies": {
"@vueuse/core": "^10.x",
@@ -940,8 +940,7 @@
"jose": "^5.x",
"lodash-es": "^4.x",
"universal-cookie": "^7.0.x",
- "vue": "^3.x",
- "vue-router": "^4.x"
+ "vue": "^3.x"
}
},
"node_modules/@volar/language-core": {
@@ -973,49 +972,49 @@
}
},
"node_modules/@vue/compiler-core": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz",
- "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
+ "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
"dependencies": {
"@babel/parser": "^7.23.9",
- "@vue/shared": "3.4.19",
+ "@vue/shared": "3.4.21",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-dom": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz",
- "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz",
+ "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==",
"dependencies": {
- "@vue/compiler-core": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-core": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/compiler-sfc": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz",
- "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz",
+ "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==",
"dependencies": {
"@babel/parser": "^7.23.9",
- "@vue/compiler-core": "3.4.19",
- "@vue/compiler-dom": "3.4.19",
- "@vue/compiler-ssr": "3.4.19",
- "@vue/shared": "3.4.19",
+ "@vue/compiler-core": "3.4.21",
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/compiler-ssr": "3.4.21",
+ "@vue/shared": "3.4.21",
"estree-walker": "^2.0.2",
- "magic-string": "^0.30.6",
- "postcss": "^8.4.33",
+ "magic-string": "^0.30.7",
+ "postcss": "^8.4.35",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-ssr": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz",
- "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz",
+ "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==",
"dependencies": {
- "@vue/compiler-dom": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/devtools-api": {
@@ -1073,48 +1072,48 @@
}
},
"node_modules/@vue/reactivity": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz",
- "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz",
+ "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
"dependencies": {
- "@vue/shared": "3.4.19"
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-core": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz",
- "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+ "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
"dependencies": {
- "@vue/reactivity": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/reactivity": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-dom": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz",
- "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+ "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
"dependencies": {
- "@vue/runtime-core": "3.4.19",
- "@vue/shared": "3.4.19",
+ "@vue/runtime-core": "3.4.21",
+ "@vue/shared": "3.4.21",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz",
- "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+ "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
"dependencies": {
- "@vue/compiler-ssr": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-ssr": "3.4.21",
+ "@vue/shared": "3.4.21"
},
"peerDependencies": {
- "vue": "3.4.19"
+ "vue": "3.4.21"
}
},
"node_modules/@vue/shared": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
- "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
+ "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g=="
},
"node_modules/@vuelidate/core": {
"version": "2.0.3",
@@ -1201,13 +1200,13 @@
}
},
"node_modules/@vueuse/core": {
- "version": "10.8.0",
- "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.8.0.tgz",
- "integrity": "sha512-G9Ok9fjx10TkNIPn8V1dJmK1NcdJCtYmDRyYiTMUyJ1p0Tywc1zmOoCQ2xhHYyz8ULBU4KjIJQ9n+Lrty74iVw==",
+ "version": "10.9.0",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz",
+ "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==",
"dependencies": {
"@types/web-bluetooth": "^0.0.20",
- "@vueuse/metadata": "10.8.0",
- "@vueuse/shared": "10.8.0",
+ "@vueuse/metadata": "10.9.0",
+ "@vueuse/shared": "10.9.0",
"vue-demi": ">=0.14.7"
},
"funding": {
@@ -1240,17 +1239,17 @@
}
},
"node_modules/@vueuse/metadata": {
- "version": "10.8.0",
- "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.8.0.tgz",
- "integrity": "sha512-Nim/Vle5OgXcXhAvGOgkJQXB1Yb+Kq/fMbLuv3YYDYbiQrwr39ljuD4k9fPeq4yUyokYRo2RaNQmbbIMWB/9+w==",
+ "version": "10.9.0",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz",
+ "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
- "version": "10.8.0",
- "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.8.0.tgz",
- "integrity": "sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==",
+ "version": "10.9.0",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz",
+ "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==",
"dependencies": {
"vue-demi": ">=0.14.7"
},
@@ -1377,9 +1376,9 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/autoprefixer": {
- "version": "10.4.17",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
- "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==",
+ "version": "10.4.18",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
+ "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==",
"dev": true,
"funding": [
{
@@ -1396,8 +1395,8 @@
}
],
"dependencies": {
- "browserslist": "^4.22.2",
- "caniuse-lite": "^1.0.30001578",
+ "browserslist": "^4.23.0",
+ "caniuse-lite": "^1.0.30001591",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
@@ -1521,9 +1520,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001589",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz",
- "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==",
+ "version": "1.0.30001597",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz",
+ "integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==",
"dev": true,
"funding": [
{
@@ -1757,9 +1756,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
- "version": "1.4.681",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz",
- "integrity": "sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg==",
+ "version": "1.4.700",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.700.tgz",
+ "integrity": "sha512-40dqKQ3F7C8fbBEmjSeJ+qEHCKzPyrP9SkeIBZ3wSCUH9nhWStrDz030XlDzlhNhlul1Z0fz7TpDFnsIzo4Jtg==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -2254,9 +2253,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
- "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
@@ -2433,9 +2432,9 @@
}
},
"node_modules/jose": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.2.tgz",
- "integrity": "sha512-/WByRr4jDcsKlvMd1dRJnPfS1GVO3WuKyaurJ/vvXcOaUQO8rnNObCQMlv/5uCceVQIq5Q4WLF44ohsdiTohdg==",
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz",
+ "integrity": "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
@@ -2560,9 +2559,9 @@
}
},
"node_modules/magic-string": {
- "version": "0.30.7",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz",
- "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==",
+ "version": "0.30.8",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
+ "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
@@ -3224,9 +3223,9 @@
}
},
"node_modules/rollup": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz",
- "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz",
+ "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -3239,19 +3238,19 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.12.0",
- "@rollup/rollup-android-arm64": "4.12.0",
- "@rollup/rollup-darwin-arm64": "4.12.0",
- "@rollup/rollup-darwin-x64": "4.12.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.12.0",
- "@rollup/rollup-linux-arm64-gnu": "4.12.0",
- "@rollup/rollup-linux-arm64-musl": "4.12.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.12.0",
- "@rollup/rollup-linux-x64-gnu": "4.12.0",
- "@rollup/rollup-linux-x64-musl": "4.12.0",
- "@rollup/rollup-win32-arm64-msvc": "4.12.0",
- "@rollup/rollup-win32-ia32-msvc": "4.12.0",
- "@rollup/rollup-win32-x64-msvc": "4.12.0",
+ "@rollup/rollup-android-arm-eabi": "4.12.1",
+ "@rollup/rollup-android-arm64": "4.12.1",
+ "@rollup/rollup-darwin-arm64": "4.12.1",
+ "@rollup/rollup-darwin-x64": "4.12.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.12.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.12.1",
+ "@rollup/rollup-linux-arm64-musl": "4.12.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.12.1",
+ "@rollup/rollup-linux-x64-gnu": "4.12.1",
+ "@rollup/rollup-linux-x64-musl": "4.12.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.12.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.12.1",
+ "@rollup/rollup-win32-x64-msvc": "4.12.1",
"fsevents": "~2.3.2"
}
},
@@ -3656,9 +3655,9 @@
}
},
"node_modules/typescript": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
- "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz",
+ "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==",
"devOptional": true,
"bin": {
"tsc": "bin/tsc",
@@ -3723,9 +3722,9 @@
"dev": true
},
"node_modules/vite": {
- "version": "5.1.4",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz",
- "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.6.tgz",
+ "integrity": "sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==",
"dev": true,
"dependencies": {
"esbuild": "^0.19.3",
@@ -3778,15 +3777,15 @@
}
},
"node_modules/vue": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz",
- "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz",
+ "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
"dependencies": {
- "@vue/compiler-dom": "3.4.19",
- "@vue/compiler-sfc": "3.4.19",
- "@vue/runtime-dom": "3.4.19",
- "@vue/server-renderer": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/compiler-sfc": "3.4.21",
+ "@vue/runtime-dom": "3.4.21",
+ "@vue/server-renderer": "3.4.21",
+ "@vue/shared": "3.4.21"
},
"peerDependencies": {
"typescript": "*"
@@ -3821,21 +3820,6 @@
"eslint": ">=6.0.0"
}
},
- "node_modules/vue-router": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz",
- "integrity": "sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==",
- "peer": true,
- "dependencies": {
- "@vue/devtools-api": "^6.5.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/posva"
- },
- "peerDependencies": {
- "vue": "^3.2.0"
- }
- },
"node_modules/vue-template-compiler": {
"version": "2.7.16",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
@@ -3864,9 +3848,9 @@
}
},
"node_modules/vue3-otp-input": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.4.1.tgz",
- "integrity": "sha512-wVl9i3DcWlO0C7fBI9V+RIP3crm/1tY72fuhvb3YM2JfbLoYofB96aPl5AgFhA0Cse5bQEMYtIvOeiqW3rfbAw==",
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.4.4.tgz",
+ "integrity": "sha512-LI1MeBiiEy59cnjqXzlcz4G4cMxZcHF/xOKilb6sfw4uFHfQ22Luu2ls0Bb51zL0pb3gGp7RuIL5eurEJXkoBg==",
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
@@ -3996,9 +3980,9 @@
"dev": true
},
"node_modules/yaml": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.0.tgz",
- "integrity": "sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
+ "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
"dev": true,
"bin": {
"yaml": "bin.mjs"
diff --git a/front-end/package.json b/front-end/package.json
index 30accd8..0631eae 100644
--- a/front-end/package.json
+++ b/front-end/package.json
@@ -14,11 +14,13 @@
"dev": "vite",
"watch": "vite build --watch --mode development --minify false",
"build": "vite build",
- "preview": "vite preview"
+ "preview": "vite preview",
+ "update": "npm update",
+ "oudated": "npm outdated"
},
"dependencies": {
"@headlessui/vue": "^1.7.17",
- "@vnuge/vnlib.browser": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/eb9752ab262522271ccaf1ff127658b7202289a4/@vnuge-vnlib.browser/release.tgz",
+ "@vnuge/vnlib.browser": "https://www.vaughnnugent.com/public/resources/software/builds/Plugins.Essentials/f2ac807486a00db4ba8486133d567e392f0fe98a/@vnuge-vnlib.browser/release.tgz",
"@vuelidate/core": "^2.0.2",
"@vuelidate/validators": "^2.0.2",
"@vueuse/core": "^10.3.x",
diff --git a/front-end/src/buttons.scss b/front-end/src/buttons.scss
index 7088deb..44df2c2 100644
--- a/front-end/src/buttons.scss
+++ b/front-end/src/buttons.scss
@@ -1,5 +1,13 @@
.btn{
- @apply focus:ring-2 focus:outline-none font-medium rounded text-sm px-4 py-2 text-center text-white;
+ @apply focus:ring-2 focus:outline-none font-medium rounded text-sm px-2.5 py-2 text-center text-white;
+
+ &.sm{
+ @apply text-xs px-2 py-1;
+ }
+
+ &.lg{
+ @apply text-lg px-4 py-3;
+ }
&.round{
@apply rounded-full;
diff --git a/front-end/src/components/Bookmarks.vue b/front-end/src/components/Bookmarks.vue
index cc3cd6a..274b0b4 100644
--- a/front-end/src/components/Bookmarks.vue
+++ b/front-end/src/components/Bookmarks.vue
@@ -387,7 +387,6 @@ const upload = (() => {
<span class="sr-only">Search</span>
</button>
</form>
-
</div>
<div class="relative ml-3 md:ml-10">
diff --git a/front-end/src/components/Boomarks/AddOrUpdateForm.vue b/front-end/src/components/Boomarks/AddOrUpdateForm.vue
index a4a3f1d..0370e0c 100644
--- a/front-end/src/components/Boomarks/AddOrUpdateForm.vue
+++ b/front-end/src/components/Boomarks/AddOrUpdateForm.vue
@@ -1,6 +1,8 @@
<script setup lang="ts">
import { computed, toRefs } from 'vue';
-import { join, split } from 'lodash-es';
+import { isEmpty, join, split } from 'lodash-es';
+import { useStore } from '../../store';
+import { useWait } from '@vnuge/vnlib.browser';
const emit = defineEmits(['submit'])
const props = defineProps<{
@@ -15,54 +17,110 @@ const tags = computed({
set: (value:string) => v$.value.Tags.$model = split(value, ',')
})
+const { websiteLookup:lookup } = useStore()
+const { setWaiting, waiting } = useWait()
+
+const execLookup = async () => {
+ //url must be valid before searching
+ if(v$.value.Url.$invalid) return
+
+ setWaiting(true)
+
+ try{
+ const { title, description, keywords } = await lookup.execLookup(v$.value.Url.$model);
+
+ //Set the title and description
+ if(title){
+ v$.value.Name.$model = title;
+ v$.value.Name.$dirty = true;
+ }
+
+ if(description){
+ v$.value.Description.$model = description;
+ v$.value.Description.$dirty = true;
+ }
+
+ if(!isEmpty(keywords)){
+ v$.value.Tags.$model = keywords;
+ v$.value.Tags.$dirty = true;
+ }
+ }
+ catch(e){
+ //Mostly ignore errors
+ console.error(e)
+ }
+ finally{
+ setWaiting(false)
+ }
+}
+
+const showSearchButton = computed(() => lookup.isSupported && !isEmpty(v$.value.Url.$model))
+
</script>
<template>
- <form class="grid grid-cols-1 gap-4 p-4" @submit.prevent="emit('submit')">
+ <form id="bm-add-or-update-form" class="grid grid-cols-1 gap-4 p-4" @submit.prevent="emit('submit')">
<fieldset>
- <label for="url" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">URL</label>
- <input type="text" id="url" class="input" placeholder="https://www.example.com"
- v-model="v$.Url.$model"
- :class="{'dirty': v$.Url.$dirty, 'error': v$.Url.$invalid}"
- required
- >
+ <label for="url" class="flex justify-between mb-2 text-sm font-medium text-gray-900 dark:text-white">
+ URL
+ </label>
+ <div class="flex gap-2">
+ <input type="text" id="url" class="input" placeholder="https://www.example.com" v-model="v$.Url.$model"
+ :class="{'dirty': v$.Url.$dirty, 'error': v$.Url.$invalid}" required>
+
+ <div class="">
+ <button
+ type="button"
+ :disabled="!showSearchButton || waiting"
+ @click.self.prevent="execLookup"
+ id="search-btn"
+ class="btn blue search-btn"
+ >
+ <svg class="w-4 h-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
+ viewBox="0 0 20 20">
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
+ d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
+ </svg>
+ </button>
+ </div>
+ </div>
</fieldset>
<fieldset>
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Title</label>
- <input type="text" id="Name" class="input" placeholder="Hello World"
- v-model="v$.Name.$model"
- :class="{'dirty': v$.Name.$dirty, 'error': v$.Name.$invalid}"
- required
- >
+ <input type="text" id="Name" class="input" placeholder="Hello World" v-model="v$.Name.$model"
+ :class="{'dirty': v$.Name.$dirty, 'error': v$.Name.$invalid}" required>
</fieldset>
- <fieldset>
+ <fieldset>
<label for="tags" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Tags</label>
- <input type="text" id="tags" class="input" placeholder="tag1,tag2,tag3"
- v-model="tags"
- :class="{'dirty': v$.Tags.$dirty, 'error': v$.Tags.$invalid}"
- >
+ <input type="text" id="tags" class="input" placeholder="tag1,tag2,tag3" v-model="tags"
+ :class="{'dirty': v$.Tags.$dirty, 'error': v$.Tags.$invalid}">
</fieldset>
<fieldset>
- <label for="description" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label>
+ <label for="description"
+ class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label>
<textarea type="text" id="description" rows="5" class="input" placeholder="This is a bookmark"
v-model="v$.Description.$model"
- :class="{'dirty': v$.Description.$dirty, 'error': v$.Description.$invalid}"
- />
+ :class="{'dirty': v$.Description.$dirty, 'error': v$.Description.$invalid}" />
</fieldset>
-
+
<div class="flex justify-end">
- <button type="submit" class="btn blue">
- Submit
+ <button id="save-button" type="submit" form="bm-add-or-update-form" class="btn blue">
+ Save
</button>
</div>
</form>
</template>
-<style scoped lang="scss">input.search {
- @apply ps-10 p-2.5 border block w-full text-sm rounded;
- @apply bg-gray-50 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 border-gray-300 text-gray-900 focus:ring-blue-500 focus:border-blue-500;
-}
+<style scoped lang="scss">
+
+#bm-add-or-update-form {
+ .search-btn{
-button.search {
- @apply p-2.5 ms-2 text-sm font-medium text-white bg-blue-700 rounded border border-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
+ @apply my-auto px-3 py-2.5;
+
+ &:disabled{
+ @apply bg-gray-600;
+ }
+ }
}
+
</style> \ No newline at end of file
diff --git a/front-end/src/components/Settings.vue b/front-end/src/components/Settings.vue
index 83d3f79..504f38a 100644
--- a/front-end/src/components/Settings.vue
+++ b/front-end/src/components/Settings.vue
@@ -19,7 +19,7 @@ const darkMode = useDark();
<h2 class="text-2xl font-bold">Settings</h2>
<div class="flex flex-col w-full max-w-3xl gap-10 mt-3">
- <div class="">
+ <div class="mb-6">
<h3 class="text-xl font-bold">
General
</h3>
@@ -41,7 +41,7 @@ const darkMode = useDark();
</div>
</div>
- <div class="">
+ <div class="mb-6">
<h3 class="text-xl font-bold">Boomarks</h3>
<div class="relative mt-4">
@@ -51,7 +51,7 @@ const darkMode = useDark();
<PasswordReset />
- <div class="">
+ <div class="mb-8">
<h3 class="text-xl font-bold">Multi Factor Auth</h3>
<div class="relative mt-4 py-2.5">
@@ -66,7 +66,7 @@ const darkMode = useDark();
<Oauth2Apps />
</div>
- <div v-if="store.registation.status?.can_invite" class="mb-10">
+ <div v-if="store.registation.status?.can_invite" class="mt-6 mb-10">
<Registation />
</div>
diff --git a/front-end/src/components/Settings/Bookmarks.vue b/front-end/src/components/Settings/Bookmarks.vue
index a4ab55a..aa4ed31 100644
--- a/front-end/src/components/Settings/Bookmarks.vue
+++ b/front-end/src/components/Settings/Bookmarks.vue
@@ -1,13 +1,14 @@
<script setup lang="ts">
import { apiCall, useWait } from '@vnuge/vnlib.browser';
import { useStore, type DownloadContentType, TabId } from '../../store';
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue'
-const { bookmarks } = useStore();
+const { bookmarks, websiteLookup } = useStore();
const downloadAnchor = ref();
const { waiting } = useWait()
+const curlSupported = computed(() => websiteLookup.isSupported);
const downloadBookmarks = (contentType: DownloadContentType) => {
apiCall(async () => {
@@ -58,8 +59,10 @@ javascript: (function() {
</div>
<p class="p-0.5 my-auto text-sm flex flex-row">
<span class="">
- <svg class="w-6 h-5 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
- <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12l4-4m-4 4 4 4"/>
+ <svg class="w-6 h-5 text-gray-800 dark:text-white" aria-hidden="true"
+ xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
+ d="M5 12h14M5 12l4-4m-4 4 4 4" />
</svg>
</span>
<span>
@@ -72,47 +75,66 @@ javascript: (function() {
<MenuButton :disabled="waiting" class="flex items-center gap-3 btn light">
<div class="hidden lg:inline">Download</div>
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none">
- <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 13V4M7 14H5a1 1 0 0 0-1 1v4c0 .6.4 1 1 1h14c.6 0 1-.4 1-1v-4c0-.6-.4-1-1-1h-2m-1-5-4 5-4-5m9 8h0"/>
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
+ d="M12 13V4M7 14H5a1 1 0 0 0-1 1v4c0 .6.4 1 1 1h14c.6 0 1-.4 1-1v-4c0-.6-.4-1-1-1h-2m-1-5-4 5-4-5m9 8h0" />
</svg>
</MenuButton>
- <transition
- enter-active-class="transition duration-100 ease-out"
- enter-from-class="transform scale-95 opacity-0"
- enter-to-class="transform scale-100 opacity-100"
+ <transition enter-active-class="transition duration-100 ease-out"
+ enter-from-class="transform scale-95 opacity-0" enter-to-class="transform scale-100 opacity-100"
leave-active-class="transition duration-75 ease-out"
- leave-from-class="transform scale-100 opacity-100"
- leave-to-class="transform scale-95 opacity-0"
- >
- <MenuItems class="absolute z-10 bg-white divide-y divide-gray-100 rounded-b shadow right-2 lg:left-0 min-w-32 lg:end-0 dark:bg-gray-700">
- <ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
+ leave-from-class="transform scale-100 opacity-100" leave-to-class="transform scale-95 opacity-0">
+ <MenuItems
+ class="absolute z-10 bg-white divide-y divide-gray-100 rounded-b shadow right-2 lg:left-0 min-w-32 lg:end-0 dark:bg-gray-700">
+ <ul class="py-2 text-sm text-gray-700 dark:text-gray-200"
+ aria-labelledby="dropdownDefaultButton">
<!-- Use the `active` state to conditionally style the active item. -->
<MenuItem as="template" v-slot="{ }">
- <li>
- <button @click="downloadBookmarks('text/html')" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
- HTML
- </button>
- </li>
+ <li>
+ <button @click="downloadBookmarks('text/html')"
+ class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
+ HTML
+ </button>
+ </li>
</MenuItem>
<MenuItem as="template" v-slot="{ }">
- <li>
- <button @click="downloadBookmarks('text/csv')" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
- CSV
- </button>
- </li>
+ <li>
+ <button @click="downloadBookmarks('text/csv')"
+ class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
+ CSV
+ </button>
+ </li>
</MenuItem>
- <MenuItem as="template" v-slot="{ }">
- <li>
- <button @click="downloadBookmarks('application/json')" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
- JSON
- </button>
- </li>
+ <MenuItem as="template" v-slot="{ }">
+ <li>
+ <button @click="downloadBookmarks('application/json')"
+ class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
+ JSON
+ </button>
+ </li>
</MenuItem>
</ul>
</MenuItems>
</transition>
</Menu>
</div>
+ <div class="mt-3">
+ <h4 class="mb-2 font-bold">Features</h4>
+ <p class="text-sm text-gray-500 dark:text-gray-400">
+ Some features for Simple-Bookmark use tools and applications that are already installed on
+ your server such as curl.
+ </p>
+ <div class="flex flex-row gap-2 mt-4">
+ <span class="w-3 h-3 my-auto rounded-full" :class="[curlSupported ? 'bg-green-500' : 'bg-amber-500']"></span>
+ <span class="my-auto font-bold">
+ curl
+ </span>
+ <span class="my-auto text-sm text-gray-500 ms-4 dark:text-gray-400">
+ Curl is used to fetch website details like title, description and tags.
+ {{ curlSupported ? '(supported)' : '(not supported)' }}
+ </span>
+ </div>
+ </div>
</div>
-
+
<a ref="downloadAnchor" class="hidden"></a>
</template> \ No newline at end of file
diff --git a/front-end/src/components/Settings/PkiSettings.vue b/front-end/src/components/Settings/PkiSettings.vue
index dfa4cad..885b2cb 100644
--- a/front-end/src/components/Settings/PkiSettings.vue
+++ b/front-end/src/components/Settings/PkiSettings.vue
@@ -32,6 +32,8 @@ const removeKey = async (key: PkiPublicKey) => {
title: 'Key Removed',
text: `${key.kid} has been successfully removed`
})
+
+ store.mfaRefreshMethods()
})
}
@@ -117,7 +119,8 @@ const onAddKey = async () => {
text: result
})
- hideAddKeyDialog()
+ hideAddKeyDialog();
+ store.mfaRefreshMethods();
})
}
diff --git a/front-end/src/components/Settings/Registation.vue b/front-end/src/components/Settings/Registation.vue
index a0f208e..d0dfaa7 100644
--- a/front-end/src/components/Settings/Registation.vue
+++ b/front-end/src/components/Settings/Registation.vue
@@ -58,7 +58,7 @@ const onCancel = () => {
<div class="">
<div class="flex flex-row justify-between w-full">
- <h3 class="text-xl font-bold">Registation</h3>
+ <h3 class="text-xl font-bold">Invite Links</h3>
<div class="flex flex-row justify-end">
<button class="btn blue" @click="toggleOpen(true)">Invite User</button>
diff --git a/front-end/src/main.ts b/front-end/src/main.ts
index c5be406..2f2ca8e 100644
--- a/front-end/src/main.ts
+++ b/front-end/src/main.ts
@@ -30,6 +30,7 @@ import { mfaSettingsPlugin } from './store/mfaSettingsPlugin'
import { socialMfaPlugin } from './store/socialMfaPlugin'
import { bookmarkPlugin } from './store/bookmarks'
import { registationPlugin } from './store/registation';
+import { siteLookupPlugin } from './store/websiteLookup';
//Setup the vnlib api
configureApi({
@@ -67,9 +68,10 @@ store.use(profilePlugin('/account/profile'))
//Enable mfa with totp settings plugin (optional pki config)
.use(mfaSettingsPlugin('/account/mfa', '/account/pki'))
//Setup social mfa plugin
- .use(socialMfaPlugin())
+ .use(socialMfaPlugin("/account/social/portals"))
//Add the oauth2 apps plugin
.use(bookmarkPlugin('/bookmarks'))
+ .use(siteLookupPlugin('/lookup', 2000))
.use(registationPlugin('/register'))
//Setup oauth apps plugin (disabled for now)
//.use(oauth2AppsPlugin('/oauth/apps', '/oauth/scopes'))
diff --git a/front-end/src/store/bookmarks.ts b/front-end/src/store/bookmarks.ts
index 2af8344..2d12a9a 100644
--- a/front-end/src/store/bookmarks.ts
+++ b/front-end/src/store/bookmarks.ts
@@ -18,7 +18,7 @@ import { MaybeRef, shallowRef, watch, computed, Ref, ref } from 'vue';
import { apiCall, useAxios, WebMessage } from '@vnuge/vnlib.browser';
import { useToggle, get, set, useOffsetPagination, watchDebounced, syncRef } from '@vueuse/core';
import { PiniaPluginContext, PiniaPlugin, storeToRefs } from 'pinia'
-import { isArray, join, map, split, sortBy } from 'lodash-es';
+import { isArray, join, map, split, sortBy, filter, isEmpty } from 'lodash-es';
import { useQuery } from './index';
export interface Bookmark{
@@ -189,7 +189,7 @@ const searchQuery = (search: Ref<string | null>, tags: Ref<string[]>) => {
const tagQuery = useQuery('t')
const currentTags = computed({
- get: () => split(tagQuery.value, ' '),
+ get: () => filter(split(tagQuery.value, ' '), p => !isEmpty(p)),
set: (value) => set(tagQuery, join(value, ' '))
})
diff --git a/front-end/src/store/socialMfaPlugin.ts b/front-end/src/store/socialMfaPlugin.ts
index d8d7bb1..e0ec972 100644
--- a/front-end/src/store/socialMfaPlugin.ts
+++ b/front-end/src/store/socialMfaPlugin.ts
@@ -1,26 +1,19 @@
-// Copyright (C) 2024 Vaughn Nugent
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'pinia'
import { MaybeRef } from 'vue';
-import { useSocialOauthLogin, useUser, SocialOAuthPortal, fromPortals, useAxios } from '@vnuge/vnlib.browser'
+import {
+ useUser,
+ useOauthLogin,
+ useSocialDefaultLogout,
+ fetchSocialPortals,
+ fromSocialPortals,
+ fromSocialConnections,
+} from '@vnuge/vnlib.browser'
import { get } from '@vueuse/core';
import { PiniaPluginContext, PiniaPlugin, storeToRefs } from 'pinia'
import { defer } from 'lodash-es';
-type SocialMfaPlugin = ReturnType<typeof useSocialOauthLogin>
+type SocialMfaPlugin = ReturnType<typeof useOauthLogin>
declare module 'pinia' {
export interface PiniaCustomProperties {
@@ -35,43 +28,40 @@ export const socialMfaPlugin = (portalEndpoint?: MaybeRef<string>): PiniaPlugin
const { } = storeToRefs(store)
const { logout } = useUser()
- /**
- * Override the logout function to default to a social logout,
- * if the social logout fails, then we will logout the user
- */
- const setLogoutMethod = (socialOauth: SocialMfaPlugin) => {
- const logoutFunc = socialOauth.logout;
+ //Create social login from available portals
+ const defaultSocial = useSocialDefaultLogout(
+ useOauthLogin([]),
+ logout //fallback to default logout
+ );
- (socialOauth as any).logout = async () => {
- if (await logoutFunc() === false) {
- await logout()
- }
- }
- }
-
- const _loadPromise = new Promise<SocialMfaPlugin>((resolve, reject) => {
+ const _loadPromise = new Promise<SocialMfaPlugin>((resolve, _) => {
- if(get(portalEndpoint) == null) {
- const socialOauth = useSocialOauthLogin([])
- setLogoutMethod(socialOauth)
- return resolve(socialOauth)
+ if (get(portalEndpoint) == null) {
+ return resolve(defaultSocial)
}
+ /*
+ Try to load social methods from server, if it fails, then we will
+ fall back to default
+ */
+
defer(async () => {
+
try {
- //Get axios instance
- const axios = useAxios(null)
- //Get all enabled portals
- const { data } = await axios.get<SocialOAuthPortal[]>(get(portalEndpoint)!);
- //Setup social providers from server portals
- const socialOauth = useSocialOauthLogin(fromPortals(data));
- setLogoutMethod(socialOauth);
+ const portals = await fetchSocialPortals(get(portalEndpoint)!);
+ const social = fromSocialPortals(portals);
+ const methods = fromSocialConnections(social);
+
+ //Create social login from available portals
+ const login = useOauthLogin(methods);
+ const socialOauth = useSocialDefaultLogout(login, logout);
resolve(socialOauth)
} catch (error) {
- reject(error)
+ //Let failure fall back to default
+ resolve(defaultSocial)
}
})
})
diff --git a/front-end/src/store/websiteLookup.ts b/front-end/src/store/websiteLookup.ts
new file mode 100644
index 0000000..560d00f
--- /dev/null
+++ b/front-end/src/store/websiteLookup.ts
@@ -0,0 +1,76 @@
+
+import 'pinia'
+import { MaybeRef, Ref, shallowRef, watch } from 'vue';
+import { WebMessage, apiCall, useAxios } from '@vnuge/vnlib.browser'
+import { get, set } from '@vueuse/core';
+import { PiniaPluginContext, PiniaPlugin, storeToRefs } from 'pinia'
+import { defer, filter, isEmpty, noop } from 'lodash-es';
+
+export interface WebsiteLookupResult {
+ readonly title: string | undefined,
+ readonly description: string | undefined,
+ keywords: string[] | undefined,
+}
+
+export interface LookupApi{
+ isSupported: Ref<boolean>,
+ timeout: Ref<number>,
+ execLookup(url:string): Promise<WebsiteLookupResult>
+}
+
+declare module 'pinia' {
+ export interface PiniaCustomProperties {
+ websiteLookup:{
+ isSupported: boolean,
+ execLookup(url: string): Promise<WebsiteLookupResult>
+ }
+ }
+}
+
+const urlToBase64UrlEncoded = (url: string) => {
+ return btoa(url)
+ .replace(/-/g, '+')
+ .replace(/_/g, '/')
+ .replace(/\./g, '=') //Fix padding
+}
+
+export const siteLookupPlugin = (lookupEndpoint: MaybeRef<string>, to: number): PiniaPlugin => {
+
+ return ({ store }: PiniaPluginContext) => {
+
+ const { loggedIn } = storeToRefs(store)
+ const axios = useAxios(null)
+
+ const isSupported = shallowRef(false)
+ const timeout = shallowRef(to)
+
+ const checkIsSupported = () => {
+ return apiCall(async () => {
+ //Execute test with the 'support' query parameter
+ const { data } = await axios.get<WebMessage>(`${get(lookupEndpoint)}?support`)
+ set(isSupported, data.success)
+ });
+ }
+
+ const execLookup = async (url:string) => {
+ const base64Url = urlToBase64UrlEncoded(url)
+
+ //Execute test with the 'support' query parameter
+ const { data } = await axios.get<WebMessage<WebsiteLookupResult>>(`${get(lookupEndpoint)}?timeout=${get(timeout)}&url=${base64Url}`)
+ const lookup = data.getResultOrThrow();
+ lookup.keywords = filter(lookup.keywords, (k) => !isEmpty(k))
+ return lookup
+ }
+
+ //If login status changes, recheck support
+ watch([loggedIn], ([li]) => li ? defer(checkIsSupported) : noop(), { immediate: true })
+
+ return {
+ websiteLookup: {
+ isSupported,
+ execLookup,
+ timeout
+ } as LookupApi
+ } as any
+ }
+} \ No newline at end of file